webpack是什么?
webpack簡單來說是一個模塊打包機:分析你的項目結(jié)構(gòu)胖翰,找到JavaScript模塊浴捆、圖片以及其它的一些瀏覽器不能直接運行的拓展語(Scss诗力,TypeScript等弟塞,并將其打包為合適的格式以供瀏覽器使用凭峡。
為什么我們要使用webpack拙已?
隨著前端開發(fā)項目功能越來越豐富的需求决记,前端所寫的JavaScript也越來越復雜還有得安裝一大堆依賴,給我們前端開發(fā)帶來越來越多的復雜度倍踪,所以在這個時候webpack就可以幫助我們將開發(fā)復雜度化簡提高開發(fā)效率系宫,同時他還具備以下優(yōu)點
① 模塊化開發(fā)(import,require)建车,讓我們可以把復雜的程序細化為小的文件;
② 預處理(Less扩借,Sass,ES6缤至,TypeScript……)
③ 主流框架腳手架支持(Vue潮罪,React,Angular)
安裝webpack
安裝webpack之前我們得先提前安裝好node.js,因為我們得需要通過使用npm安裝webpack
npm install webpack -g (這是全局安裝)
npm install webpack --save-dev (這是安裝到自己本地的項目)
或者下面這種帶有版本號的安裝
npm install --save-dev webpack@<version>
(這里提示最好是安裝到本地項目里面,因為當你同時開著多個項目的時候可能會出現(xiàn)不同項目需要不同版本的webpack)
-如果你使用 webpack 4+ 版本嫉到,你還需要安裝 CLI
npm install --save-dev webpack-cli
設置webpack-dev-server
在開發(fā)時沃暗,每次更改文件后要運行npm run build 來重新編譯、打包文件何恶,無聊又麻煩孽锥。我們可以設置 webpack-dev-server來讓他自動運行。webpack-dev-server 主要是啟動了一個使用 express 的 Http服務器 细层,它的作用主要是用來伺服資源文件 惜辑。此外這個 Http服務器 和 client 使用了 websocket 通訊協(xié)議,原始文件作出改動后疫赎, webpack-dev-server 會實時的編譯盛撑,但是最后的編譯的文件并沒有輸出到目標文件夾。在webpack.config.js配置文件中增加入口命令可以使文件變化時瀏覽器自動刷新捧搞。
首先要安裝它 npm install webpack-dev-server --save-dev撵彻。然后在package.json文件的scripts部分增加快捷指令:
"scripts": {
"dev": "webpack-dev-server --open --history-api-fallback",
"build": "webpack"
},
webpack的使用
entry與output
//基本結(jié)構(gòu)
module.exports = {
var path = require('path');
context: path.join(__dirname), //這是entry配置項的根目錄(絕對路徑)
entry: "./src/root.js",//打包入口文件,就是打包誰
output: {
path: __dirname + "/dist/",//打包后文件放置的目錄路徑
// publicPath: "發(fā)布項目時在相對路徑前面添加的絕對路徑"
filename: "bundle.js"http://打包后文件的名字
}
}
entry:
寫法一:字符串 ----------打包一個入口文件实牡,如上
寫法二: 數(shù)組 ------------['./a.js', './b.js'] 打包兩個不相依賴的文件陌僵,打包在一起
寫法三:對象----------在多頁面應用中,針對不同的頁面填寫不同的入口文件
entry: {
page1: './a.js',-----可以是一個
page2: ['./as.js', './b.js']-------可以是多個
}
此時如果還像上面那樣子寫output則只會生成一個輸出文件创坞,且后面的打包文件會把前面輸出文件覆蓋碗短,解決方法是在filename中添加一個占位符,區(qū)分不同輸出文件题涨,方法有三種:
1 [name] 就是entry對象的key值偎谁,page1, page2
output: {
filename: '[name]'.js,
path: __dirname + 'src'
}
2 [hash] 每次打包生成的一個hash值,假設為“123asd”纲堵,可以和[name]一起使用
output: {
filename: '[name]-[hash]'.js,
path: __dirname + 'src'
}
多個打包生成文件hash相同,都是“123asd”
loader
module.exports = {
module: {
rules: [
{//js巡雨、jsx
19 test: /\.jsx?$/,
20 exclude:/node_modules/,//排除node_modules中的庫文件,加快編譯速度
21 loader: 'babel',
22 query:{
23 presets:['es2015', 'react']
24 }
25 },
26 {//css
27 test: /\.css$/,
28 loader: ExtractTextPlugin.extract("style", "css")//多個加載器通過!鏈接,可忽略加載器后綴“-loader”
29 },
30 {//sass,還需要安裝node-sass
31 test: /\.scss$/,
32 loader: 'style!css!sass'
33 },
34
35 {//less,還需要安裝less
36 test: /\.less$/,
37 loader: 'style!css!less'
38 },
39 {//url-loader:圖片席函、字體圖標加載器铐望,是對file-loader的上層封裝,支持base64編碼。傳入的size(也有的寫limit) 參數(shù)是告訴它圖片如果不大于 25KB 的話要自動在它從屬的 css 文件中轉(zhuǎn)成 BASE64 字符串.
40 test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
41 loader: 'url?limit=25000&name=[name].[ext]'
42 }
]
},
}
webpack 本身只能處理 JavaScript 模塊茂附,如果要處理其他類型的文件正蛙,就需要使用 loader 進行轉(zhuǎn)換。Loader 可以理解為模塊和資源的轉(zhuǎn)換器营曼,它本身是一個函數(shù)乒验,接受源文件作為參數(shù),返回轉(zhuǎn)換的結(jié)果蒂阱。這樣锻全,我們就可以通過 require 來加載任何類型的模塊或文件狂塘,比如 CoffeeScript、 JSX鳄厌、 LESS 或圖片睹耐。Loader 本身也是運行在 node.js 環(huán)境中的 JavaScript 模塊,它通常會返回一個函數(shù)部翘。大多數(shù)情況下硝训,我們通過 npm 來管理 loader,但是你也可以在項目中自己寫 loader 模塊新思。
一般loader 一般以xxx-loader的方式命名窖梁,xxx代表了這個 loader 要做的轉(zhuǎn)換功能,比如css-loader夹囚。Loader 可以在require()引用模塊的時候添加纵刘,也可以在 webpack 全局配置中進行綁定,還可以通過命令行的方式使用荸哟。例如頁面中要引入樣式文件main.css假哎,我們可以將main.css看成一個模塊,然后css-loader會遍歷 CSS 文件鞍历,然后找到 url() 處理他們舵抹,style-loader 會把原來的 CSS 代碼插入頁面中的一個 style 標簽中。
插件plugins
插件可以完成更多l(xiāng)oader不能完成的任務劣砍。在webpack.config.js中增加config.plugins:
列如webpack插件 html-webpack-plugin惧蛹,就是可以幫你在打包的時候自動給你生成index.html并且?guī)湍阃锩嬉肽愕膉s文件,你就省的自己去手動引入創(chuàng)建了
1 var webpack = require("webpack");
2 var path = require('path');
3 var ExtractTextPlugin = require('extract-text-webpack-plugin');
4 var HtmlWebpackPlugin = require('html-webpack-plugin');
5
6 var config = {
7 //省略entry刑枝、output等
8 plugins:[//給打包輸出的文件加banner
9 new webpack.BannerPlugin("The file is creted by yangmin.--" + new Date()),
10 new webpack.ProvidePlugin({
11 $: "webpack-zepto",
12 }),
13 /*插件:單獨使用style標簽加載css文件*/
14 new ExtractTextPlugin("css/[name].css"),//設置其路徑(路徑相對于path)
15 /*插件:動態(tài)生成html香嗓,在webpack完成前端資源打包以后,自動將打包后的資源路徑和版本號寫入HTML中装畅,達到自動化的效果靠娱。*/
16 new HtmlWebpackPlugin({
17 filename:'view/index-build.html', //生成的html存放路徑,相對于 path
18 template:'src/view/index.html', //html模板路徑
19 inject:true, //允許插件修改哪些內(nèi)容掠兄,包括head與body
20 hash:false, //為靜態(tài)資源生成hash值
21 minify:{ //壓縮HTML文件
22 removeComments:false, //移除HTML中的注釋
23 collapseWhitespace:false //刪除空白符與換行符
24 }
25 })
26 ]
27 };
28 module.export = config;
babel的實現(xiàn)
安裝 npm i -D @babel-preset-env @babel-core babel-loader
@babel-preset-env:可以讓我們靈活設置代碼目標執(zhí)行環(huán)境
@babel-core: babel核心庫
babel-loader: webpack的babel插件像云,讓我們可以在webpack中運行babel
配置.babelrc
{
"presets": ['@babel/preset-env']
}
配置webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {loader: 'babel-loader'}
}]
}
}
在webpack中如何做到長緩存優(yōu)化?
webpack中可以在output中指定chunkhash徽千,并且分離經(jīng)常更新的代碼和框架代碼苫费。通過NameModulesPlugin或HashedModuleIdsPlugin使再次打包文件名不變汤锨。