webpack 的 tree shaking 的原理
Webpack 的 Tree Shaking 過程主要包含以下步驟:
- 模塊依賴分析:Webpack 首先構建一個完整的模塊依賴圖,確定每個模塊之間的依賴關系。
- 導出值分析:通過分析模塊之間的 import 和 export,Webpack 識別出哪些導出值被其他模塊引用。
- 未使用代碼識別:通過對比模塊的導出值和引用情況,Webpack 可以確定哪些代碼是未被使用的"死代碼"。
- 代碼移除:最后,Webpack 會從構建包中移除這些未使用的代碼,從而減小最終文件的大小。
webpack 構建流程
- 初始化各種參數,讀取配置文件,進行解析。各種merge…,形成標準化的配置
- 開始編譯:complier 對象初始化,注冊所有的配置插件,執行run方法開始編譯
- 從 entry 開始,讀取所有的依賴樹,形成 AST。不斷地遞歸下去進行處理。
- 文件編譯:根據文件正則匹配對應的 loader,進行文件轉換
- 形成一個整體的資源樹,完成模塊的編譯
- 輸出資源:根據入口和模塊的關系,組成一個個的chunk,再把每個 chunk 轉換成單獨的文件,準備輸出。
- 輸出完成,根據 output 配置的內容,把文件最后,寫入到磁盤。
- webpack的hooks:中間不同時段會有不同的plugin執行
loader 和 plugin 的區別?
loader: 轉換器,核心是解析.
webpack 沒有 loader 的話,只能打包基礎的 cjs的 js 文件,對于 css,靜態資源 是無法實現打包的,這時候就需要引入 一些 loader 來進行文件的處理,更多的是,文件的轉換器。
plugin: 插件,主要是擴展webpack 的功能,在 webpack 的運行周期里,會有一些 hooks 對外暴露,所以在webpack 打包編譯的過程中, plugin 會根據這些 hooks 執行一些自定義的操作,來實現對輸出結果的干預的增強。
區別:
loader 更專注于 文件的轉換,是轉換器,讓 webpack 處理非JS 模塊plugin 更專注于 流程的擴展,是擴展器。讓輸出資源的能力更豐富。
webpack中hash、chunkhash和contenthash的區別
- hash:一整個項目,一次打包,只有一個hash值
- chunkhash:一個入口打包出來的文件所得到的是同一個chunkhash
- 從入口entry出發,到它的依賴,以及依賴的依賴,依賴的依賴的依賴,等等,一直下去,所打包構成的代碼塊(模塊的集合)叫做一個chunk,也就是說,入口文件和它的依賴的模塊構成的一個代碼塊,被稱為一個chunk。
- 所以,一個入口對應一個chunk,多個入口,就會產生多個chunk
- 所以,單入口文件,打包后chunkhash和hash值是不同的,但是效果是一樣的
- contenthash:該哈希只會和文件內容有關,是控制力度最細的
如何提高 webpack 的打包速度
- 使用多進程打包: 使用 thread-loader,happypack 等工具,將構建的流程分解為多個進程或線程去處理。esbuild,swc 相關。
- 使用 dllPlugin 將第三方庫預先進行打包,減少構建;
- 使用 HardSourceWebpackPlugin, 緩存一些中間文件,加速后續的構建流程
- 使用 tree shaking
- 移除不需要的loader和不必要的插件
- cache-loader:開啟Cache-loader 實現打包緩存,對于之前讀過文件進行緩存,而不需要再去讀系統文件
如何減小 webpack 打包后的體積/性能優化
- code spliting:非首屏加載的數據,先排除掉。
- tree shaking:沒用的,先干掉
- 壓縮代碼:css 壓縮、JS 壓縮
- 圖片壓縮:gzip
- 按需引入:例如組件庫
- CDN加速:react,vue,比較大的第三方