通過webpack打包提取公共代碼
提取公共代碼的必要性
網站都是由多個頁面組成的,一般來說所有的頁面采用的都是相同的技術棧,要么都是Vue,都是React,要么都是Angular,采用的技術是一致的,既然是一致的,就會有公共的代碼,有很多代碼是相同的,如果每個頁面都將這些相同的公共代碼包含進去,會引起一些問題。
- 相同的資源配重復加載,造成了資源的浪費,(最后的靜態資源包會很大)
- 每個頁面打開的時間會變長(影響用戶體驗)
因為第一個原因,導致了第二個原因,所以我們將公共代碼抽離出來,在用戶打開一個頁面的時候,順便加載了公共的文件,在打開其他頁面的時候,如果其他頁面也引用了這個公共文件,就不用重新加載,直接從瀏覽器緩存中獲取,這么做解決了以上的兩個問題。
有人說通過cdn加載公共靜態資源也可以解決以上問題,對此,我說:
什么是CDN
內容分發網絡,加速網絡傳輸,就是通過將資源部署到世界各地,用戶訪問時按照就近原則從最近的服務器獲取資源,來提高獲取資源的速度,cdn就是對http的提速

綜合以上,cdn在數據傳輸層面上降低了用戶打開首頁的時間,和webpack提取公共打碼不是一個方向
如何提取公共代碼?
從webpack4開始官方移除了commonchunk插件,改用了optimization屬性進行更加靈活的配置,這也應該是從V3升級到V4的代碼修改過程中最為復雜的一部分
splitChunks: { chunks: "async”,//默認作用於異步chunk,值為all/initial/async/function(chunk),值為function時第一個參數為遍歷所有入口chunk時的chunk模塊,chunk._modules為chunk所有依賴的模塊,通過chunk的名字和所有依賴模塊的resource可以自由配置,會抽取所有滿足條件chunk的公有模塊,以及模塊的所有依賴模塊,包括css minSize: 30000, //表示在壓縮前的最小模塊大小,默認值是30kb minChunks: 1, // 表示被引用次數,默認為1; maxAsyncRequests: 5, //所有異步請求不得超過5個 maxInitialRequests: 3, //初始話並行請求不得超過3個 automaticNameDelimiter:'~',//名稱分隔符,默認是~ name: true, //打包后的名稱,默認是chunk的名字通過分隔符(默認是~)分隔 cacheGroups: { //設置緩存組用來抽取滿足不同規則的chunk,下面以生成common為例 common: { name: 'common', //抽取的chunk的名字 chunks(chunk) { //同外層的參數配置,覆蓋外層的chunks,以chunk為維度進行抽取 }, test(module, chunks) { //可以為字符串,正則表達式,函數,以module為維度進行抽取,只要是滿足條件的module都會被抽取到該common的chunk中,為函數時第一個參數是遍歷到的每一個模塊,第二個參數是每一個引用到該模塊的chunks數組。自己嘗試過程中發現不能提取出css,待進一步驗證。 }, priority: 10, //優先級,一個chunk很可能滿足多個緩存組,會被抽取到優先級高的緩存組中 minChunks: 2, //最少被幾個chunk引用 reuseExistingChunk: true,// 如果該chunk中引用了已經被抽取的chunk,直接引用該chunk,不會重復打包代碼 enforce: true // 如果cacheGroup中沒有設置minSize,則據此判斷是否使用上層的minSize,true:則使用0,false:使用上層minSize } } }
公共模塊抽離
舉例:
項目中分別有a.js, b.js, page1.js, page2.js這四個JS文件, page1.js 和 page2.js中同時都引用了a.js, b.js, 這時候想把a.js, b.js抽離出來合並成一個公共的js,然后在page1, page2中自動引入這個公共的js,怎么配置呢?如下:
配置webpack.config.js文件
module.exports = { //... //優化項配置 optimization: { // 分割代碼塊 splitChunks: { cacheGroups: { //公用模塊抽離 common: { chunks: 'initial', minSize: 0, //大於0個字節 minChunks: 2 //抽離公共代碼時,這個代碼塊最小被引用的次數 } } } } }
第三方模塊抽離
頁面中有時會引入第三方模塊,比如import $ from 'jquery'; page1中需要引用,page2中也需要引用,這時候就可以用vendor把jquery抽離出來,方法如下:
module.exports = { //... //優化項配置 optimization: { // 分割代碼塊 splitChunks: { cacheGroups: { //公用模塊抽離 common: { chunks: 'initial', minSize: 0, //大於0個字節 minChunks: 2, //在分割之前,這個代碼塊最小應該被引用的次數 }, //第三方庫抽離 vendor: { priority: 1, //權重 test: /node_modules/, chunks: 'initial', minSize: 0, //大於0個字節 minChunks: 2, //在分割之前,這個代碼塊最小應該被引用的次數 } } } } }
注意:這里需要配置權重 priority,因為抽離的時候會執行第一個common配置,入口處看到jquery也被公用了就一起抽離了,不會再執行wendor的配置了,所以加了權重之后會先抽離第三方模塊,然后再抽離公共common的,這樣就實現了第三方和公用的都被抽離了。