項目二期上線後,相對不辣麼忙,眼看着webpack4也出來快半年了而且日趨穩定,以前雖然寫過demo測試使用,但還未在項目中用過,因而擇日不如撞日一氣呵成開啓了升級【踩坑】之旅css
首先保證 node>= 6.11.5,建議使用8以上LTS版本html
如下是個人項目中使用到的依賴安裝或更新狀況,不一樣項目使用loader、插件不一樣,這部分得根據自身狀況調整
主要依賴:vue
- webpack安裝最新 - webpack-cli安裝(啓動webpack) - webpack-dev-server更新至3以上 - vue-loader更新至15以上 - 安裝mini-css-extract-plugin
其餘:
babel相關依賴、html-webpack-plugin、file-loader、url-loader、sass-loader等我都升級了版本,或者也能夠修改完配置後,運行起來看看控制檯是否有相關報警再更新
輔助:
推薦安裝webpack-bundle-analyzer插件,能夠分析構建結果依賴關係node
接下來來到此次愉快踩坑之旅的重頭戲了!webpack
mode
是webpack4新增的配置項,也是本次更新的亮點之一,簡單理解就是告訴webpack本次構建模式,使其能夠對構建使用對應的優化策略。回想以前寫工程化配置,也會區分開發模式和生產模式的配置入口,webpack4提供了mode
下降了很多配置成本。git
mode
可被設置爲development
(默認)或production
github
module.exports = { mode: 'production' };
development
側重於優化開發體驗,production
側重於優化模塊體積和線上部署,具體優化內容這裏就不搬運官方文檔了,對於個人項目而言比較在乎的有如下幾點:web
process.env.NODE_ENV
爲對應值(development
或production
),原手工配置process.env.NODE_ENV = 'development' ;
的代碼能夠刪除production
模式將自動加入代碼壓縮功能,可刪除原new UglifyJsPlugin()
相關代碼更多說明參考 [https://medium.com/webpack/we...
](https://medium.com/webpack/we...
)vue-router
webpack4根據mode
配置對構建進行優化,也能夠經過覆蓋optimization
配置進一步定製兩種構建模式下的優化策略,而且官方移除了CommonsChunkPlugin
插件。npm
其中項目升級最大的變動就在CommonsChunkPlugin
插件的移除和optimization
下splitChunks
、runtimeChunk
的配置
另外因爲代碼壓縮功能將在production
模式下自動開啓,若是須要對js壓縮或css壓縮策略定製,則須要覆蓋默認optimization.minimizer
配置
關於splitChunks
能夠單獨用一篇文章進行詳細說明,這裏我只是按原項目的緩存策略修改(CommonsChunkPlugin
配置): 抽取/node_modules/下第三方依賴做爲公共vendor(基於第三方依賴更新頻率低)
默認配置下,splitChunks
只對懶加載的模塊產生影響
註釋部分是splitChunks的默認配置,這裏僅修改cacheGroups內vendor相關配置,將chunks改爲'initial'避免將部分異步加載的較大的第三方依賴也合併到vendor中
splitChunks: { //chunks: 'async', //minSize: 30000, //minChunks: 1, //maxAsyncRequests: 5, //maxInitialRequests: 3, //automaticNameDelimiter: '~', //name: true, cacheGroups: { vendor: { name: 'vendor', //@NOTE 配置成all 會把async的也打進來 chunks: 'initial', priority: -10, test: /[\\/]node_modules[\\/]/ } } }
以前的production
模式構建會使用CommonChunkPlugin
抽取runtime code(這部分概念不瞭解的能夠參考https://webpack.js.org/concepts/manifest/#src/components/Sidebar/Sidebar.jsx)做爲單獨的chunk,升級後這部分配置須要寫到optimization.runtimeChunk
中:
false
,runtime code包含在基於各個entry抽取的第一個chunk中(注意:因爲本項目抽取了公用vendor,針對本項目會將全部entry的runtime代碼抽取到公用vendor中,vendor將失去瀏覽器緩存意義) single string
,全部entry的runtime代碼將會抽取爲一個chunk配置成生成函數的代碼:
runtimeChunk: { name: entrypoint => `manifest~${entrypoint.name}` },
這個接收單個對象或對象數組,指定壓縮插件和配置,相對比較簡單,這裏就不詳細描述了
minimizer: [ // 配置UglifyJsPlugin壓縮js文件 new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true }), // 配置css文件壓縮 new OptimizeCSSAssetsPlugin({ cssProcessor: require('cssnano'), cssProcessorOptions: { discardComments: {removeAll: true}, // 避免 cssnano 從新計算 z-index safe: true }, canPrint: false }) ]
webpack4以後,Extract-text-plugin
再也不適用於css文件抽取,若是還要繼續使用安裝時只能經過@next版本安裝(yarn add extract-text-plugin@next),除此以外contenthash
不支持使用在文件名中、會生成一些多餘的chunk css文件
mini-css-extract-plugin
專用於抽取css文件支持async-loading,只能配合webpack4使用,但目前暫時還不支持HMR(Hot Module Replace),本項目只在production
下使用這個插件
配置相對Extract-text-plugin
是簡單一些
// loader部分(項目使用scss) test: /\.(sa|sc|c)ss$/, use: [ isProd ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', { loader: 'sass-loader', options: { ... ... } }, ], }, // plugin部分 plugins.push( new MiniCssExtractPlugin({ filename: isProd ? "css/[name].[contenthash:8].css" : "css/[name].css"; }) );
vue-loader配合webpack4升級到了v15版本,升級以後配置方式發生了一些改變,如下是項目中使用到的部分:
<script></script>
標籤內的js代碼將被視爲獨立的js文件並根據webpack配置使用babel-loader轉譯;項目配置babel-loader時使用exclude: /node_modules/
排除依賴包中代碼的轉譯,若是導入了/node_modules/
中的.vue文件,<script>
部分將不能被轉譯,故須要將.vue文件加入到排除白名單中// 增長一個plugin const VueLoaderPlugin = require('vue-loader/lib/plugin') plugin.push( new VueLoaderPlugin()) // rules loader配置 // @UPDATED // vue-loader v15+版本 .vue文件中的樣式將被抽取出來並認爲和獨立引入的css文件相同 // 故須要配置單獨loader處理 ... ... { test: /\.(sa|sc|c)ss$/, use: [ isProd ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', { loader: 'sass-loader', options: { includePaths: ['src/static/scss'] } }, ], }, // .vue文件 { test: /\.vue$/, loader: 'vue-loader', options: { // @UPDATED @DEPRECATED // v15+版本再也不須要提供內聯的cssloader配置 // 若是不去掉會報錯 // loaders: util.cssLoaders({ // sourceMap: false, // extract: build, // build: build // }) } }, // .js文件 { test: /\.js$/, loader: 'babel-loader', exclude: file => ( // @UPDATED // vue-loader v15+版本 // /node_modules/中的.vue文件須要通過babel-loader轉譯 /node_modules/.test(file) && !/\.vue\.js/.test(file) ) } ... ...
其餘變動能夠參考vue-loader官方文檔說明https://vue-loader.vuejs.org/migrating.html#notable-breaking-changes
項目webpack4配置demo,能夠參考~~
https://github.com/icyfanfan/...
webpack官方文檔
https://medium.com/webpack/we...
https://medium.com/webpack/we...
https://medium.com/webpack/we...
mini-css-extract-plugin
https://github.com/webpack-co...
vue-loader
https://vue-loader.vuejs.org/...