(webpack系列二)webpack打包優化探索
來自專欄大轉轉FE
雖然webpack的已經升級到了webpack4,而我們目前還在使用webpack3,但其中的優化點都大同小異,升級後同樣適用。
性能優化初步原則
- 減小代碼量
- 減小請求數
- 最大化利用瀏覽器緩存
這三條原則永遠是一切優化的前提
優化配置
- 升級
webpack 3
,優化js的編譯能力(Scope Hoisting)
// 主要配置 plugins:[ new webpack.optimize.ModuleConcatenationPlugin() ]
- 合理規劃
entry
入口配置(平衡vendor.js, app.js文件的大小)
// main.js中第三方公共庫提出,作為公共vendor.js, 配合package.json固定第三方庫版本,最大化利用瀏覽器緩存載入js entry: { vendor:[vue, vue-router, vue-resource], app: ./src/main.js } // ... plugins:[ new webpack.optimize.CommonsChunkPlugin({ name: [manifest,vendor].reverse(), minChunks:Infinity }) ]
- 打包後文件大小限制,首次載入js+css超過
400k
,單個文件大小超過300k
將會報錯,打包不通過,該配置在build中使用
performance: { hints: error, maxEntrypointSize: 400000, maxAssetSize: 300000 }
減小代碼量
- 提取
chunk
中使用的公共庫(能為chunk代碼節約近1/3的代碼量)
new webpack.optimize.CommonsChunkPlugin({ name: app, async: vendor-async, children: true, minChunks: (module, count) => { // 被 2 個及以上 chunk 使用的共用模塊提取出來 return count >= 2 } })
- 減少圖片base64的使用,降低限制,限制2k(vue官方配置是10k,會大大增加js文件體積,移動端對base64的解析成本高)
{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: url-loader, options: { limit: 2048, name: utils.assetsPath(img/[name].[hash:7].[ext]) } }
- 生產模式(pro)下第三方庫使用已壓縮版本,能節約近20k文件大小
// 開發模式 resolve: { alias: { vue: vue/dist/vue.esm.js } } // 生產模式 resolve: { alias: { vue: vue/dist/vue.min.js } }
- 優化
babel-ployfill
,結合babel-preset-env
實現兼容按需載入,比使用es2015
能節約近半的大小
entry: { vendor:[babel-polyfill, vue, vue-router, axios], app: ./src/main.js }
// .babelrc { "presets": [ ["env", { "modules": false, "targets": { "browsers": [ "> 1%", "last 3 versions", "Firefox ESR", "not ie < 10" ] }, "debug": false, "useBuiltIns": true }], "react", "stage-2" ] }
- 極致壓縮js,css代碼
var os = require(os) var OptimizeCSSPlugin = require(optimize-css-assets-webpack-plugin) plugins: [ new webpack.optimize.UglifyJsPlugin({ // 利用多核能力壓縮 beautify: { cache: true, workers: os.cpus().length }, // 最緊湊的輸出 beautify: false, // 刪除所有的注釋 comments: false, compress: { // 在UglifyJs刪除沒有用到的代碼時不輸出警告 warnings: false, // 刪除所有的 `console` 語句 drop_console: true, // 內嵌定義了但是只用到一次的變數 collapse_vars: true, // 提取出出現多次但是沒有定義成變數去引用的靜態值 reduce_vars: true, }, sourceMap: true }), new OptimizeCSSPlugin({ cssProcessor: require(cssnano)({ zindex: false }), cssProcessorOptions: { safe: true, discardComments: {removeAll: true } } }) ]
- 第三方庫的依賴過濾,如下:
// 此插件默認全部引入語言庫,但我們只用到了中文,最多英文,所以進行了過濾,大大減少了總體代碼量 plugins: [ new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh|en/) ]
減少請求數
- manifest.js文件內聯(app.css可以自行選擇,當小於10k是最好內聯),webpack推薦配置如下:
// 引入內聯插件 var HtmlWebpackInlineSourcePlugin = require(html-webpack-inline-source-plugin) plugins:[ // ... new HtmlWebpackPlugin({ // ... 其他不相關配置省略 inlineSource:/(app\.(.+)?\.css|manifest\.(.+)?\.js)$/, // ... }), new HtmlWebpackInlineSourcePlugin() ]
最大化利用瀏覽器緩存
這樣能最大化利用瀏覽器緩存
// 不固定版本,會造成打包後 hash 值變化,瀏覽器沒辦法利用本身的緩存載入js,每次上線都會使本地緩存失效,頁面載入變慢 "dependencies": { "moment": "2.17.1", "querystring": "0.2.0", "sprite-cli": "0.1.5", "sticky-state": "2.4.1", "superagent-jsonp": "0.1.1", "underscore": "1.8.3", "vue": "2.0.0", "vue-lazyload": "0.8.3", "vue-router": "2.0.0", "vuex": "2.0.0" }
其他優化
zindex被重置問題+autoprefixer不生效問題
zindex
被重置 由於cssnano
默認配置,是自動會把z-index
重置為1,例如:
classname { z-index:1000; } after classname { z-index:1; }
autoprefixer
不生效 這是由於cssnano
中已經包含autoprefixer
的配置,需要關閉
這時候需要優化cssnano
的配置,.postcssrc
如下:
module.exports = { plugins: { cssnano: { zindex: false, autoprefixer: false } } }
此處需要做特殊說明,發現官方提供的cssnano
的preset
寫法,並不生效
使用按需載入js後,打包代碼特別大
需要注意的是,當使用按需載入的功能,然後沒有提取所有chunk
包里的css
,同時又開啟了sourcemap
功能,那麼就會造成這種情況 最簡單的辦法就是,對css
不使用sourcemap
功能,例如:
rules: [ { loader: postcss-loader, options: { sourceMap: false } } ]
廣告
以下是筆者基於 vue-cli 的模版優化後的vue
和react
的打包工具,用法一致。
以下包集成了以上所有優化,支持單頁面及多頁面應用,完全兼容vue-cli
生成的模版項目
zz-webpack-vue
zz-webpack-react
以下是使用本組一個vue-cli生成的項目做的一個優化對比:
優化前:
優化後:
可以查看具體的優化配置,或者直接在項目中嘗試使用,有任何問題歡迎隨時反饋,目前正在籌劃統一升級webpack4
目前網上提供了各種腳手架,不要太相信這些腳手架的打包配置,其中可優化的點還有很多,根據自己的需要好好做深度優化吧
推薦閱讀:
※setState的函數參數叫啥名好
※從 React 到 Preact 遷移指南
※React 導讀(六)
※如何入門 React?你應該跟著這八步走