點(diǎn)我看看~
webpack(4)說復(fù)雜也不復(fù)雜。不復(fù)雜宠纯,核心概念不外乎是entry, output, loader, plugins。webpack4還新增了optimization選項(xiàng)隧哮,用于代碼分割和打包優(yōu)化∮睦眨現(xiàn)在webpack官網(wǎng)文檔已經(jīng)寫的挺棒了。
然鵝焊虏,當(dāng)你真正開始手寫一個(gè)webpack.config.js的時(shí)候淡喜,你就會(huì)發(fā)現(xiàn),要記得東西有點(diǎn)兒多诵闭,還挺復(fù)雜的……
好啦炼团,Ladies and Gentleman,本文講的是手動(dòng)編寫基于vue開發(fā)的webpack4配置疏尿,以下內(nèi)容主要針對(duì)生產(chǎn)環(huán)境瘟芝,開發(fā)環(huán)境的配置于之后奉上。 created by 2018.07.22 润歉。
webpack的核心概念包含以下幾個(gè)模狭,要牢記:
- entry - webpack打包的入口,并非代碼執(zhí)行的入口踩衩;
- output - webpack打包后生成的靜態(tài)資源文件嚼鹉,它是最終會(huì)被html引用的文件;
- loader - 對(duì)于非js的模塊(或說文件)驱富,轉(zhuǎn)化成webpack能夠處理的js文件锚赤;對(duì)于還要進(jìn)一步處理的js文件進(jìn)行加工處理;
- plugins - 參與到整個(gè)webpack打包的過程褐鸥,可與loader結(jié)合使用线脚,提供相應(yīng)/輔助的功能。
Entry:
entry可以是單個(gè)入口,也可以是多入口浑侥。
單個(gè)入口的寫法:
entry: 'a.js' 或 ['a.js', 'b.js']
多個(gè)入口的寫法:
entry: {
a: 'a.js',
b: 'b.js'
}
webpack會(huì)以你給的entry為入口姊舵,根據(jù)dependency graph,挨個(gè)打包寓落,結(jié)合其他相應(yīng)的設(shè)置括丁,最終輸出成頁(yè)面要引用的靜態(tài)資源文件。注意了伶选,這里提到的“結(jié)合其他相應(yīng)的設(shè)置”史飞,很可能是不止一處的設(shè)置。??????
output
output里面的選項(xiàng)主要有(但遠(yuǎn)不止以下):
- filename: '[name].[hash].bundle.js' // [name]和entry里面的name對(duì)應(yīng)
- path: path.resolve(__dirname, 'dist') // 指最終打包生成的目錄
- publicPath: 可以是'./dist/' 或 '/' 或 cdn地址 // 指訪問靜態(tài)資源文件的路徑
- chunkFilename: '[name].chunk.js' // 指用webpack.ensure或import().then()動(dòng)態(tài)加載的文件
loader
loader就是把模塊轉(zhuǎn)換成webpack能夠處理的js文件(如css,scss,vue等非js模塊)仰税,或者對(duì)js模塊本身進(jìn)行再加工(如編譯es6語(yǔ)法等)构资。
loader的寫法好有好幾種,loader一般放在module這個(gè)對(duì)象里的rules里面陨簇,現(xiàn)總結(jié)以下4種:
module: {
rules: [
{ //第一種, 需要用到的loader簡(jiǎn)單的放在use數(shù)組里
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{// 第二種吐绵,use里面是一個(gè)個(gè)對(duì)象,這種方式可以給loader進(jìn)行配置
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
require('autoprefixer')({
browsers: ['iOS >= 7', 'Android >= 4.1']
}),
]
}
}
]
},
{//第三種塞帐,單個(gè)loader和對(duì)象loader一起放在use數(shù)組里
test: /\.(png|jpg|jpeg|gif)$/i
use: [
'file-loader',
{
loader: 'image-webpack-loader',
optiosn: {
pngquant: {
quality: '65-80'
}
}
}
]
},
{//簡(jiǎn)單使用loader拦赠,不用use
test: /\.vue$/,
loader: 'vue-loader'
}
]
}
總結(jié)一下loader的常用四種寫法:
use: [xxx, xxx]
use: [{loader: XXX}, {loader: XXX}]
use: [{
loader: XXX,
options: {}
}, 'XXX']
loader: [XXX, XXX]
loader的options配置項(xiàng)里面還可以放置loader,also plugins ??????
常用的loader有:
- 處理樣式的:style-loader,css-loader,postcss-loader,sass-loader,less-loder
- 處理es6的:babel-loader(要連同babel-core, babel-preset-env)一起用
- 處理圖片的:file-loader, url-loader, image-webpack-loader
Plugins
常用的plugin有:
- 壓縮js:uglifyjs-webpack-plugin
- 合并&壓縮css: mini-css-extract-plugin葵姥,optimize-css-assets-webpack-plugin
- 清除目錄:clean-webpack-plugin
- 生成html:html-webpack-plugin
- postcss相關(guān)的:postcss-plugin-px2rem荷鼠,postcss-preset-env,postcss-sprites榔幸,autoprefixer
- webpack自帶的方法:webpack.ProvidePlugin等
是不是開始覺得要記得東西很多霸世帧?蛤蛤蛤蛤蛤蛤削咆,不要急牍疏,要記得東西遠(yuǎn)不止這些……
以上講的都是些概念和基本配置,結(jié)合起來怎么用呢拨齐?
先上目錄:
因?yàn)橹粚懸粋€(gè)注冊(cè)頁(yè)鳞陨,筆者沒有用vue-cli,選擇用webpack手動(dòng)擼一個(gè)vue的配置瞻惋。
因?yàn)槭莢ue項(xiàng)目厦滤,這里多說兩句。打包編譯vue文件歼狼,需要用到vue-loader掏导,樣式需要用vue-style-loader,那么<template>怎么辦呢羽峰?一定記住加載vue-template-compiler趟咆,雖然它只存在于你的node_modules文件夾中添瓷,但是vue-loader需要用到它,所以務(wù)必記住下載值纱。
另外鳞贷,在loader中設(shè)置了vue-loader之外,還得設(shè)置一個(gè)變量const { VueLoaderPlugin } = require('vue-loader')虐唠,并且在plugins里面創(chuàng)建一個(gè)它的實(shí)例才行悄晃,即new VueLoaderPlugin()。
ps. 系不系感覺復(fù)雜了凿滤?我也布吉島為神馬這些配置要分散在不同地方進(jìn)行配置,這就加劇了webpack配置的復(fù)雜度庶近。翁脆。。鼻种。
在我們書寫配置的時(shí)候反番,一定要清楚自己想要webpack幫助你達(dá)到什么目的,以此來選擇需要的loader和plugin以及其他輔助工具叉钥。
除了上面講到的轉(zhuǎn)化vue模塊外罢缸,我需要webpack幫助我的主要是打包、壓縮js,css,images投队,自動(dòng)生成html文件枫疆,以及每次打包前先刪除已存在的dist目錄。所以上圖中所引入的模塊就是能完成這些功能的工具敷鸦。
這個(gè)是對(duì)html文件進(jìn)行打包壓縮的息楔,它會(huì)把html文件打包壓縮成如下:
上面兩張圖分別在loader和plugins里面用到,它們結(jié)合在一起可以把css樣式文件打包成一個(gè)css靜態(tài)資源文件扒披,通過link標(biāo)簽引入進(jìn)html文檔中值依。
在webpack4中,打包壓縮JS和CSS都可以在optimization這個(gè)對(duì)象里進(jìn)行碟案。
它們分別會(huì)讓你的js和css文件打包壓縮成如下:
另外webpack最顯著的特點(diǎn)愿险,這也是webpack創(chuàng)始人打造它的初衷,就是code splitting价说!既然如此辆亏,我們當(dāng)然要發(fā)揮webpack這個(gè)特點(diǎn),幫助我們優(yōu)化啦熔任!注意哦褒链,code-split是內(nèi)置在webpack里面的方法。在webpack4中疑苔,它在optimization里面配置甫匹,也就是取代了之前的commonsChunkPlugin這個(gè)插件。如下:
另外,runtimeChunk用來單獨(dú)打包壓縮運(yùn)行時(shí)的webpack代碼兵迅。通俗的成為manifest.js
至此抢韭,經(jīng)過npm run build之后,代碼執(zhí)行的入口文件為以下四個(gè):
再讓我們來分析一下打包后的文件大小恍箭,總之我打包后vendor變得很大刻恭,即便uglify了,也有188k扯夭。這可不行鳍贾!這時(shí)候請(qǐng)記住plugin:compression-webpack-plugin。
然后如下圖在plugins里面創(chuàng)建一個(gè)它的實(shí)例:
這樣一來交洗,打包后你生成的文件就會(huì)包含一個(gè)vendor.bundle.js.gz二進(jìn)制格式的壓縮文件骑科。如下圖:
很開熏是不是?但是我們打包后dist/index.html中引用的是vendor.bundle.js构拳,并不是這個(gè).gz的壓縮文件咆爽,怎么辦?
這時(shí)候就需要后端配合修改一下nginx的配置置森,增加gzip_static on斗埂。僅僅有g(shù)zip on是不行滴。
然后你再打開頁(yè)面就會(huì)發(fā)現(xiàn)vendor.bundle.js變成了63.4k凫海。雖然還沒有達(dá)到我的要求呛凶,但是已經(jīng)縮水一半以上了??
補(bǔ)充說一下webpack4“動(dòng)態(tài)引入”的不同,如果要用import().then()這個(gè)動(dòng)態(tài)引入方法盐碱,需要安裝babel-plugin-dynamic-import-webpack這個(gè)插件才行把兔。
總結(jié)一下webpack如何復(fù)雜吧,總體來講就是要記得東西很多瓮顽,有點(diǎn)“無厘頭县好,沒規(guī)律”,具體來說至少包含以下幾個(gè)方面:
- 有些功能用loader就完事了暖混,可有些還要配合著plugins去寫缕贡,沒有統(tǒng)一的規(guī)律遵循,比較雜亂拣播。有些loader本身要配置plugins晾咪,有些loader需要到外面大plugins對(duì)象里進(jìn)行設(shè)置;
- 不同loader和plugins配置項(xiàng)可以很多贮配,不同版本也不一樣(希望以后版本更迭的成本小一些谍倦,給開發(fā)者多一些溫油);
- 像babel這樣的泪勒,要注意不同版本的差別昼蛀,否則會(huì)報(bào)錯(cuò)宴猾。babel-loader, babel-core, babel-preset, babel-polyfill一定要對(duì)應(yīng)著來。并且用了babel-loader并不久完事了叼旋,要去設(shè)置對(duì)應(yīng)的presets告訴babel要把你的es6編譯成啥樣的規(guī)范仇哆,可以寫在options里,也可以在根目錄設(shè)置.babelrc夫植。另外要編譯es方法和函數(shù)還要用到polyfill讹剔,如果是開發(fā)框架則要用另一個(gè)babel-plugin--transform-runtime --save-dev和babel-runtime --save。
總之要記的很多就是了详民。延欠。。
但是呢沈跨,如果能記住這些雜碎的東西衫冻,webpack能幫助你做到不少事!也就覺得沒那么復(fù)雜了谒出。當(dāng)然啦,要弄懂原理是另一回事啦邻奠。??????
good night~