webpack打包優化

本文將從打包分析,速度優化,體積優化三個方面進行闡述javascript

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

打包分析css

  • 初級分析: webpack內置的stats(構建的統計信息)html

能夠在 package.json 中使用 stats,也能夠在 Node API 中使用 stats
  •  
webpack --config webpack.prod.js --json > stats.json

 

  • 速度分析:speed-measure-webpack-plugin(分析整個打包總耗時&每一個插件和loader的耗時狀況)html5

  •  
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
 const webpackConfig = smp.wrap({   plugins: [     new MyPlugin(),     new MyOtherPlugin()   ] })
  • 體積分析: webpack-bundle-analyzer分析依賴的第三方模塊文件和業務裏面的組件代碼大小java

  •  
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 module.exports = {   plugins: [     new BundleAnalyzerPlugin()   ] }

 

速度優化node

  • 使用高版本的webpack react

webpack4 增長了一個叫mode的配置項  production默認值會提供一系列有效的默認值以便部署應用  optimization.splitChunks老是啓用

 

  • 多進程構建webpack

  • happypack:每次 webapck 解析一個模塊,HappyPack 會將它及它的依賴分配給 worker 線程中web

  •  
exports.plugins = [    new HappyPack({      id: 'jsx',      threads: 4,      loaders: [ 'babel-loader' ]    }),    new HappyPack({      id: 'styles',      threads: 2,      loaders: [ 'style-loader', 'css-loader', 'less-loader' ]    })];
  exports.module.rules = [    {      test: /\.js$/,      use: 'happypack/loader?id=jsx'    },    {      test: /\.less$/,      use: 'happypack/loader?id=styles'    }  ]

 

  • thread-loader:每次 webpack 解析一個模塊,thread- loader 會將它及它的依賴分配給 worker 線程中json

  •  
module.exports = {    module: {      rules: [        {          test: /\.js$/,          include: path.resolve("src"),          use: [          {            loader: "thread-loader"            options: {                workers: 2  // worker的數量,默認是cpu核心數        }        }       }      ]    }}

 

 

  • 多進程並行壓縮代碼

terser-webpack-plugin:開啓parallel參數
  •  
const TerserPlugin = require('terser-webpack-plugin');
 module.exports = {   optimization: {     minimize: true,     minimizer: [       new TerserPlugin({         parallel: true       })     ]   }}

 

  • 預編譯資源模塊

使用DLLPlugin 進行分包,DllReferencePlugin對manifest.json引用,將react,react-dom,redux,react-redux等基礎包和業務基礎包打包成一個文件

  

webpack.dll.config.js文件:

  •  
const path = require('path');const webpack = require('webpack');
  module.exports = {    context: process.cwd,    resolve: {      extensions: ['.js', '.jsx', '.json', '.styl', '.css'],      modules: [__dirname, 'node_modules']    },    entry: {      vendor: [        'react',        'react-dom',        'react-router-dom'      ]    },    output: {      path: path.resolve(__dirname, './dist/lib'),      filename: '[name].js',      library: '[name]'    },    plugins: [      new webpack.DllPlugin({        path: path.resolve(__dirname, '.', '[name]-manifest.json'),        name: '[name]'      })    ]};

 

 

運行 

  •  
webpack --config webpack.dll.config.js --mode production

生成vendor-manifest.json文件

 

webpack.config.js文件:

  •  
module.exports = {   plugins: [    new webpack.DllReferencePlugin({         manifest: require('./vendor-manifest.json')       })   ]}

 

html: 

  •  
<script type="text/javascript" src="./lib/vendor.js"></script>

 

 

  • 基礎庫分離

  • 經過html-webpack-externals-plugin,而後在html裏面直接引入組件庫的cdn連接

  •  
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
  moudles.export = {      plugins: [          new HtmlWebpackExternalsPlugin({              externals: [                  {                      module: 'react',                      entry: '//11.url.cn/now/lib/16.2.0/react.min.js',                      global: 'React'                  },                  {                      module: 'react-dom',                      entry: '//11.url.cn/now/lib/16.2.0/react-dom.min.js',                      global: 'ReactDom'                  }              ]          })      ]}

 

html:

  •  
<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react.min.js"></script><script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react-dom.min.js"></script> 

 

  • 經過webpack4的SplitChunksPlugins(webpack3使用的是commonChunksPlugin)

     

  •  
module.exports = {plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, "./src/pages/search/search.html"),filename: "search.html",chunks: ["vendors", "common", "search"],inject: true,minify: {html5: true,collapseWhitespace: true,preserveLineBreaks: false,minifyCSS: true,minifyJS: true,removeComments: false}})],optimization: {splitChunks: {minSize: 0,cacheGroups: {vendors: {test: /(react|react-dom)/,name: "vendors",chunks: "all",priority: -10},common: {name: "commons",chunks: "all",minChunks: 2,priority: -20}}}}}

 

  • 利用緩存:第一次構建花費正常的時間,第二次構建速度將顯著加快、

 

  • babel-loader開啓緩存

  •  
module: {    rules: [      {        test: /\.js$/,        exclude: 'node_modules',        use: {          loader: 'babel-loader',          options: {            cacheDirectory: true          }        }      }    ]}

 

  • erser-webpack-plugin:開啓緩存

  •  
module.exports = {    optimization: {      minimize: true,      minimizer: [        new TerserPlugin({          cache: true        })      ]    }}

 

  • 使用 cache-loader 或者 hard-source-webpack-plugin

     

  •  
module.exports = {    module: {      rules: [        {          test: /\.js$/,          use: [            'cache-loader',            'babel-loader'          ],          include: path.resolve('src')        }      ]    }}

 

  • 縮小構建目標

 

  • babel-loader不解析node-modules

  •  
exclude: "node-modules"

 

  • 減小文件搜索範圍

    優化 resolve.modules 配置(減小模塊搜索層級)      優化 resolve.mainFields 配置     優化 resolve.extensions 配置     合理使用 alias(模塊別名相對於當前上下文導入)
  •  
 module: {    resolve: {      alias: {        react: path.resolve(__dirname, "./node_modules/react/dist/react.min.js")      },      modules: [path.resolve(__dirname, "node_modules")],      extensions: [".js"],      mainFields: ["main"]    }  }

 

 

體積優化

  • Scope Hoisting 

將全部模塊的代碼按照引⽤順序放在⼀個函數做⽤域裏,而後適當的重命名⼀些變量以防⽌變量名衝突

webpack4  mode 爲 production 默認開啓

plugins:

  •  
new webpack.optimize.ModuleConcatenationPlugin()

 

  •  使用Tree shaking擦除無用的javaScript和css

     

  • 概念:1個模塊可能有多個方法,只要其中的某個方法使用到了,則整個文件都會被打到 bundle ⾥去,tree shaking 就是隻把用到的方法打⼊ bundle ,沒⽤到的方法會在 uglify 階段被擦除掉。

  • 使⽤:webpack production mode的狀況下默認開啓

  • 要求: 必須是 ES6 的語法,CJS的方式不支持

 

  • CSS:purgecss-webpack-plugin 和 mini-css-extract-plugin 配合使用

 

  • 圖片壓縮

配置image-webpack-loade
  •  
loader: "image-webpack-loader"
  • 使用動態polyfill-service或者browserlist

   根據瀏覽器的UA來判斷當前瀏覽器缺失哪些特性,進而進行補強

 

 

 

 

 

 

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索