一、前言 之前一直也沒有研究過webpack4是基於怎樣的規則去拆分模塊的,現在正好有時間打算好好瞭解一下,看了官方文檔也陸陸續續的看了看網上別人寫的文章,感覺大部分都是將官方文檔翻譯了一遍,很多問題都沒有解釋清楚,無奈只好自己寫demo去通過實際編譯結果來理解,經過一天多的不斷調試和百度,基本弄清 ...
一、前言
之前一直也沒有研究過webpack4是基於怎樣的規則去拆分模塊的,現在正好有時間打算好好瞭解一下,看了官方文檔也陸陸續續的看了看網上別人寫的文章,感覺大部分都是將官方文檔翻譯了一遍,很多問題都沒有解釋清楚,無奈只好自己寫demo去通過實際編譯結果來理解,經過一天多的不斷調試和百度,基本弄清楚了splitChuns的運行規則了,特此記錄下來。
二、webpack中的三個概念module、chunk和bundle
在研究splitChunks之前,我們必須先弄明白這三個名詞是什麼意思,主要是chunk的含義,要不然你就不知道splitChunks是在什麼的基礎上進行拆分。
從官網上貌似沒找太多的解釋,去網上搜了搜基本上都在轉述這位老哥的回答《what are module,chunk and bundle in webpack》,我根據自己的理解給出我個人的看法:
- module:就是js的模塊化webpack支持commonJS、ES6等模塊化規範,簡單來說就是你通過import語句引入的代碼。
- chunk: chunk是webpack根據功能拆分出來的,包含三種情況:
1、你的項目入口(entry)
2、通過import()動態引入的代碼
3、通過splitChunks拆分出來的代碼
chunk包含著module,可能是一對多也可能是一對一。
- bundle:bundle是webpack打包之後的各個文件,一般就是和chunk是一對一的關係,bundle就是對chunk進行編譯壓縮打包等處理之後的產出。
三、splitChunks
下麵進入正題講解splitChunks,splitChunks就算你什麼配置都不做它也是生效的,源於webpack有一個預設配置,這也符合webpack4的開箱即用的特性,它的預設配置如下:
module.exports = { //... optimization: { splitChunks: { chunks: 'async', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } } };
我們現在用一個簡單的react項目來測試下打包之後的效果如何,我的這個項目有兩個頁面entry1.js和page1.js,entry1.js是入口文件,entry1.js裡面動態引入了page1.js。
entry1.js
1 import React from 'react' 2 import ReactDOM from 'react-dom' 4 5 const App = () => { 6 let Page1 = null 7 8 import(/* webpackChunkName: "page1" */'./routes/page1').then(comp => { 9 Page1 = comp 10 }) 11 console.log($) 12 return ( 13 <div> 14 <div>App</div> 15 <Page1 /> 16 </div> 17 ) 18 } 19 20 ReactDOM.render(<App />, document.getElementById('root'))
page1.js
1 import React from 'react' 2 import _ from 'lodash' 4 5 const Page1 = () => { 6 console.log($) 7 8 return ( 9 <div> 10 <div>Page1</div> 11 </div> 12 ) 13 } 14 15 export default Page1
讓我們想一想打包之後的代碼是怎樣的呢?
以上就是打包之後的代碼,是否如你所想呢,讓我們分析一下:
1、第一個main文件就是打包之後的入口文件,這個我們上面說了webpack會把入口文件單獨拆成一個chunk,這個沒有問題
2、第三個page1文件,我們上面也說過動態載入得文件webpack會將其拆分為一個chunk,這個也沒有問題
3、第二個vendor~page1文件,這個是對page1文件裡面引入的第三方庫進行打吧,具體就是lodash那個第三方庫了,這個涉及到cacheGroup,我們在下麵的系列文章裡面會詳細講述
以上就是所有被拆分出來的包,但是我們發現有一個文件沒有拆分出來,那就是entry1裡面引入的第三方庫react-dom,這個是為什麼呢,這個就要涉及到我們接下來講到的chunks屬性的配置。
註意:這裡提個小問題為什麼react-dom這個第三方庫只在entry1.js裡面引入了一次就被拆分出來了?這個答案我將在第三篇文章《理解webpack4.splitChunks之cacheGroups》裡面進行解釋。
為了方便閱讀我將整個系列分為了若幹小部分,大家可以各取所需:
《理解webpack4.splitChunks之chunks》
《理解webpack4.splitChunks之cacheGroups》
《理解webpack4.splitChunks之maxInitialRequests》
《理解webpack4.splitChunks之maxAsyncRequests》
文章中所用到的源碼倉庫地址是webpack-splitChunks-demo