原文首發於 blog.flqin.com。若有錯誤,請聯繫筆者。分析碼字不易,轉載請代表出處,謝謝!css
前面一至十一章,介紹了在 development
的模式下,整個完整了構建主流程。在瞭解構建流程的基礎上,本章整理一些與 webpack
優化相關的知識點。html
咱們參考 production
模式裏,裏面已經作了大部分的優化,如壓縮,Scope Hoisting
, tree-shaking
等給予咱們啓發,接下來具體分析各個點。webpack
FlagDependencyUsagePlugin
compilation.hooks.optimizeDependencies
module.usedExports
裏。用於 Tree shaking
。optimization.usedExports:true
FlagIncludedChunksPlugin
compilation.hooks.optimizeChunkId
chunk
添加了 ids
,用於判斷避免加載沒必要要的 chunk
ModuleConcatenationPlugin
compilation.hooks.optimizeChunkModules
esm
語法能夠做用域提高(Scope Hoisting
)或預編譯全部模塊到一個閉包中,提高代碼在瀏覽器中的執行速度optimization.concatenateModules:true
NoEmitOnErrorsPlugin
compiler.hooks.shouldEmit
,compilation.hooks.shouldRecord
compilation
編譯時有 error
,則不執行 Record
相關的鉤子,而且拋錯和不編譯資源OccurrenceOrderModuleIdsPlugin
,OccurrenceOrderChunkIdsPlugin
SideEffectsFlagPlugin
normalModuleFactory.hooks.module
,compilation.hooks.optimizeDependencies
normalModuleFactory.hooks.module
鉤子裏讀取 package.json
裏的 sideEffects
字段和讀取 module.rule
裏的 sideEffects
賦給 module.factoryMeta
(純的 ES2015
模塊);compilation.hooks.optimizeDependencies
鉤子里根據 sideEffects
配置,刪除未用到的 export
導出optimization.sideEffects:true
(默認)TerserPlugin
template.hooks.hashForChunk
,compilation.hooks.optimizeChunkAssets
template.hooks.hashForChunk
鉤子即在 chunks
生成 hash
階段會把壓縮相關的信息也打入到裏面compilation.hooks.optimizeChunkAssets
鉤子觸發資源壓縮事件optimization.minimize
是否開啓壓縮optimization.minimizer
定製 Terser
另:development
模式單獨啓用的插件:git
NamedChunksPlugin
compilation.hooks.beforeChunkIds
chunk id
optimization.chunkIds
NamedModulesPlugin
compilation.hooks.beforeModuleIds
module id
optimization.moduleIds
在更新部署頁面資源時,不管是先部署頁面,仍是先部署其餘靜態資源,都會由於新老資源替換後的緩存緣由,或者部署間隔緣由,都會致使資源不對應而引發頁面錯誤。github
持久化緩存方案就是在各靜態資源的名字後面加惟一的 hash
值,這樣在每次修改文件後生成的不一樣的 hash
值,而後在增量式發佈文件時,就能夠避免覆蓋掉以前舊的文件。獲取到新文件的用戶就能夠訪問新的資源,而瀏覽器有緩存等狀況的用戶則繼續訪問老資源,保證新老資源同時存在且互不影響不出錯。web
html
:不開啓緩存,把 html
放到單獨的服務器上並關閉服務器的緩存,須要保證每次的 html
都爲最新js
,css
,img
等其餘靜態資源:開啓緩存,將靜態資源上傳到 cdn
,對資源開啓長期緩存,由於有惟一 hash
的緣故因此不會致使資源被覆蓋,用戶在初次訪問能夠將這些長效緩存下載到本地,而後在後續的訪問能夠直接從緩存裏讀,節約網絡資源。js
使用 chunkhash
,對 css
應用 mini-css-extract-plugin
插件並使用 contenthash
optimization.moduleIds
屬性設置 module id
moduleIds
設爲 named
即便用 NamedModulesPlugin
(相對路徑爲 key
)來固化 module id
,moduleIds
設爲 hashed
即便用 HashedModuleIdsPlugin
(將路徑轉換爲 hash
爲 key
)來固化 module id
,保證在某一模塊增刪後,不會影響其餘模塊的 module id
optimization.chunkIds
屬性設置爲 named
或 optimization.namedChunks
屬性設置爲 true
(經過將 chunk name
複製到 chunk id
)固化 chunk id
,該屬性會啓用 NamedChunksPlugin
NamedChunksPlugin
插件裏能夠自定義 nameResolver
設置 name
splitChunks.cacheGroups[].name
也能夠設置 chunk name
import(/* webpackChunkName: "my-chunk-name" */ 'module')
optimization.splitChunks
屬性抽離庫 vendor
,業務公共代碼 common
optimization.runtimeChunk
屬性抽離運行時 runtime
,其中 runtime
也能夠經過 script-ext-html-webpack-plugin
插件嵌入到 html
Tree Sharing
是一個術語,一般用於描述移除 JavaScript
上下文中的未引用代碼(dead-code
)。由 rollup 普及,在 webpack
裏由 TerserPlugin
實現。json
ES6
的模塊引入是靜態分析的,故而能夠在編譯時正確判斷到底加載了什麼代碼若是咱們引入的模塊被標記爲 sideEffects: false
,只要它任意一個導出都沒有被其餘模塊引用到,那麼無論它是否真的有反作用,整個模塊都會被完整的移除。api
"
side effect
(反作用)" 的定義是,在導入時會執行特殊行爲的代碼,而不是僅僅暴露一個export
或多個export
。舉例說明,例如polyfill
,它影響全局做用域,而且一般不提供export
。瀏覽器
tree shaking
須要知足ES2015
模塊語法(即 import
和 export
),目的是爲了供程序靜態分析compiler
將 ES2015
模塊語法轉換爲 CommonJS
模塊(設置 babel.config.js
presets: [['@babel/env', { modules: false }]]
)package.json
或者 module.rule
設置 sideEffects : false
,告訴 webpack
該項目或者該文件沒有反作用production
,其中會啓用 FlagDependencyUsagePlugin
,TerserPlugin
完成 tree shaking
Scope Hoisting
即 做用域提高,可讓 webpack
打包出來的代碼文件更小,運行更快。緩存
ES6
的靜態模塊分析,分析出模塊之間的依賴關係,按照引用順序儘量地把模塊放到同一個函數做用域中,而後適當的重命名一些變量以防止變量名衝突。
異步
import()
不會啓用Scope Hoisting
ES2015
模塊語法(即 import
和 export
)mode
選項設置爲 production
,其中會啓用 ModuleConcatenationPlugin
插件完成 Scope Hoisting
如下列舉部分我用過優化相關的插件及 loader
:
css
樣式到單獨文件HtmlWebpackPlugin
,將 css
內聯到 html
裏HtmlWebpackPlugin
,將 js
內聯到 html
裏css
DataURL
,減小請求數各插件隨着時間推移,有的可能廢棄,有的可能被更好的所替代,已社區流行爲準。
從 webpack
源碼開始,到後面打包結果分析,watch
, webpack
優化總結等,前先後後花了一個月的時間,但收穫也頗多。因爲對 webpack
底層有了認知,海量配置也清楚具體實現,不用死記硬背了;因爲對 webpack
底層有了認知,因此遇到的各類構建問題都能定位到是構建的哪一步;因爲對 webpack
底層有了認知,也可以很快速的根據業務寫一些針對性的 loader
和 plugin
;最重要的是經過對源碼分析,大型工程的組織架構,擴展性,健壯性等給人帶來一些新的思路和啓發。
本系列到此結束,後續會不斷的更新優化。對 webpack
源碼的分析解除了我心中不少的構建相關的疑惑,整我的都昇華了。因此每一個人精力、時間都有限,選擇作本身喜歡的事情,方爲上策。
若有錯誤,請聯繫筆者。分析碼字不易,轉載請代表出處,謝謝!