天天看點

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

作者:架構思考
若你對webpack僅僅是處于使用階段,覺得webpack原理太雜太亂太多,但是覺得大概了解下webpack的大緻原理也不錯。亦或是想要了解分包優化如何進行配置呢?以及為什麼webpack官方分包配置會從 CommmonsChunkPlugin演變成SplitChunksPlugin呢?我按照自己的方式,通過查閱、整理相關文檔,梳理一些比較容易讓大家糾結的點,讓大家通過本篇文章,大概了解webpack是幹了什麼?

一、webpack前生今世

1.1、前端石器時代----->工業化時代

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

前端變遷轉折點

  • 2008年9月2号,當Chrome第一次出現的時候(V8與Chrome同一天宣布開源),它對網頁的加載速度讓所有人驚歎,是V8引擎把JavaScript的運作速度提上來了,讓前端從蒸汽機機時代正式步入内燃機時代。
  • 2009年誕生的Node.js和2010年誕生的npm,迅速将JavaScript變成全球最受歡迎的生态系統之一。前端正式從石器時代進入到了工業化時代。

1.2、前端為什麼需要子產品化

痛點

  • 變量和方法不容易維護,容易污染全局作用域。
  • 加載資源的方式通過script标簽從上到下。
  • 依賴的環境主觀邏輯偏重,代碼較多就會比較複雜。
  • 大型項目資源難以維護,特别是多人合作的情況下,資源的引入會讓人崩潰。

作用

子產品化的開發方式可以提高代碼複用率,友善進行代碼的管理。通常來說,一個檔案就是一個子產品,有自己的作用域,隻向外暴露特定的變量和函數。有了子產品,我們就可以更友善地使用别人的代碼,想要什麼功能,就加載什麼子產品。

子產品規範

但是,這樣做有一個前提,那就是大家必須以同樣的方式編寫子產品,否則你有你的寫法,我有我的寫法,豈不是亂了套!考慮到Javascript子產品現在還沒有官方規範,這一點就更重要了。目前流行的js子產品化規範有CommonJS、AMD、CMD以及ES6的子產品系統。

(1)CommonJS

NodeJS誕生之後,它使用CommonJS的子產品化規範。從此,js子產品化開始快速發展。它有四個重要的環境變量為子產品化的實作提供支援:module、exports、require、global。

(2)AMD

CommonJS對伺服器端不是一個問題,因為所有的子產品都存放在本地硬碟,可以同步加載完成,等待時間就是硬碟的讀取時間。但是,對于浏覽器,這卻是一個大問題,因為子產品都放在伺服器端,等待時間取決于網速的快慢,可能要等很長時間,浏覽器處于“假死”狀态。是以,浏覽器端的子產品,不能采用“同步加載”(synchronous),隻能采用“異步加載”(asynchronous)。這就是AMD規範誕生的背景。

AMD是“Asynchronous Module Definition”的縮寫,意思就是“異步子產品定義”。它采用異步方式加載子產品,子產品的加載不影響它後面語句的運作。所有依賴這個子產品的語句,都定義在一個回調函數中,等到加載完成之後,這個回調函數才會運作。主要有兩個Javascript庫實作了AMD規範:require.js和curl.js。

(3)CMD

CMD是另一種js子產品化方案,它與AMD很類似,不同點在于:AMD推崇依賴前置、提前執行,CMD推崇依賴就近、延遲執行。此規範其實是在sea.js推廣過程中産生的。

(4)ES6

在語言标準的層面上,實作了子產品功能,而且實作得相當簡單,旨在成為浏覽器和伺服器通用的子產品解決方案。其子產品功能主要由兩個指令構成:export和import。export指令用于規定子產品的對外接口,import指令用于輸入其他子產品提供的功能。

子產品化總結

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

1.3、為什麼需要webpack呢?

前端頁面效果越來越酷炫、功能越來越複雜。而前端工程師們為了更友善的開發提高開發效率進行了一系列der探索,子產品化思想的提出啊,将複雜的程式分割成更小的檔案。這些年優秀的架構層出不窮react、vue、angular、es6這種在javascript基礎上拓展的新的文法規範和less、sass、css處理器等等等。所有的事物都是具有雙面性的、有利有弊。大大提高開發效率的同時,又為後期維護造成了困擾。因為利用這些工具的檔案往往不能直接被浏覽器識别,需要手動處理,很影響開發進度。

是否可以有一種方式,不僅可以讓我們編寫子產品,而且還支援任何子產品格式(至少在我們到達ESM之前),并且可以同時處理資源和資産?是以webpack應運而生~這就是webpack存在的原因。它是一個工具,可以打包你的JavaScript應用程式(支援ESM和CommonJS),可以擴充為支援許多不同的靜态資源,例如:images, fonts和stylesheets。

webpack關心性能和加載時間;它始終在改進或添加新功能,例如:異步地加載chunk和預取,以便為你的項目和使用者提供最佳體驗。

二、webpack概念

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

webpack是一個用于現代JavaScript應用程式的靜态子產品打包工具。當 webpack處理應用程式時,它會在内部從一個或多個入口點建構一個依賴圖(dependency graph),然後将你項目中所需的每一個子產品組合成一個或多個bundles,它們均為靜态資源,用于展示你的内容。

三、webpack核心流程解析

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

總體流程架構圖

上述提及的各類技術名詞不太熟悉的同學,可以先看看簡介:

  • Entry:編譯入口,webpack編譯的起點。
  • Compiler:編譯管理器,webpack啟動後會建立compiler對象,該對象一直存活直到結束退出。
  • Compilation:單次編輯過程的管理器,比如watch=true時,運作過程中隻有一個compiler但每次檔案變更觸發重新編譯時,都會建立一個新的 compilation對象。
  • Dependence:依賴對象,webpack基于該類型記錄子產品間依賴關系。
  • Module:webpack内部所有資源都會以“module”對象形式存在,所有關于資源的操作、轉譯、合并都是以“module”為基本機關進行的。
  • Chunk:編譯完成準備輸出時,webpack會将module按特定的規則組織成一個一個的chunk,這些chunk某種程度上跟最終輸出一一對應。
  • Loader:資源内容轉換器,其實就是實作從内容A轉換B的轉換器。
  • Plugin:webpack建構過程中,會在特定的時機廣播對應的事件,插件監聽這些事件,在特定時間點介入編譯過程。

擴充

Compiler是plugin的apply接口傳進來的參數,它代表了完整的 webpack環境配置。這個對象在啟動webpack時被一次性建立,并配置好所有可操作的設定,包括options,loader和plugin。當在webpack環境中應用一個插件時,插件将收到此compiler對象的引用,可以使用它來通路webpack的主環境。對于plugin而言,通過它來注冊事件鈎子。

Compilation對象代表了一次資源版本建構。當運作webpack開發環境中間件時,每當檢測到一個檔案變化,就會建立一個新的compilation,進而生成一組新的編譯資源。一個compilation對象表現了目前的子產品資源、編譯生成資源、變化的檔案、以及被跟蹤依賴的狀态資訊。對于plugin而言,通過它來完成資料的處理。

3.1、初始化階段

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘
  • 初始化參數:從配置檔案、 配置對象、Shell參數中讀取,與預設配置結合得出最終的參數。
  • 建立編譯器對象:用上一步得到的參數。
  • 建立Compiler對象初始化編譯環境:包括注入内置插件、注冊各種子產品工廠、初始化RuleSet集合、加載配置的插件等。
  • 開始編譯:執行compiler對象的run方法。
  • 确定入口:根據配置中的entry找出所有的入口檔案,調用compilition.addEntry将入口檔案轉換為dependence對象。

這個過程需要在webpack初始化的時候預埋下各種插件,經曆4個檔案,7次跳轉才開始進入主題。

3.2、建構階段

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘
  • 編譯子產品(make):根據entry對應的dependence建立module對象,調用loader将子產品轉譯為标準JS内容,調用JS解釋器将内容轉換為AST對象,從中找出該子產品依賴的子產品,再遞歸。本步驟直到所有入口依賴的檔案都經過了本步驟的處理。
  • 完成子產品編譯:上一步遞歸處理所有能觸達到的子產品後,得到了每個子產品被翻譯後的内容以及它們之間依賴關系圖。

建構階段從entry開始遞歸解析資源與資源的依賴,在compilation對象内逐漸建構出module集合以及module之間的依賴關系。

這個過程中資料流module=>ast=>dependences=>module,先轉AST再從AST找依賴。compilation按這個流程遞歸處理,逐漸解析出每個子產品的内容以及module依賴關系,後續就可以根據這些内容打包輸出。

3.3、生成階段

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

輸出資源(seal):根據入口和子產品之間的依賴關系,組裝成一個個包含多個子產品的Chunk,再把每個Chunk轉換成一個單獨的檔案加入到輸出清單,這步是可以修改輸出内容的最後機會。

寫入檔案系統(emitAssets):在确定好輸出内容後,根據配置确定輸出的路徑和檔案名,把檔案内容寫入到檔案系統。

seal的關鍵邏輯是将module按規則組織成chunks,webpack内置的chunk封裝規則比較簡單:entry及entry觸達到的子產品,組合成一個 chunk 使用動态引入語句引入的子產品,各自組合成一個chunk。

chunk是輸出的基本機關,預設情況下這些chunks與最終輸出的資源一一對應,那按上面的規則大緻上可以推導出一個entry會對應打包出一個資源,而通過動态引入語句引入的子產品,也對應會打包出相應的資源。

四、chunk概念及分包基本規則

4.1、webpack資源形态流轉

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

webpack資源形态流轉

從資源流轉的層面,我們來看下webpack的打包流程:

  • compiler.make階段:

entry檔案以dependence對象形式加入compilation的依賴清單,dependence對象記錄有entry的類型、路徑等資訊。

根據dependence調用對應的工廠函數建立module對象,之後讀入module對應的檔案内容,調用loader-runner對内容做轉化,轉化結果若有其它依賴則繼續讀入依賴資源,重複此過程直到所有依賴均被轉化為module。

  • compilation.seal階段:

周遊module集合,根據entry配置及引入資源的方式,将module配置設定到不同的chunk。

周遊chunk集合,調用compilation.emitAsset方法标記chunk的輸出規則,即轉化為assets集合。

  • compiler.emitAssets階段:

将assets寫入檔案系統

綜上,Module主要作用在webpack編譯過程的前半段,解決原始資源“如何讀”的問題;而Chunk對象則主要作用在編譯的後半段,解決編譯産物“如何寫”的問題,兩者合作搭建起webpack搭建主流程。

4.2、chunk概念

從上面的webpack資源形态流轉圖以及解析中,我們不難發現chunk的大概概念。

chunk:webpack實作中,原始的資源子產品以Module對象形式存在、流轉、解析處理。

而Chunk則是輸出産物的基本組織機關,在生成階段webpack按規則将entry及其它Module插入Chunk中,之後再由SplitChunksPlugin插件根據優化規則與ChunkGraph對Chunk做一系列的變化、拆解、合并操作,重新組織成一批性能(可能)更高的Chunks 。運作完畢之後webpack繼續将 chunk一一寫入實體檔案中,完成編譯工作。代碼塊,是webpack根據功能拆分出來的(chunk是無法在打包結果中看到的,打包結果中看到的是bundle)。

4.3、chunk的基本分包規則

chunk可以分為三類:

  • 每個entry項都會對應生成一個chunk對象,稱之為initial chunk。
  • 每個異步子產品都會對應生成一個chunk對象,稱之為async chunk。
  • Webpack 5之後,如果entry配置中包含runtime值,則在entry之外再增加一個專門容納runtime的chunk對象,此時可以稱之為runtime chunk。

預設情況下initial chunk通常包含運作該entry所需要的所有runtime代碼,但webpack 5之後出現的第三條規則打破了這一限制,允許開發者将runtime從initial chunk中剝離出來獨立為一個多entry間可共享的 runtime chunk。

注意:

  • 「業務子產品」是指開發者所編寫的項目代碼。
  • 「runtime 子產品」是指Webpack分析業務子產品後,動态注入的用于支撐各項特性的運作時代碼。

4.4、bundle vs chunk

bundle: bundle是webpack打包之後的各個檔案,一般就是和chunk是一對一的關系,但有時候也不完全是一對一的關系。bundle就是對chunk進行編譯壓縮打包等處理之後的産出。

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

Chunk是過程中的代碼塊,Bundle是結果的代碼塊。

五、SplitChunksPlugin的前世今生

預設情況下,Webpack會将所有代碼建構成一個單獨的包,這在小型項目通常不會有明顯的性能問題,但伴随着項目的推進,包體積逐漸增長可能會導緻應用的響應耗時越來越長。歸根結底這種将所有資源打包成一個檔案的方式存在兩個弊端:

  • 「資源備援」:用戶端必須等待整個應用的代碼包都加載完畢才能啟動運作,但可能使用者當下通路的内容隻需要使用其中一部分代碼。
  • 「緩存失效」:将所有資源達成一個包後,所有改動——即使隻是修改了一個字元,用戶端都需要重新下載下傳整個代碼包,緩存命中率極低。

一個多頁面應用,所有頁面都依賴于相同的基礎庫,那麼這些所有頁面對應的entry都會包含有基礎庫代碼,這豈不浪費?這些問題都可以通過對産物做适當的分解拆包解決 ,誕生了CommonsChunkPlugin。

5.1、CommmonsChunkPlugin的弊端

CommmonsChunkPlugin的思路是Create this chunk and move all modules matching minChunks into the new chunk,即将滿足minChunks配置想所設定的條件的子產品移到一個新的chunk檔案中去,這個思路是基于父子關系的,也就是這個新産出的new chunk是所有chunk的父親,在加載孩子chunk的時候,父親chunk是必須要提前加載的。舉例:

  • 同步子產品加載
example:
entryA:  vue  vuex  someComponents 
entryB:  vue axios someComponents 
entryC: vue vux axios someComponents minchunks: 2           

産出後的chunk:

vendor-chunk:vue vuex axios 
chunkA~chunkC: only the components           

對entryA和entryB來說,vendor-chunk都包含了多餘的module。

  • 異步的子產品
example:
 entryA:  vue  vuex  someComponents 
 asyncB:vue axios someComponents 
 entryC: vue vux axios someComponents 
 minchunks: 2           

産出後的chunk:

vendor-chunk:vue vuex  
chunkA: only the components
chunkB: vue axios someComponents 
 chunkC: axios someComponents           

帶來的問題是:如果asyncB在entryA中動态引入,則會引入多餘的module。

總的來說,CommonsChunkPlugin有以下三個問題:

  • 産出的chunk在引入的時候,會包含重複的代碼。
  • 無法優化異步chunk。
  • 高優的chunk産出需要的minchunks配置比較複雜。

綜上,CommonsChunkPlugin有很多問題:

  • 它可能會導緻許多不必要的代碼代碼被加載。
  • 它會影響異步加載的chunk。
  • 它很難使用。
  • 它使用起來很難了解。

5.2、SplitChunksPlugin的誕生

針對以上種種問題,webpack4內建了新的插件:SplitChunksPlugin

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

其中,可以發現SplitChunksPlugin産出的vendor-chunk有多個,對于入口A來說,引入的代碼隻有chunkA、vendor-chunkA-B、vendor-chunkA-C、vendor-chunkA-B-C;這時候chunkA、vendor-chunkA-B、vendor-chunkA-C、vendor-chunkA-B-C形成了一個chunkGroup。SplitChunksPlugin它會使用子產品重複計數和子產品種類(node_modules)自動識别哪些chunk需要被分離。可以類比一下兩個插件。

CommonsChunkPlugin就類似于:建立這個chunk并且把所有與minChunks字段比對的子產品移到新的chunk中。而SplitChunksPlugin就類似于:這是啟發式的,確定你需要他們(指令式vs聲明式)

5.3、SplitChunksPlugin的概念和優點

SplitChunksPlugin是Webpack 4之後引入的分包方案(此前為 CommonsChunkPlugin),它能夠基于一些啟發式的規則将Module編排進不同的Chunk序列,并最終将應用代碼分門别類打包出多份産物,進而實作分包功能。

SplitChunksPlugin有一些很贊的屬性:

  • 不會下載下傳不必要的子產品(隻要你強制使用name屬性合并chunk)
  • 對異步加載的chunk也有效
  • 預設情況下,隻對異步加載的chunk有效
  • 處理從多個vendor chunks分離出來的vendor
  • 更容易使用
  • 不需要依賴chunk graph的hack手法
  • 更加自動化

命名規則大緻舉例如下:

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

六、SplitChunksPlugin使用

使用上,SplitChunksPlugin的配置規則比較抽象,算得上Webpack的一個難點,仔細拆解後關鍵邏輯在于:

SplitChunksPlugin通過module被引用頻率、chunk大小、包請求數三個次元決定是否執行分包操作,這些決策都可以通過 optimization.splitChunks配置項調整定制,基于這些次元我們可以實作:

  • 單獨打包某些特定路徑的内容,例如node_modules打包為 vendors;
  • 單獨打包使用頻率較高的檔案。

SplitChunksPlugin還提供配置組概念optimization.splitChunks.cacheGroup,用于為不同類型的資源設定更有針對性的配置資訊。

SplitChunksPlugin還内置了default與defaultVendors兩個配置組,提供一些開箱即用的特性:

  • node_modules資源會命中defaultVendors規則,并被單獨打包。
  • 隻有包體超過20kb的Chunk才會被單獨打包。
  • 加載 Async Chunk 所需請求數不得超過30。
  • 加載 Initial Chunk 所需請求數不得超過30。

6.1、分包範圍(chunks)

SplitChunksPlugin預設隻對Async Chunk生效,開發者也可以通過optimization.splitChunks.chunks調整作用範圍,該配置項支援如下值:

  • 字元串'all' :對Initial Chunk與Async Chunk都生效,建議優先使用該值。
  • 字元串'initial':隻對Initial Chunk生效。
  • 字元串'async':隻對Async Chunk生效。
  • 函數 (chunk)=>boolean:該函數傳回true時生效。
module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
}           

6.2、根據Module使用頻率分包(minChunks)

module.exports = {
  //...
  optimization: {
    splitChunks: {
      // 設定引用次數超過 3 的子產品才進行分包
      minChunks: 3
    },
  },
}           

SplitChunksPlugin支援按Module被Chunk引用的次數決定是否進行分包,開發者可通過optimization.splitChunks.minChunks設定最小引用次數。

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

示例中,entry-a、entry-b分别被視作Initial Chunk處理;async-module被entry-a以異步方式引入,是以被視作Async Chunk處理。那麼對于common子產品來說,分别被三個不同的Chunk引入,此時引用次數為 3,命中optimization.splitChunks.minChunks=2規則,是以該子產品「可能」會被單獨分包,最終産物:entry-a.js entry-b.js async-module.js common.js

6.3、限制分包數量(maxInitialRequest/maxAsyncRequests)

在滿足minChunks基礎上,還可以通過maxInitialRequest/maxAsyncRequests配置項限定分包數量,配置項語義。

  • maxInitialRequest:用于設定Initial Chunk最大并行請求數。
  • maxAsyncRequests:用于設定 Async Chunk 最大并行請求數。

注意:這裡所說的“請求數”,是指加載一個Chunk時所需同步加載的分包數。例如對于一個Chunk A,如果根據分包規則(如子產品引用次數、第三方包)分離出了若幹子Chunk A¡,那麼請求A時,浏覽器需要同時請求所有的A¡,此時并行請求數等于¡個分包加A主包,即¡+1。

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

若minChunks=2,則common-1 、common-2同時命中minChunks規則被分别打包,浏覽器請求entry-b時需要同時請求common-1、common-2兩個分包,并行數為2+1=3,此時若maxInitialRequest= 2,則分包數超過門檻值,SplitChunksPlugin會放棄common-1、common-2中體積較小的分包。maxAsyncRequest邏輯與此類似,不在贅述。

并行請求數關鍵邏輯總結如下:

Initial Chunk本身算一個請求Async Chunk不算并行請求 通過 runtimeChunk拆分出的runtime不算并行請求 如果同時有兩個Chunk滿足拆分規則,但是maxInitialRequests(或maxAsyncRequest) 的值隻能允許再拆分一個子產品,那麼體積更大的子產品會被優先拆解。

6.4、限制分包體積(minSize、maxSize.........)

在滿足minChunks與maxInitialRequests的基礎上,SplitChunksPlugin還會進一步判斷Chunk包大小決定是否分包,這一規則相關的配置項非常多:

  • minSize:超過這個尺寸的Chunk才會正式被分包。
  • maxSize:超過這個尺寸的Chunk會嘗試繼續做分包。
  • maxAsyncSize:與maxSize功能類似,但隻對異步引入的子產品生效。
  • maxInitialSize:與maxSize類似,但隻對entry配置的入口子產品生效。
  • enforceSizeThreshold:超過這個尺寸的Chunk會被強制分包,忽略上述其它size限制。

那麼,結合前面介紹的兩種規則,SplitChunksPlugin的主體流程如下:

  • SplitChunksPlugin嘗試将命中minChunks規則的Module統一抽到一個額外的Chunk對象。
  • 判斷該Chunk是否滿足maxInitialRequests門檻值,若滿足則進行下一步。
  • 判斷該 Chunk 資源的體積是否大于上述配置項minSize聲明的下限門檻值。

如果體積「小于」 minSize則取消這次分包,對應的Module依然會被合并入原來的Chunk。

如果Chunk體積「大于」minSize則判斷是否超過maxSize、maxAsyncSize、maxInitialSize聲明的上限門檻值,如果超過則嘗試将該Chunk繼續分割成更小的部分。

注意,這些屬性的優先級順序為:

maxInitialRequest/maxAsyncRequests < maxSize < minSize

而命中 enforceSizeThreshold 門檻值的 Chunk 會直接跳過這些屬性判斷,強制進行分包。           

6.5、cacheGroups

cacheGroups配置項用于為不同檔案組設定不同的規則,例如:

基本規則

module.exports = {
  //...
  optimization: {
    splitChunks: {
      minChunks: 2,
      cacheGroups: {
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            minChunks: 1,
            minSize: 0
        },
      },
    },
  },
};           

示例通過cacheGroups屬性設定vendors緩存組,所有命中vendors.test規則的子產品都會被視作vendors分組,優先應用該組下的minChunks、minSize等分包配置。

除了minChunks等分包基礎配置項之外,cacheGroups還支援一些與分組邏輯強相關的屬性,包括:

  • test:接受正規表達式、函數及字元串,所有符合test判斷的Module或Chunk都會被分到該組。
  • type:接受正規表達式、函數及字元串,與test類似均用于篩選分組命中的子產品,差別是它判斷的依據是檔案類型而不是檔案名,例如type='json'會命中所有JSON檔案。
  • name:chunk命名。
  • priority:數字型,用于設定該分組的優先級,若子產品命中多個緩存組,則優先被分到priority更大的組。

緩存組的作用在于能為不同類型的資源設定更具适用性的分包規則,一個典型場景是将所有node_modules下的子產品統一打包到vendors産物,進而實作第三方庫與業務代碼的分離。

預設分組

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};           

這兩個配置組能幫助我們:

  • 将所有node_modules中的資源單獨打包到vendors.js命名的産物。
  • 對引用次數大于等于2的子產品,也就是被多個Chunk引用的子產品,單獨打包。

七、SplitChunksPlugin最佳實戰

那麼,如何設定最适合項目情況的分包規則呢?這個問題并沒有放諸四海皆準的通用答案,因為軟體系統與現實世界的複雜性,決定了很多計算機問題并沒有銀彈,不過還是有幾條可供參考的最佳實踐:

  • 「盡量将第三方庫拆為獨立分包」
  • 「保持按路由分包,減少首屏資源負載」
  • 「盡量保持」 chunks='all'

八、建構打包工具比較

「前端」騰訊前端工程師總結的 webpack基礎、分包大揭秘

文章來源:李倩倩_騰訊前端開發工程師_https://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&mid=2247539154&idx=1&sn=04b1c5e2f8d36257c9c71068b95caeea&chksm=eaa84382dddfca9494c58a871e5e0f41304185b5e7c3b09d885781bcf5882e6e6130c9ed97e5&scene=178&cur_album_id=2721018755119595521#rd