[譯] webpack 更新日誌(一)

原文連接javascript

webpack 團隊於北京時間 10 月 14日凌晨發佈了 v5.0.0-beta.0 版本,本文譯自 webpack/changelog-v5。此部分主要面向非插件開發的 webpack 使用者。前端

簡要說明

此版本重點關注如下內容:java

  • 咱們嘗試經過持久化存儲優化構建性能。
  • 咱們嘗試採用更好的算法與 defalut 來改善長效緩存。
  • 咱們嘗試經過更好的 Tree Shaking 和代碼生成來改善 bundle 的大小。
  • 咱們嘗試清除內部結構中奇怪的代碼,同時在不影響 v4 功能基礎上實現了新特性。
  • 咱們目前嘗試經過引入破壞性更改來爲新特性作準備,以便於咱們能儘量長期地使用 v5。

遷移指南

=> 查閱遷移指南 <=node

主要更改

移除廢棄的代碼

v4 中全部廢棄的代碼均已刪除。webpack

遷移:以確保你的 webapck 4 不打印棄用警告。git

如下是已刪除但在 v4 中沒有棄用警告的內容:github

  • 如今必須爲 IgnorePlugin 和 BannerPlugin 傳遞一個 options 對象。

自動移除 Node.js Polyfills

早期,webpack 的目的是容許在瀏覽器中運行大多數 node.js 模塊,可是模塊總體格局發生了變化,如今許多模塊的主要用途是以編寫前端爲目的。webpack <= 4 附帶了許多 Node.js 核心模塊的 polyfil,一旦模塊中使用了任何核心模塊(即 」crypto「 模塊),這些模塊就會被自動啓用。web

雖然這使得爲 Node.js 編寫模塊變得簡單,但它會將超大的 polyfill 添加到 package 中。在許多狀況下,這些 polyfill 並不是必要。算法

webpack 5 會中止自動 polyfill 這些核心模塊,並專一於與前端兼容的模塊。express

遷移:

  • 儘量嘗試使用與前端兼容的模塊。
  • 能夠爲 Node.js 核心模塊手動添加 polyfill。錯誤信息將提示如何進行此操做。
  • package 做者:在 package.json 中使用 browser 字段,以使得 package 與前端代碼兼容。爲 borwser 提供可選的 implementations/dependencies。

反饋:不管是否喜歡上述修改,請都向咱們提出反饋。咱們並不肯定是否會歸入最終版本。

採用新算法生成 chunk ID 以及 module ID

添加了用於長效緩存的新算法。在生產模式下,默認啓用這些功能。

chunkIds: "deterministic", moduleIds: "deterministic"

此算法採用肯定性的方式將短數字 ID(3 或 4 個字符)分配給 modules 和 chunks。 這是基於 bundle 大小和長效緩存間的折中方案。

遷移:最好使用 chunkIdsmoduleIds 的默認值。你還能夠選擇使用舊的默認值,chunkIds: "size", modules: "size",這將生成較小的 bundle,但這會使得它們頻繁地進行緩存。

以新算法混淆 export 名稱

添加了新算法來處理 export 的名稱。默認狀況下啓用。

若是可能,它將以肯定性方式破壞 export 的名稱。

遷移:不須要進行任何操做。

爲 chunk IDs 命名

在開發模式下默認啓用,以新的算法爲 chunk id 命名,給 chunk(以及文件名)提供易於理解的名稱。 module ID 由其相對於 context 的路徑決定。 chunk ID 由 chunk 的內容決定。

所以,你再也不須要使用 import(/* webpackChunkName: "name" */ "module") 進行調試。 可是,若是你要控制生產環境的文件名,那仍可以使用。

能夠在生產中使用 chunkIds: "named",但要確保在使用時不會意外地泄露有關模塊名稱的敏感信息。

遷移:若是你不喜歡在開發中更改文件名,則能夠傳遞 chunkIds: "natural" 以使用舊的數字模式。

JSON 模塊

JSON 模塊如今符合規範,並會在使用非默認導出時發出警告。

遷移:使用 default export

(自 alpha.16 起)

嵌套 tree-shaking

webpack 如今能夠追蹤對 exports 嵌套屬性的訪問。從新導出 namespace 對象,這能夠改善 Tree Shaking 操做(未使用 export elimination 和 export mangling)。

// inner.js
export const a = 1;
export const b = 2;

// module.js
import * as inner from "./inner";
export { inner }

// user.js
import * as module from "./module";
console.log(module.inner.a);
複製代碼

在此示例中,能夠在生成模式下移除 export b

(從 alpha.15 起)

內部模塊(inner-module) tree-shaking

webpack 4 沒有分析模塊 export 與 import 之間的依賴關係。webpack 5 有一個新的選項 optimization.innerGraph,該選項在生產模式下默認啓用,它對模塊中的符號進行分析以找出從 export 到 import 的依賴關係。

以下述模塊所示:

import { something } from "./something";

function usingSomething() {
  return something;
}

export function test() {
  return usingSomething();
}
複製代碼

內部圖算法將肯定僅在使用 export 的 test 時使用 something。這樣能夠將更多 export 標記爲未使用,並從 bundle 中刪除更多的代碼。

若是設置了 "sideEffects": false,則能夠省略更多模塊。在此示例中,當未使用 export 的 test 時,將忽略 ./something

如需獲取有關未使用的 export 的信息,需使用 optimization.unusedExports。如需刪除無反作用的模塊,需使用 optimization.sideEffects

此方式能夠分析如下符號:

  • 函數聲明(function declarations)
  • class 聲明(class declarations)
  • 帶有 export default 或帶有變量聲明(variable declarations)的
    • 函數表達式(function expressions)
    • class 語句(class expressions)
    • /*#__PURE__*/ 表達式
    • 局部變量(local variables)
    • imported bindings

反饋:若是您發現此分析中缺乏某些內容,請反饋 issues,咱們考慮將其添加。

此優化也稱爲深度做用域分析(Deep Scope Analysis)。

(自 alpha.24 起)

編譯器空閒並關閉(idle and close)

如今須要再使用編譯器(compilers)後將其關閉。編譯器具備 enter 和 leave 空閒狀態,並具備這些狀態的 hook。插件可使用這些 hook 執行不重要的工做。(即,持久化緩存將延遲存儲到磁盤)。在編譯器關閉時,全部剩餘工做應儘快完成。回調執行時,代表關閉已完成。

插件及其各自的做者應該會指望某些用戶可能會忘記關閉編譯器。所以,全部工做最終也應該在空閒時完成。當工做完成時,應防止進程退出。

當傳遞 callback 時,webpack() 實例會自動調用 close

遷移:使用 node.js API 時,請確保在完成後調用 Complier.close

改進代碼生成

此版本添加了新的選項 output.ecmaVersion。它容許爲 webpack 生成的運行時代碼指定最大 EcmaScript 版本。

webpack 4 僅能於生成 ES5 的代碼。webpack 5 現支持 ES5 或 ES2015 的代碼。

默認配置將生成 ES2015 的代碼。若是你須要支持舊版瀏覽器(例如,IE11),則能夠將其降爲 output.ecmaVersion: 5

設置爲 output.ecmaVersion: 2015 將使用箭頭函數生成較短的代碼,以及更多符合規範的代碼,使用 const 聲明(TDZ)做爲 export default

(自 alpha.23 起)

生產模式中的默認壓縮(default minimizing)也使用 ecmaVersion 選項生成較小的代碼。(自 alpha.31 起)

chunk 分割以及 module size

與以前展現單個數值相比,模塊如今以更好的方式展現其 size。除此以外,如今也擁有了不一樣類型的 size。

目前,SplitChunksPlugin 已知道如何處理這些不一樣的 size,並將它們應用於 minSizemaxSize。 默認狀況下,僅處理 javascript 的 size,但你能夠傳遞多個參數來管理它們:

minSize: {
	javascript: 30000,
	style: 50000,
}
複製代碼

遷移:檢查構建中使用了哪些類型的 size,並在 splitChunks.minSize 和可選的 splitChunks.maxSize 中進行配置。

持久化緩存

目前包含文件系統緩存。它是可選的,能夠經過如下配置啓用:

cache: {
  // 1. 設置緩存類型爲 filesystem
  type: "filesystem",

  buildDependencies: {
    // 2. 將你的配置添加爲 buildDependency 以在更改配置時,使得緩存失效。
    config: [__filename]

    // 3. 若是你還有其餘須要構建的內容,能夠在此處添加它們
    // 請注意,loader 和全部模塊中配置中引用的內容會自動添加
  }
}
複製代碼

重要內容

默認狀況下,webpack 會假定其所處的 node_modules 目錄由包管理器修改。針對 node_modules 目錄,將跳過哈希和時間戳處理。出於性能方面考慮,僅使用 package 的名稱和版本。symlinks(例如,npm/yarn link)很友好。除非你使用 cache.managedPaths: [] 選項取消此優化,不然請不要直接在 node_modules 中編輯文件。

默認狀況下,緩存將分別存儲在 node_modules/.cache/webpack 中(當使用 node_modules 時)和 .pnp/.cache/webpack(當使用 Yarn PnP 時,自 alpha.21 起)。你可能永遠沒必要手動刪除它。

(自 alpha.20 起)

當使用 Yarn PnP webpack 時,若是 yarn 的緩存不可變(一般不會發生變化)。你能夠經過 cache.immutablePaths: [] 退出此優化。

(自 alpha.21 起)

用於 single-file-target 的 chunk 分割

目前,僅容許啓動單個文件 target(如 node,WebWorker,electron main)支持在運行時自動加載引導程序所需的相關代碼片斷。

這容許對帶有 chunks: "all" 的 target 使用 splitChunks

值得注意的是,因爲 chunk 加載是異步的,所以這也會使初始估算也爲異步操做。當使用 output.library 時,這可能會出現問題,由於導出的值的類型目前爲 Promise。從 alpha.14 開始,這將不適用於 target: "node",由於 chunk 加載在此 target 下爲同步。

(自 alpha.3 起)

更新解析器

enhanced-resolve 已更新至 v5。具體改進以下:

  • 當使用 Yarn PnP 時,解析器將直接處理無需其餘插件
  • 此 resolve 可追蹤更多的依賴項,例如文件缺失
  • 別名(aliasing)可能包含多種選擇
  • 能夠設置別名(aliasing)爲 false
  • 性能提高

(自 alpha.18 起)

不包含 JS 的 chunk

不包含 JS 代碼的 chunk 將再也不生成 JS 文件。

(自 alpha.14 起)

實驗階段特性

並不是全部特性從開始就文檔。在 webpack 4 中,咱們添加了實驗性功能,並在 changelog 中指出它們是實驗性的,可是從配置中並不能很清楚的瞭解這些功能是實驗性的。

在 webpack 5 中,有一個新的 experiments 配置項,容許啓用實驗性功能。這樣能夠清楚地瞭解啓用/使用了哪些實驗特性。

雖然 webpack 遵循語義版本控制,可是實驗性功能將成爲例外。它可能包含 webpack 次要版本的破壞性更改。發生這種狀況時,咱們將在 changelog 中添加清晰的註釋。這促使咱們能夠更快地迭代實驗性功能,同時還可使用咱們在主要版本上停留更長時間以得到穩定的功能。

如下實驗性功能將隨 webpack 5 一同發佈:

  • 像 webpack 4 同樣對 .mjs 提供支持(experiments.mjs
  • 像 webpack 4 同樣對舊版 WebAssembly 提供支持(experiments.syncWebAssembly
  • 根據更新規範 對新版 WebAssembly 提供支持(experiments.asyncWebAssembly
    • 這使得 WebAssembly 模塊成爲異步模塊
  • Top Level Await Stage 3 階段提案(experiments.topLevelAwait
    • 在頂層使用 await 使模塊成爲異步模塊
  • 使用 import 引入異步模塊(experiments.importAsync
  • 使用 import await 引入異步模塊(experiments.importAwait
  • asset 模塊相似相似於 file-loaderexperiments.asset)(自 alpha.19 起)
  • 導出 bundle 做爲模塊(experiments.outputModule)(自 alpha.31 起)
    • 這將從 bundle 中移除 IIFE 的包裝器,強制執行嚴格模式,經過 <script type="module"> 進行懶加載,並在 module 模式下將其進行壓縮

請注意,這也意味着針對 .mjs 的支持和 WebAssembly 的支持將被默認禁用

(自 alpha.15 起)

Stats

chunk 間關係默認狀況下是隱藏的。可使用 stats.chunkRelations 進行切換。

(自 alpha.1 起)

Stats 現階段能夠區分 filesauxiliaryFiles

(自 alpha.19 起)

默認狀況下,Stats 會隱藏模塊和 chunk id。可使用 stats.ids 進行切換。

全部模塊的列表均按照到 entrypoint 的距離排序。可使用 stats.modulesSort 進行切換。

chunk 模塊列表和 chunk 根模塊列表分別根據模塊名進行排序。能夠分別使用 stats.chunkModulesSortstats.chunkRootModulesSort 進行更改。

在串聯模塊中,嵌套模塊列表進行拓撲排序。能夠經過 stats.nestedModulesSort 進行更改。

chunks 和 assets 會顯示 chunk id 的提示。

(自 alpha.31 起)

最低 Node.js 版本

Node.js 的最低支持版本從 6 變動爲 8。

遷移:升級到最新的 node.js 可用版本。

配置變動

結構變動

  • 移除 cache: Object:不能設置爲內存緩存對象
  • 添加 cache.type:能夠設置爲 "memory""filesystem"
  • cache.type = "filesystem" 添加新配置項:
    • cache.cacheDirectory
    • cache.name
    • cache.version
    • cache.store
    • ~cache.loglevel~(自 alpha.20 起被移除)
    • cache.hashAlgorithm
    • cache.idleTimeout(自 alpha.8 起)
    • cache.idleTimeoutForIntialStore(自 alpha.8 起)
    • cache.managedPaths(自 alpha.20 起)
    • cache.immutablePaths(自 alpha.21 起)
    • cache.buildDependencies(自 alpha.20 起)
  • 添加 resolve.cache:容許禁用/啓用安全 resolve 緩存
  • 移除 resolve.concord
  • 移除用於原生 node.js 模塊自動的 polyfill
    • 移除 node.Buffer
    • 移除 node.console
    • 移除 node.process
    • 移除 node.*(node.js 原生模塊)
    • 遷移:使用 resolve.aliasProvidePlugin。發生錯誤會給出提示。
  • output.filename 能夠賦值函數(自 alpha.17 起)
  • 添加 output.assetModuleFilename(自 alpha.19 起)
  • resolve.alias 的值能夠爲數組或 false(自 alpha.18 起)
  • 添加 optimization.chunkIds: "deterministic"
  • 添加 optimization.moduleIds: "deterministic"
  • 添加 optimization.moduleIds: "hashed"
  • 添加 optimization.moduleIds: "total-size"
  • 移除 module 和 chunk id 的相關的棄用選項
    • 移除 optimization.hashedModuleIds
    • 移除 optimization.namedChunksNamedChunksPlugin 與之相同)
    • 移除 optimization.namedModulesNamedModulesPlugin 與之相同)
    • 移除 optimization.occurrenceOrder
    • 遷移:使用 chunkIdsmoduleIds
  • optimization.splitChunks test 不在匹配 chunk 名
    • 遷移:使用 test 函數 (module, { chunkGraph }) => chunkGraph.getModuleChunks(module).some(chunk => chunk.name === "name")
  • optimization.splitChunks 中添加 minRemainingSize(自 alpha.13 起)
  • optimization.splitChunks filename 能夠賦值函數 (since alpha.17)
  • optimization.splitChunks sizes 能夠爲每一個源類型的 size 對象
    • minSize
    • minRemainingSize
    • maxSize
    • maxAsyncSize(自 alpha.13 起)
    • maxInitialSize
  • optimization.splitChunks 中添加 maxAsyncSizemaxInitialSize:容許爲初始和異步 chunk 指定不一樣的最大 size。
  • 移除 optimization.splitChunks 中的 name: true:再也不支持自動命名
    • 遷移:使用默認值。chunkIds: "named" 將爲你的文件提供有用的名稱以便於調試
  • 添加 optimization.splitChunks.cacheGroups[].idHint:將提示如何命名 chunk id
  • 移除 optimization.splitChunks 中的 automaticNamePrefix
    • 遷移:使用 idHint 替代
  • optimization.splitChunks 中的 filename 再也不侷限於初始 chunk(自 alpha.11 起)
  • 添加 optimization.mangleExports(自 alpha.10 起)
  • 移除 output.devtoolLineToLine
    • 遷移:無替代方式
  • output.hotUpdateChunkFilename: Function 如今被禁止:不會生效。
  • output.hotUpdateMainFilename: Function 如今被禁止:不會生效。
  • module.rules 中的 resolveparser 將以不一樣的方式合併(對象會進行深度合併,數組將採用 "..." 進行展開以獲取以前的值)(自 alpha.13 起)
  • module.rules 中的 queryloaders 已被移除(自 alpha.13 起)
  • 添加 stats.chunkRootModules:展現 chunk 的根模塊
  • 添加 stats.orphanModules:展現未觸發的模塊。
  • 添加 stats.runtime:展現 runtime 模塊
  • 添加 stats.chunkRelations:顯示 parent/children/sibling chunk(自 alpha.1 起)
  • 添加 stats.preset:選擇 preset(自 alpha.1 起)
  • BannerPlugin.banner 簽名變動
    • 移除 data.basename
    • 移除 data.query
    • 遷移:從 filename 中進行提取
  • 移除 SourceMapDevToolPlugin 中的 lineToLine
    • 遷移:無替代方式
  • [hash] 不支持完整編譯的 hash
    • 遷移:使用 [fullhash] 或採用更好的 hash 選項
  • [modulehash] 被廢棄
    • 遷移:使用 [hash] 代替
  • [moduleid] 被廢棄
    • 遷移:使用 [id] 代替
  • 移除 [filebase]
    • 遷移:使用 [base] 代替
  • 基於文件模板的新佔位符(即 SourceMapDevToolPlugin)
    • [name]
    • [base]
    • [path]
    • [ext]
  • 當向 externals 傳遞一個函數時,它將具備不一樣的函數簽名 ({ context, request }, callback)
    • 遷移:更改函數簽名
  • 添加 experiments(請參閱上述實驗部分,自 alpha.19 起)
  • 添加 watchOptions.followSymlinks(自 alpha.19 起)

默認值變動

  • 默認狀況下,僅對 node_modules 啓用 module.unsafeCache
  • 在生產模式下,optimization.moduleIds 的默認值從 size 替換爲 deterministic
  • 在生產模式下,optimization.chunkIds 的默認值從 total-size 替換爲 deterministic
  • none 模式下,optimization.nodeEnv 默認爲 false
  • optimization.splitChunks 中的 minRemainingSize 默認爲 minSize(自 alpha.13 起)
    • 若是剩餘部分太小,這將減小建立 chunk 的數量
  • 當使用 cache 時,resolve(Loader).cache 默認爲 true
  • resolve(Loader).cacheWithContext 默認爲 false
  • ~node.global 默認爲 false~(自 alpha.4 起被移除)
  • resolveLoader.extensions 移除 .json(自 alpha.8 起)
  • 當 node-target 時,node.global 中的 node.__filenamenode.__dirname 默認爲 false(自 alpha.14 起)

勘誤

如對譯文有疑問,歡迎評論或點擊閱讀原文。

關注咱們

相關文章會在公衆號首發,掃描下方二維碼關注咱們,咱們將提供前端相關最新最優含量的資訊。

相關文章
相關標籤/搜索