webpack 配置哪些優化?

1.忽略依賴庫的解析

module.exports = {
  //...
  module: {
    noParse: /jquery|lodash/, //不去解析jquery | lodash 中的依賴庫
  }
};
複製代碼

若是js中引入jquery, webpack會去解析jq中是否有依賴庫,配置noParse後打包時候忽略解析配置的庫,提升打包效率。javascript

2.解析時指定和排除查找目錄

module:{
		rules:[
			{
				test:/\.js$/,
				exclude:/node_modules/, // 解析不包含的目錄,二者寫其一便可
				include:path.resolve('src'), // 即系包含的目錄,二者寫其一便可
				use:{
					loader:'babel-loader',
					options:{
						presets:[
							'@babel/preset-env',
							'@babel/preset-react'
...
複製代碼

exclude排除目錄不進行解析。html

3.指定目錄不打包

IgnorePluginwebpack內置插件,能夠忽略第三方包不進行打包java

舉例:node

moment包react

好比引入第三方依賴庫moment, 該庫主要是對時間進行格式化,而且支持多個國家語言。jquery

moment打包問題webpack

import moment from 'moment'
//設置語言
moment.locale('zh-cn');
let r = moment().endOf('day').fromNow();
console.log(r);
複製代碼

雖然只設置了一種語言,可是在打包的時候,moment會將全部語言引入。這樣就致使包很大,打包速度又慢 。 咱們須要把其餘不須要的與語言包剔除 而moment的包含./locale/該字段路徑的文件目錄就是各國語言的目錄,好比./locale/zh-cn就是中文語言web

IgnorePlugin使用npm

let Webpack = require('webpack');
plugins:[
	new Webpack.IgnorePlugin(/\.\/locale/,/moment/)
]
複製代碼

若是在moment中引入了./locale目錄的內容,會忽略掉 傳遞給IgnorePlugin的第一個參數resourceRegExp參數並不針對導入或必需的已解析文件名或絕對模塊名進行測試,而是針對在導入發生的源代碼中傳遞給require或import的字符串進行測試。例如,若是您試圖排除node_modules/moment/locale/*.js,這是行不通的 使用第二個contextRegExp參數選擇導入發生的特定目錄。下面的代碼將致使這些locale文件被忽略json

問題存在與解決

若是上述方法忽略了./locale/的目錄,那麼全部語音都會被忽略,若是須要引入中文,須要手動配置

import moment from 'moment'

//手動引入所須要的語言包
import 'moment/locale/zh-cn';

moment.locale('zh-cn');

let r = moment().endOf('day').fromNow();
console.log(r);
複製代碼

4.DllPlugin動態連接庫

場景舉例: 當打包一個react項目的時候,項目中引入reacrreact-dom兩個包,而這兩個庫很大且基本不會變,每次項目打包都會對打包,浪費時間和性能。

處理方法: 將react和react-dom單獨打包好,而後動態連接引入便可。若是第二次打包,那麼發現react和react-dom已經被打包好了,那麼直接找到打包好的文件,不須要再次打包。

實現

src 下 index.js 文件引入 reactreact-dom

import React from 'react'
import {render} from 'react-dom'
render('<h1>jsx</h1>')
複製代碼

src 下建立 test.js文件

module.exports = 'joker';
複製代碼

建立webpack.config.react.jsreact包單獨打包

let path = require('path');
 let webpack = require('webpack');
 module.exports = {
  mode:'development',
  entry:{
   react:['react','react-dom']
  },
  output:{
   filename:'_dll_[name].js',//產生的文件名_dll_react.js 
   path:path.resolve(__dirname,'dist'),
   library:'_dll_[name]',//_dll_react // 
   // libraryTarget:'var',
  },
  plugins:[
   new webpack.DllPlugin({
    name:'_dll_[name]',//這個name要與output中的library同名
    path:path.resolve(__dirname,'dist','manifest.json')
   })
  ]
 }
複製代碼

打包出一個_dll_react.js和一個是清單manifest.json而後在index.html去引用這個打包後的文件

<!DOCTYPE html>
 <html>
 <head>
  <title></title>
 </head>
 <body>
  <div id="root"></div>
  <script type="text/javascript" src="/_dll_react.js"></script>
 </body>
 </html>
複製代碼

可是如今,咱們引用reactreact-dom的時候,咱們須要判斷是否在清單裏,這時候,咱們就須要在咱們正式的webpack.config.js裏進行配置, 須要使用到webpack內置插件webpack.DllReferencePlugin

let path = require('path');
 let webpack = require('webpack');
 let HtmlWebpackPlugin = require('html-webpack-plugin');
 module.exports = {
  devServer:{
   port:3000,
   open:true,
   contentBase:'./dist'
  },
  mode:'development',
  entry:'./src/index.js',
  output:{
   filename:'bundle.js',
   path:path.resolve(__dirname,'./dist')
  },
  module:{
   rules:[
    {
     test:/\.js$/,
     use:{
      loader:'babel-loader',
      options:{
       presets:[
        '@babel/preset-env',
        '@babel/preset-react'
       ]
      }
     }
    }
   ]
  },
  plugins:[
   new webpack.DllReferencePlugin({
    manifest:path.resolve(__dirname,'dist','manifest.json')
   }),
   new HtmlWebpackPlugin({
    template:'./src/index.html',
    filename:'index.html'
   })
  ]
 }
複製代碼

5.抽離公共代碼

場景舉例: 當多頁應用重複使用部分公用代碼時,每次單頁都會重複加載這些公用代碼會形成一下問題: 相同資源,重複加載,增長用戶流量和服務器成本

處理方法: 那麼,若是將這些公共代碼抽取出來,並讓瀏覽器緩存起來,用戶在請求資源的時候,能夠直接讀取緩存中的這些代碼,這樣就能解決以上問題。

如何抽取公共代碼: 如今存在以下文件結構

other.js
        ↑
  -------------
  ↑           ↑
a.js        b.js
  ↓           ↓
  -------------
        ↓
     index.js
複製代碼

如上圖,index.jsother.js都依賴了a.jsb.js,那麼只須要將 a.jsb.js抽離出來並打包成common.js,而後讓index.jsother.js直接引用common.js便可.

1.webpack.config.js配置 使用optimization的splitChunks屬性

module.exports = {
	optimization:{
		splitChunks:{//分割代碼塊,若是隻有一個入口,就不須要分割了,只有多頁,才須要把公共的抽離出來
			cacheGroups:{//緩存組
				common:{//公共的模塊
					chunks:'initial',//剛開始就要抽離
					minSize:0,//大小大於0字節的時候須要抽離出來
					minChunks:2,//重複2次使用的時候須要抽離出來
				}
			}
		}
	},
	...
}
複製代碼

npm run build獲得的文件爲:

dist
  |
  ----- common~index~other.js
  |
  ----- index.js
  |
  ----- other.js
  |
  ----- index.html
複製代碼

這樣,index.jsother.js都引用了抽離出來的公共代碼common~index~other.js

如何抽離第三方庫 假設在上面的基礎上,index.js 和 other.js都引用了jquery庫,那麼這樣來配置抽離第三方庫 vendor屬性的配置,是用於抽取第三方庫的(詳看代碼和註釋)

module.exports = {
	optimization:{
		splitChunks:{ //分割代碼塊,若是隻有一個入口,就不須要分割了,只有多頁,才須要把公共的抽離出來
			cacheGroups:{ //緩存組
				common:{ //公共的模塊
					chunks:'initial',
					minSize:0,
					minChunks:2,
				},
				vendor:{	test:/node_modules/,//把這個目錄下符合下面幾個條件的庫抽離出來
					chunks:'initial',//剛開始就要抽離
					minSize:0,//大小大於0字節的時候須要抽離出來
					minChunks:2,//重複2次使用的時候須要抽離出來
				}
			}
		}
	},
	...
}
複製代碼

可是這樣會存在問題——代碼從上到下執行,會先執行common,而後執行vendor,而在執行common的時候,就把jquery抽離出來打包到跟a.js和b.js裏面去了,後面的vendor就沒有什麼效果了。這並非個好方案,咱們最好是可以將庫單獨抽離出來,因而,能夠這麼操做: 在vendor添加權重屬性:priority,將權重提升,使得先去抽離第三方庫,再去抽離a.js和b.js

module.exports = {
	optimization:{
		splitChunks:{//分割代碼塊,若是隻有一個入口,就不須要分割了,只有多頁,才須要把公共的抽離出來
			cacheGroups:{//緩存組
				common:{//公共的模塊
					chunks:'initial',
					minSize:0,
					minChunks:2,
				},
				vendor:{
					priority:1,//添加權重
					test:/node_modules/,//把這個目錄下符合下面幾個條件的庫抽離出來
					chunks:'initial',//剛開始就要抽離
					minSize:0,//大小大於0字節的時候須要抽離出來
					minChunks:2,//重複2次使用的時候須要抽離出來
				}
			}
		}
	},
	...
}
複製代碼

打包結果爲

common~index~other.js  579 bytes  
           index.html  388 bytes
             index.js   7.38 KiB 
             other.js   7.38 KiB 
vendor~index~other.js    306 KiB 
複製代碼
相關文章
相關標籤/搜索