webpack優化

​ 原有的vue-cli,create-react-app在項目較大時編譯時間過長,擴展性很差。重寫了一套,優化了構建速度和體積。主要從如下優化了webpackcss

構建速度

  1. 多線程壓縮

    開啓多線程壓縮有多種方式,happy-pack/thread-loader/parallel-webpack等,happy-packwebpack3時很受歡迎,主要是在webpack compile後經過happy-pack建立的線程池分模塊構建,處理後從新傳到主線程,目前官方已經再也不維護,推薦使用的webpack4thread-loader。在webpack解析一個模塊時, thread-loader會將它及它的依賴分配到 worker 線程中,添加thread-loader以下:html

    //1. 安裝依賴
     npm install --save-dev thread-loader (以後方法省略該步驟)
    //2. module中引入
      module: {
              rules: [
                  {
                      test: /\.js$/,
                      include: path.resolve(__dirname, '../src'),
                      //多線程編譯 項目不大不建議使用
                      use: [{
                          loader: 'thread-loader',
                          options: {
                              workers: 3
                          }
                      },
                     	'babel-loader?cacheDirectory=true']
    
                  }
                ]
      }
    
    
    複製代碼
  2. 多進程多實例並行壓縮

    一樣多種方式: parallel-uglify-plugin/ugilfyjs-wepack-plugin/terser-webpack-plugin ,而terser-webpack-plugin支持壓縮ES6語法。使用一樣簡單:vue

    //安裝後添加到optimization中
    
    optimization: {
        minimizer: [
          new TerserPlugin({
            //開啓並行壓縮,true爲默認值,可設數值, 一樣項目小不建議使用,可能反而延長時間
            parallel: true,
            //開啓壓縮緩存
            cache: true
          })
        ],
      },
    複製代碼
  3. 分包

    使用html-webpack-externals-plugin指定引入包CDNnode

    new HtmlWebpackExternalsPlugin({
      externals: [
        {
          module: 'jquery',
          entry: '//unpkg.com/jquery@3.2.1/dist/jquery.min.js',
          global: 'jQuery',
        },
        {
          module: 'react',
          entry: '//unpkg.com/react@16/umd/react.production.min.js',
          global: 'React',
        },
      ],
    })
    複製代碼

    此方法需手動引入,同時會致使頁面打入多個<script>標籤進行引用,對於SplitChunk仍是會對基礎包進行分析。項目不大可使用。推薦使用DLLreact

  4. DLLPlugin預編譯

    這是webpack自帶的神器,此插件專門用於單獨的webpack配置中,以建立dll的捆綁包。它建立一個manifest.json文件,DllReferencePlugin使用它來映射依賴項。webpack詳情jquery

    能夠先建立webpack.dll.js文件,將公共包提出來(如下文件都存在config文件夾,__dirname目錄可能補同)webpack

    const path = require('path')
    const webpack = require('webpack')
    module.exports = {
        entry: {
          	//將一下包打成library文件
            library:[
                'react',
                'react-dom',
                'redux',
                'react-redux',
                'axios'
            ],
        },
        output:{
            filename:'[name]_[hash].js',
          	//路徑不要存在dist中,不然會被cleanwebpackplugin清理
            path: path.join(__dirname,'../build/library'),
            library:'[name]'
        },
        plugins:[
          	//使用dll
            new webpack.DllPlugin({
                name:'[name]_[hash]',
                path: path.join(__dirname,'../build/library/[name].json'),
            })
        ]
    }
    複製代碼

    pack.json中新加一條命令運行:ios

    "dll": "webpack --config ./config/webpack.dll.js",
    複製代碼

    run後會產生build文件夾web

    在原webpack production模式下添加vue-cli

    plugins:[
        new webpack.DllReferencePlugin({
          manifest:require(path.resolve(__dirname,'../build/library/library.json')),
        })
      ]
    複製代碼

    會發現速度提高,同時打包體積變小。此時需在編譯後的html文件中手動添加library文件夾。可以使用copy-webpack-pluginhtml-webpack-tags-plugin實現自動添加:

    plugins:[
    				new HtmlWebpackPlugin(),
            new HtmlWebpackTagsPlugin({
              	//須要引入的文件
                tags: [`${require('../build/library/library.json').name}.js`],
               //加載末尾
                append: false
            }),
        ]
    複製代碼

    注:html-webpack-tags-plugin必須配合html-webpack-plugin,而且在此以後引入。同時,該插件彷佛和speed-measure-webpack-plugin衝突,如果引用了speed-measure-webpack-plugin建議在構建時暫時關閉。

    production配置中添加:

    plugins:[
        new CopyWebpackPlugin([
          //目錄從項目根文件開始,從複製build/lirary文件到當前,須要更多配置可查詢官方
        { from: 'build/library', to: '' },
        ]),
      ]
    複製代碼

    此時運行能夠自動添加文件。

  5. 開啓緩存

    緩存對於二次編譯具備很大的提升。一般有幾種方法:

    • 開啓babel-loaer緩存(直接在babel-loader後添加?cacheDirectory=true方法1中)

    • 開啓terser-webpack-plugin緩存(方法二中)

    • 使用hard-source-webpack-plugin提高模塊轉換階段緩存

      plugins:[
      		// ...
          new HardSourceWebpackPlugin(),
      ]
      複製代碼
  6. 縮小構建目標

    縮小構建目標,減小每次構建文件查找範圍也能提升速度,有如下狀況:

    // 1. 排除或縮小目錄
        module: {
            rules: [
                {
                    test: /\.js$/,
                  	//只在解析src下文件
                  	include: path.resolve(__dirname, '../src'),
                  	//排除 node_module文件夾,一般不須要同時使用。
    								exclude: 'node_module',
                    use: [{
                          loader: 'thread-loader',
                          options: {
                              workers: 3
                          }
                      },
                          'babel-loader?cacheDirectory=true']
                  }
              ]
        	}
    //2.resolve模塊使用
      resolve: {
        //合理使用別名,減小搜索層級
        alias: {
          //import react能夠直接找到
          "react": path.resolve(__dirname, "../node_module/react/dist/react.min.js"),
        },
         modules:[path.resolve(__dirname,"../node_module")]
          //後綴名,如import 'index'時會自動按extensions順序查找,可選多個,但查找速度慢,指定爲一下數組中類型時,其餘類必須寫明後綴,不然沒法找到
         extensions:[.js],
         //packjson指定的入口文件
         mainFeilds:['main'] 
      }      
    複製代碼

構建體積優化

圖片優化

基於Node庫的Imagemin(定製選項,能夠引入第三方優化插件,能夠處理多種圖片格式)

使用:配置image-webpack-loader 快速入口

module:{
   rules:[
     {
       test: /\.(gif|png|jpe?g|svg|blob)$/,
       use: [
         'file-loader',
         {
           loader: 'image-webpack-loader',
           options: {
             mozjpeg: {
               progressive: true,
               quality: 65
             },
             // optipng.enabled: false will disable optipng
             optipng: {
               enabled: false,
             },
             pngquant: {
               quality: '65-90',
               speed: 4
             },
             gifsicle: {
               interlaced: false,
             },
             // the webp option will enable WEBP
             webp: {
               quality: 75
             }
           }
         },
       ],
     },
   ]
 }
複製代碼

Mac OS 可能因爲libpng錯誤,官方建議安裝或更新libpng

brew install libpng
複製代碼

若還有錯誤,可能因爲node引發

node rebuild
複製代碼

從新編譯可能時間長

CSSTreeShaking

webpack3中使用purifyCSS,已經中止維護,4中可以使用purgecss-webpack-plugin 進行treeshaking,刪除未使用的css;

const PATHS = {
    src: path.join(__dirname, '../src')
}

plugins:[
		new MiniCssExtractPlugin(),
		//必須和mini-css-extract-plugin配合使用
    new PurgecssPlugin({
    	paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
    }),
  ]
複製代碼

動態引入polyfill

Polyfill通常佔用很大,不少時候不是必須的。通常經常使用的方法是使用babel-polyfill,體積會很大。可使用polyfill-service按需加載。polyfill-service主要經過UA來判斷該引用哪些polyfill。因此缺點也明顯,各大瀏覽器會僞造UA來搶佔,這會形成 service判斷困難。

CDN:

其餘優化

除了對項目和速度進行優化,也能夠對webpack展現優化,提升友好性。

  • 提示框
  • 進度條
  • 儀表板
  • 錯誤提示
  • 體積分析
plugins:[
  // 提示框
  new WebpackBuildNotifyerPlugin({
  	//提示項目名
    title: 'project',
    suppressSuccess: true
  }),
  //進度條
  new ProgressBarPlugin(),
  //儀表盤,看須要
  //new DashboardPlugin(),
  //錯誤提示,須要同stats使用
  new FriendlyErrorsWebpackPlugin(),
	// 體積分析,須要的時候加上,有多種分析插件
  // new BundleAnalyzerPlugin(),
]
複製代碼
相關文章
相關標籤/搜索