當你把所有的代碼都打包到一個文件的時候,每次改一個代碼都需要重新打包。且用戶都要重新加載下這個js文件。但是如果你把一些公共的代碼或第三方庫抽離並單獨打包。通過緩存加載,會加快頁面的加載速度。(分割成多個文件,不必打包成一個文件,提高性能)
- 異步加載的代碼,webpack會單獨打包到一個js文件中
- 同步加載的代碼有兩種方式
入口文件index.js
引入的第三方庫 import _ from 'lodash' 業務邏輯代碼 console.log(666)
打包后的文件main.js:
main.js 551 KiB main [emitted] main
可以看到,webpack將業務代碼跟lodash庫打包到一個main.js文件了,每次更改業務代碼,就要重新被打包一次,浪費性能
方法一:手動代碼分割,不推薦
index.js
業務邏輯代碼 console.log(666)
創建一個新文件lodsh.js入口, 將第三方的庫單獨抽離
import _ from 'lodash' window._ = _
將文件掛載到 window
對象上,這樣其他地方就可以直接使用了。
然后在webpack配置文件中的entry增加一個入口為該文件。
module.exports = { entry: { main: './src/index.js',
//新增一個打包的文件,lodash為打包后的文件名稱 ./src/lodash.js為入口文件, 映射關系 lodash:'./src/lodash.js' },
output: {
//模糊匹配entry需要打包文件名稱 filename: '[name].js', path: path.resolve(__dirname, '../dist') }
打包后,打包成main,js和lodash.js兩個文件,html會引入這兩個文件。
當我們業務邏輯更改,webpack重新打包只需打包main.js,lodash.js會緩存在瀏覽器中。代碼分割打包,此時提高了性能
Asset Size Chunks Chunk Names lodash.js 551 KiB lodash [emitted] lodash main.js 3.79 KiB main [emitted] main
方法二: webpack自動代碼分割
2.1,同步引入第三方庫
入口文件index.js
// 同步加載lodash import _ from 'lodash' console.log(_.join(['a','b','c','***']))
在webpack.base.js配置optimization
配置參數
optimization: { // 代碼分割配置 splitChunks: { chunks: 'all' } }, output: { filename: '[name].js', path: path.resolve(__dirname, '../dist') }
module.exports = { entry: { main: './src/index.js' },
打包后的文件,webapck的optimization會自動將諸如lodash
等庫抽離成單獨的chunk
,還會將多個模塊公用的模塊抽離成單獨的chunk,提高性能
2.2,異步引入代碼第三方庫
index.js入口文件
function getComponent() { // 異步加載lodash return import('lodash').then(({ default: _ }) => { var element = document.createElement('div'); element.innerHTML = _.join(['Dell', 'Lee'], '-'); return element; }) } getComponent().then(element => { document.body.appendChild(element); });
不需要webpack做任何配置
打包后文件, lodash第三方庫自動打包成單獨的0.js, vue中的路由懶加載就是這樣,import函數
總結
// 代碼分割,和webpack無關 // webpack中實現代碼分割,兩種方式 // 1. 同步代碼: 只需要在webpack.common.js中做optimization的配置即可 // 2. 異步代碼(import): 異步代碼,無需做任何配置,會自動進行代碼分割,放置到新的文件中
splitChunks
里面還可以在添加個參數cacheGroups
optimization: { splitChunks: { chunks: 'all', cacheGroups: { // 下面的意思是:將從node_modules中引入的模塊統一打包到一個vendors.js文件中 vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, filename: 'vendors.js' }, default: false } } }
index.js入口文件
同步加載lodash import _ from 'lodash' console.log(_.join(['a','b','c','***']))
打包加載后,cacheGroups
中vendors
配置表示將從node_modules
中引入的模塊(所有引入的第三方庫)統一打包到一個vendors.js文件中
如果venders的 filename: 'vendors.js',屬性注釋掉,那么默認會把第三方庫lodash統一打包到vendors~main.js文件中(main.js為第三方庫引入的文件)
splitChunks
的default
參數:
根據上下文來解釋,如上配置了vendors
,打包node_modules
文件夾中的模塊,
那么default
將會打包自己編寫的公共方法。
添加default的配置
optimization: { splitChunks: { chunks: 'all', cacheGroups: { // 下面的意思是:將從node_modules中引入的模塊統一打包到一個vendors.js文件中 vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, filename: 'vendors.js' }, // 打包除上面vendors以外的公共模塊 default: { priority: -20, reuseExistingChunks: true, // 如果該chunk已經被打包進其他模塊了,這里就復用了,不打包進common.js了 filename: 'common.js' } } } }
新增test.js
export default { name: 'Dell Lee' }
入口文件index.js,引入test模塊
import test from './test.js'; console.log(test.name);
打包后,自己編寫test.js的公共模塊打包成common.js文件
splitChunks: { chunk: 'all', // all(全部), async(異步的模塊),initial(同步的模塊) minSize: 3000, // 表示文件大於3000k的時候才對他進行打包 maxSize: 0, minChunks: 1, // 當某個模塊滿足minChunks引用次數時,才會被打包。例如,lodash只被一個文件import,那么lodash就不會被code splitting,lodash將會被打包進 被引入的那個文件中。如果滿足minChunks引用次數,lodash會被單獨抽離出來,打出一個chunk。 maxAsyncRequests: 5, // 在打包某個模塊的時候,最多分成5個chunk,多余的會合到最后一個chunk中。這里分析下這個屬性過大過小帶來的問題。當設置的過大時,模塊被拆的太細,造成並發請求太多。影響性能。當設置過小時,比如1,公共模塊無法被抽離成公共的chunk。每個打包出來的模塊都會有公共chunk automaticNameDelimiter: '~', // 當vendors或者default中的filename不填時,打包出來的文件名就會帶~ name: true, cashGroups: {} // 如上 }
注意;chunk:'all' 默認等於下面一大竄的配置,我們一般默認all即可就行了
optimization: { // 代碼分割配置 splitChunks: { chunks: 'all' } },
optimization: { splitChunks: { chunks: 'all', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, // filename: 'vendors.js', }, default: { priority: -20, reuseExistingChunk: true, filename: 'common.js' } } } },