在 webpack 3 釋出 之後, webpack 團隊向社群承諾,之後 webpack 主版本的迭代會有一個時間比較長且穩定的開發週期。而在2017年8月份的時候,webpack 團隊從 master
分支切出了 next
分支用於 webpack 4 的開發,經歷 5 個月的開發週期之後,webpack 4.0-beta 在 2018年1月 已經 Released 了,不僅兌現了之前的承諾,還帶來了諸多新特性,在使用者使用的體驗上也作了諸多改進。
安裝
如果需要使用 webpack 4,則需要從 next
分支上安裝:
1 2 3 4 5 |
// yarn yarn add webpack<a href="http://www.jobbole.com/members/q3538679238">@next</a> webpack-cli --dev // npm npm install webpack<a href="http://www.jobbole.com/members/q3538679238">@next</a> webpack-cli --save-dev |
不完全遷移指北
環境
不再支援 Node.js 4。
根據
package.json
配置, Node.js 的最低支援版本為6.11.5
模組型別
webpack 4之前,js 是 webpack 中的唯一模組型別,因而不能有效地打包其它型別的檔案。而 webpack 4 則提供了 5 種模組型別:
javascript/auto
: (webpack 3中的預設型別)支援所有的JS模組系統:CommonJS、AMD、ESMjavascript/esm
: EcmaScript 模組,在其他的模組系統中不可用(預設.mjs
檔案)javascript/dynamic
: 僅支援 CommonJS & AMD,EcmaScript 模組不可用json
: 可通過require
和import
匯入的 JSON 格式的資料(預設為.json
的檔案)webassembly/experimental
: WebAssembly 模組(處於試驗階段,預設為.wasm
的檔案)
此外,webpack 4 中會預設解析 .wasm
, .mjs
, .js
和 .json
為字尾的檔案。
在對應檔案的 loader 配置,需要增加 type
欄位來指定模組型別:
1 2 3 4 5 6 7 |
module: { rules: [{ test: /\.special\.json$/, type: "javascript/auto", use: "special-loader" }] } |
javascript/auto
/ javascript/esm
都可以處理 ESM, 但後者會更加嚴格:
- 匯入的名稱必須存在於匯入的模組中
- 動態的模組(非 ESM,如 CommonJS)只能通過預設
import
匯入,其它方式(包括名稱空間)的匯入都會報錯
對於 WebAssembly 模組:
- 可以匯入其它模組(JS 和 WASM)
- 試圖在 WASM 模組中匯入不存在的模組將會得到一個警告或者錯誤
- ESM 可以引入 WASM 模組中匯出的模組名
- 僅可在 async chunks(通過
import()
匯入的模組)中使用,在 initial chunks 中是無效的(不利於提升 web 應用的效能)
import()
: 動態匯入
在 webpack 4 中,import()
會返回一個帶名稱空間(namespace
)的物件,這對 ES Module 不會有影響,但對於遵循 commonjs
規範的模組則會加一層包裹:
1 2 3 4 5 6 7 8 9 |
// webpack 2/3 import("./commonjs").then(exports => { ... }) // webpack 4 import("./commonjs").then({default: exports}=> { ... }) |
mode
: 模式配置
mode
是 webpack 4 中新增加的引數選項,其有兩個可選值:production
和 development
。mode
不可預設,需要二選一:
production
模式:- 預設提供所有可能的優化,如程式碼壓縮/作用域提升等
- 不支援
watching
process.env.NODE_ENV
的值不需要再定義,預設是production
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** webpack.production.config.js **/ // webpack 2/3 module.exports = { plugins: [ new UglifyJsPlugin(/* ... */), new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), new webpack.optimize.ModuleConcatenationPlugin(), new webpack.NoEmitOnErrorsPlugin() ] } // webpack 4 module.exports = { mode: 'production' } |
development
模式:- 主要優化了增量構建速度和開發體驗
process.env.NODE_ENV
的值不需要再定義,預設是development
- 開發模式下支援註釋和提示,並且支援 eval 下的 source maps
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** webpack.development.config.js **/ // webpack 2/3 module.exports = { plugins: [ new webpack.NamedModulesPlugin(), new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }) ] } // webpack 4 module.exports = { mode: 'development' } |
此外, webpack 4 還提供一種隱藏(
none
)模式,這種模式下會禁用一切優化
sideEffects 設定
webpack 4 在 package.json
中引入了對 sideEffects: false
的支援。當模組的 package.json
中新增該欄位時,表明該模組沒有副作用,也就意味著 webpack 可以安全地清除被用於重複匯出(re-exports)的程式碼。
JSON
webpack 4 不僅支援本地處理 JSON,還支援對 JSON 的 Tree Shaking。當使用 ESM 語法 import
json 時,webpack 會消除掉JSON Module 中未使用的匯出。
此外,如果要用 loader 轉換 json 為 js,需要設定 type
為 javascript/auto
:
1 2 3 4 5 6 7 |
module.rules: [ { test: /\.special\.json$/, type: "javascript/auto", use: "special-loader" } ] |
配置
- 刪除了一些常用內建外掛:
- NoEmitOnErrorsPlugin -> optimization.noEmitOnErrors (生產模式預設)
- ModuleConcatenationPlugin -> optimization.concatenateModules (生產模式預設)
- NamedModulesPlugin -> optimization.namedModules (開發模式預設)。
- 刪除了 CommonsChunkPlugin,取而代之的是
optimization.splitChunks
和optimization.runtimeChunk
,這提供了細粒度的快取策略控制
- 可以使用
module.rules[].resolve
來配置解析,它會與全域性配置合併。 optimization.minimize
用於控制 minimizing 的開關。 生產模式預設為開,開發模式預設為關。optimization.minimizer
用於配置 minimizers 和選項。- 許多支援佔位符(placeholders)的配置選項現也支援函式形式
- 錯誤的
options.dependencies
配置將報錯 sideEffects
可以通過module.rules
覆蓋output.hashFunction
可以是一個建構函式,用於自定義 hash 函式。處於效能考慮,也可以提供非加密雜湊函式output.globalObject
可以用於配置執行時的全域性物件引用- 預設配置
- webpack 預設會按照
.wasm
,.mjs
,.js
和.json
的副檔名順序查詢模組。 output.pathinfo
在開發模式下預設是開啟的- 生產環境下,預設關閉記憶體快取
entry
的預設值是./src
,output.path
的預設值是./dist
- 在選擇模式選項時,預設值是
production
- webpack 預設會按照
優化
uglifyjs-webpack-plugin
釋出 v1,支援 ES2015- 使用 JSONP 陣列來代替 JSONP 函式 –> 非同步支援
- webpack 自身也可以刪除無用程式碼。webpack 2/3 中是在 Uglify 時刪除無用程式碼,webpack 4 中 webpack 也可以(在某些情況下)刪除無用程式碼,避免
import()
引用無用程式碼時導致的奔潰 - 作用域提升後的模組將生成更少的程式碼
效能
- 預設情況,UglifyJS 會預設快取和並行化(完全實現快取和並行化將在 webpack 5 中實現)
- 多個效能改進,尤其是在增量構建這方面
- 改進了
RemoveParentModluesPlugin
的效能 - 未使用模組不再有非必要的作用域提升
- 新增 ProfilingPlugin,此外掛會(在 Chrome 瀏覽器中)建立一個包含各外掛時間消耗的檔案
for of
代替forEach
;Map/Set
代替Objects
;includes
代替indexOf
- 同一個任務只會進入佇列一次
完整的效能改善和優化列表可以參考 Release 4.0-beta.0
移除的功能
- 移除了
module.loaders
- 移除了
loaderContext.options
- 移除了
Compilation.notCacheable
- 移除了
NoErrorsPlugin
- 移除了
Dependency.isEqualResource
- 移除了
NewWatchingPlugin
- 移除了
CommonsChunkPlugin