Webpack 5 發行(2020-10-10)

Webpack 4 於 2018 年 2 月發布。自此之後,我們發布許多功能,且未進行重大變更。我們知道人們不喜歡重大變更。尤其是 webpack,人們通常一年只會接觸兩次,其餘時間它「都能正常運作」。但發布功能且不進行重大變更也需要付出代價:我們無法進行重大的 API 或架構改善。

因此,有時會出現困難堆積如山,我們被迫進行重大變更,以免搞得一團糟。這就是新主要版本的時候。因此,webpack 5 包含這些架構改善,以及在沒有這些改善的情況下無法實作的功能。

主要版本也是修改一些預設值,以及與這段期間提出的提案和規格保持一致的機會。

因此,今天 (2020-10-10) 發布 webpack 5.0.0,但這並不表示它已完成、沒有錯誤,甚至功能齊全。與 webpack 4 一樣,我們會持續修正問題和新增功能來進行開發。在接下來的幾天,可能會修正許多錯誤。功能會在稍後推出。

常見問題

那麼,這個版本發布代表什麼意思?

這表示我們已完成重大變更。已進行許多重構,以提升架構等級,並為未來功能(以及目前功能)建立良好的基礎。

那麼什麼時候是升級的時機?

這取決於情況。升級失敗的機率很高,你可能需要嘗試第二次或第三次。如果你願意接受這樣的風險,請嘗試立即升級,並提供回饋給 webpack、外掛和載入器。我們渴望解決這些問題。總得有人先開始,而你將會是首批受益者之一。

贊助更新

Webpack 完全仰賴贊助。它不像其他一些開源專案,與大型企業綁定(並由其支付費用)。99% 的贊助收益會根據貢獻者的貢獻,分配給貢獻者和維護者。我們相信投資這筆資金,可以讓 webpack 變得更好。

但現在疫情肆虐,企業不再願意提供贊助。Webpack 也因此遭受影響(就像許多其他公司和個人一樣)。

我們從來沒有辦法支付我們認為貢獻者應得的金額,但現在我們只有以前一半的資金可用,因此我們需要進行更嚴格的削減。在情況好轉之前,我們只會在每個月的前 10 天支付貢獻者和維護者的費用。在剩下的時間裡,他們可以自願工作、由雇主支付費用、從事其他工作或休假。這讓我們能夠在頭 10 天支付他們與投入時間更相等的費用。

最感謝的對象是trivago,在過去 3 年裡,他們贊助了 webpack 大筆資金。遺憾的是,由於受到新冠肺炎疫情的嚴重衝擊,他們今年無法繼續提供贊助。我希望其他公司能站出來,追隨這些(巨大的)腳步。

感謝所有贊助者

一般方向

此版本著重於下列事項

  • 透過持續快取改善建置效能。
  • 透過更佳演算法和預設值改善長期快取。
  • 透過更佳的樹狀搖晃和程式碼產生改善套件大小。
  • 改善與網路平台的相容性。
  • 清除在 v4 中實作功能時遺留的奇怪狀態的內部結構,且不會引入任何重大變更。
  • 透過立即引入重大變更來為未來功能做好準備,讓我們能盡可能維持在 v5。

移轉指南

請參閱此處的移轉指南

重大變更:移除

移除已棄用的項目

已移除 v4 中所有已棄用的項目。

移轉:請確定您的 webpack 4 建置不會列印已棄用警告。

以下是 v4 中已移除但沒有已棄用警告的幾項內容

  • IgnorePlugin 和 BannerPlugin 現在只能傳遞一個引數,可以是物件、字串或函式。

已棄用代碼

新的已棄用項目包含已棄用代碼,以便更容易參照。

已棄用語法

require.include 已棄用,且在使用時預設會發出警告。

行為可以使用 Rule.parser.requireInclude 變更為允許、已棄用或停用。

已移除自動 Node.js 多重填補

早期,webpack 的目標是允許在瀏覽器中執行大部分 Node.js 模組,但模組環境已改變,現在許多模組用途主要都是為前端目的而撰寫。Webpack <= 4 內建許多 Node.js 核心模組的 polyfill,只要模組使用任何核心模組(例如 crypto 模組),這些 polyfill 就會自動套用。

雖然這讓使用為 Node.js 撰寫的模組變得更容易,但會將這些龐大的 polyfill 加入套件。在許多情況下,這些 polyfill 都是不必要的。

Webpack 5 停止自動為這些核心模組進行 polyfill,並專注於與前端相容的模組。我們的目標是改善與網路平台的相容性,而 Node.js 核心模組在網路平台上並不可用。

移轉:

  • 請盡可能使用與前端相容的模組。
  • 可以手動為 Node.js 核心模組加入 polyfill。錯誤訊息會提供如何達成此目標的提示。
  • 套件作者:在 package.json 中使用 browser 欄位,讓套件與前端相容。為瀏覽器提供替代實作/相依性。

重大變更:長期快取

確定性的區塊、模組 ID 和匯出名稱

已新增新的演算法,用於長期快取。這些演算法在生產模式下預設啟用。

chunkIds: "deterministic" moduleIds: "deterministic" mangleExports: "deterministic"

這些演算法會以確定性的方式將簡短(3 或 5 位數字)的數字 ID 指派給模組和區塊,並將簡短(2 個字元)的名稱指派給匯出。這是套件大小和長期快取之間的權衡。

moduleIds/chunkIds/mangleExports: false 停用預設行為,且使用者可以透過外掛提供自訂演算法。請注意,在 webpack 4 中,moduleIds/chunkIds: false 在沒有自訂外掛的情況下會產生可運作的建置,而在 webpack 5 中,您必須提供自訂外掛。

移轉:最好對 chunkIdsmoduleIdsmangleExports 使用預設值。您也可以選擇加入舊的預設值 chunkIds: "size", moduleIds: "size", mangleExports: "size",這將產生較小的套件,但會更常使快取失效。

注意:在 webpack 4 中,雜湊模組 ID 會降低 gzip 效能。這與變更模組順序有關,且已修復。

注意:在 webpack 5 中,deterministic ID 在生產模式中預設啟用

真實內容雜湊

現在,Webpack 5 在使用 [contenthash] 時,會使用檔案內容的真實雜湊。在以前,它「只」使用內部結構的雜湊。當只有註解變更或變數重新命名時,這可能會對長期快取產生正面的影響。這些變更會在最小化後看不見。

重大變更:開發支援

命名區塊 ID

在開發模式中,預設啟用新的命名區塊 ID 演算法,讓區塊(和檔名)具有人類可讀取的名稱。模組 ID 是由其路徑決定的,相對於 context。區塊 ID 是由區塊的內容決定的。

因此,您不再需要使用 import(/* webpackChunkName: "name" */ "module") 來進行偵錯。但如果您想要控制生產環境的檔名,這仍然有意義。

可以在生產環境中使用 chunkIds: "named",但請確保不會意外地公開模組名稱的敏感資訊。

移轉:如果您不喜歡開發中變更的檔名,您可以傳遞 chunkIds: "natural" 來使用舊的數字模式。

模組聯盟

Webpack 5 新增一個稱為「模組聯盟」的新功能,允許多個 webpack 建置共同作業。從執行時期的角度來看,來自多個建置的模組將表現得像一個巨大的連接模組圖。從開發人員的角度來看,模組可以從指定的遠端建置匯入,並在最少限制下使用。

更多詳細資訊,請參閱 這個獨立指南

重大變更:新的網路平台功能

JSON 模組

JSON 模組現在與提案一致,並在使用非預設匯出時發出警告。從嚴格的 ECMAScript 模組匯入時,JSON 模組不再具有命名匯出。

移轉:使用預設匯出。

即使使用預設匯出,未使用的屬性也會被 optimization.usedExports 最佳化刪除,而屬性會被 optimization.mangleExports 最佳化混淆。

可以在 Rule.parser.parse 中指定自訂 JSON 解析器,以匯入類似 JSON 的檔案(例如 toml、yaml、json5 等)。

import.meta

  • import.meta.webpackHotmodule.hot 的別名,在嚴格的 ESM 中也可以使用
  • import.meta.webpack 是 webpack 的主要版本,以數字表示
  • import.meta.url 是目前檔案的 file: url(類似於 __filename,但作為檔案 url)

資產模組

Webpack 5 現在原生支援代表資產的模組。這些模組會將檔案發射到輸出資料夾,或將 DataURI 注入到 JavaScript 程式包中。無論哪一種方式,它們都會提供一個可供使用的 URL。

它們可以使用多種方式

  • import url from "./image.png" 並在與此類匯入相符時在 module.rules 中設定 type: "asset"。(舊方法)
  • new URL("./image.png", import.meta.url)(新方法)

選擇「新方法」語法,以便允許在沒有套件管理程式的狀況下執行程式碼。此語法也可以在瀏覽器的原生 ECMAScript 模組中使用。

原生 Worker 支援

將資產的 new URLnew Worker/new SharedWorker/navigator.serviceWorker.register 結合使用時,webpack 會自動為網頁工作執行緒建立新的進入點。

new Worker(new URL("./worker.js", import.meta.url))

語法選用允許在沒有套件管理員的情況下執行程式碼。此語法也可用於瀏覽器中的原生 ECMAScript 模組。

URI

Webpack 5 支援處理請求中的協定。

  • data: 受到支援。支援 Base64 或原始編碼。MIME 類型可對應到 module.rules 中的載入器和模組類型。範例:import x from "data:text/javascript,export default 42"
  • file: 受到支援。
  • http(s): 受到支援,但需要透過 new webpack.experiments.schemesHttp(s)UriPlugin() 選擇加入
    • 預設針對「網頁」時,這些 URI 會導致對外部資源的請求(它們是外部的)

請求中的片段受到支援:範例:./file.js#fragment

非同步模組

Webpack 5 支援所謂的「非同步模組」。這些模組並非同步評估,而是非同步且基於 Promise。

透過 import 匯入它們會自動處理,不需要額外的語法,而且幾乎不會注意到差異。

透過 require() 匯入它們會傳回一個 Promise,解析為匯出。

在 webpack 中,有多種方法可以擁有非同步模組

  • 非同步外部
  • 新規格中的 WebAssembly 模組
  • 使用頂層 Await 的 ECMAScript 模組

外部

Webpack 5 新增其他外部類型,涵蓋更多應用程式

promise:評估為 Promise 的表達式。外部模組是非同步模組,解析的值用作模組匯出。

import:使用原生 import() 來載入指定的請求。外部模組是非同步模組。

module:尚未實作,但計畫透過 import x from "..." 來載入模組。

script:透過 <script> 標籤載入網址,並從全域變數(以及其屬性,視情況而定)取得匯出。外部模組是非同步模組。

重大變更:新的 Node.js 生態系功能

解析

現在支援 package.json 中的 exportsimports 欄位。

原生支援 Yarn PnP。

請參閱 套件匯出 以取得更多詳細資訊。

重大變更:開發體驗

改善的目標

Webpack 5 允許傳遞目標清單,並支援目標版本。

範例:target: "node14" target: ["web", "es2020"]

這讓我們能夠提供 Webpack 判斷下列事項所需的所有資訊

  • 區塊載入機制,以及
  • 支援的語法,例如箭頭函式

統計資料

統計測試格式已在可讀性和詳細度方面得到改進。預設值已改進為更簡潔,且適用於大型建置。

  • 區塊關聯現在預設為隱藏。這可以用 stats.chunkRelations 切換。
  • 統計資料現在區分 filesauxiliaryFiles
  • 統計資料現在預設隱藏模組和區塊 ID。這可以用 stats.ids 切換。
  • 所有模組的清單現在依據到進入點的距離排序。這可以用 stats.modulesSort 變更。
  • 區塊模組的清單現在依據模組名稱排序。這可以用 stats.chunkModulesSort 變更。
  • 串接模組中嵌套模組的清單現在依據拓撲排序。這可以用 stats.nestedModulesSort 變更。
  • 區塊和資產現在顯示區塊 ID 提示。
  • 資產和模組將以樹狀結構顯示,而非清單/表格。
  • 一般資訊現在顯示在最後的摘要中。它顯示 webpack 版本、組態名稱和警告/錯誤數量。
  • 雜湊現在預設為隱藏。這可以用 stats.hash 變更。
  • 建置時間戳記不再預設顯示。這可以用 stats.builtAt 啟用。它將在摘要中顯示時間戳記。
  • 子編譯不再預設顯示。它們可以用 stats.children 顯示。

進度

已對 ProgressPlugin 進行一些改進,CLI 使用它進行 --progress,但也可以手動用作外掛程式。

它過去只計算已處理的模組。現在它可以計算 entries dependenciesmodules。所有這些現在都預設顯示。

它過去顯示目前已處理的模組。這導致大量的 stderr 輸出,並在某些主機上產生效能問題。這現在預設為停用(activeModules 選項)。這也減少了主機上的垃圾訊息數量。現在在建置模組期間寫入 stderr 的節流時間為 500 毫秒。

剖析模式也獲得升級,並將顯示巢狀進度訊息的時間。這使得找出導致效能問題的外掛變得更容易。

新增加的 percentBy 選項會告訴 ProgressPlugin 如何計算進度百分比。

new webpack.ProgressPlugin({ percentBy: 'entries' });

為了讓進度百分比更準確,ProgressPlugin 會快取最後已知的總模組數量,並在下次建置時重複使用這個值。第一次建置會預熱快取,但後續建置會使用並更新這個值。

自動唯一命名

在 webpack 4 中,多個 webpack 執行時間可能會在同一個 HTML 頁面中衝突,因為它們使用相同的全域變數來載入區塊。為了修復這個問題,需要為 output.jsonpFunction 設定提供自訂名稱。

Webpack 5 會自動從 package.json name 推斷出建置的唯一名稱,並將其用作 output.uniqueName 的預設值。

這個值用於讓所有潛在衝突的全域變數保持唯一性。

移轉:移除 output.jsonpFunction,改在 package.json 中使用唯一名稱。

自動公共路徑

Webpack 5 會在可能的情況下自動決定 output.publicPath

Typescript 型別

Webpack 5 會從原始碼產生 Typescript 型別,並透過 npm 套件公開它們。

移轉:移除 @types/webpack。當名稱不同時更新參照。

重大變更:最佳化

巢狀樹狀搖晃

Webpack 現在能夠追蹤存取匯出的巢狀屬性。當重新匯出命名空間物件時,這可以改善樹狀搖晃(消除未使用的匯出和匯出混淆)。

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

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

// user.js
import * as module from './module';
console.log(module.inner.a);

在此範例中,輸出 b 可在生產模式中移除。

內部模組樹狀搖晃

Webpack 4 未分析模組的輸出與輸入之間的相依性。Webpack 5 有個新的選項 optimization.innerGraph,在生產模式中預設啟用,會針對模組中的符號執行分析,找出從輸出到輸入的相依性。

在像這樣的模組中

import { something } from './something';

function usingSomething() {
  return something;
}

export function test() {
  return usingSomething();
}

內部圖形演算法會找出 something 僅在使用 test 輸出時才會使用。這允許將更多輸出標記為未使用,並從套件中省略更多程式碼。

當設定 "sideEffects": false 時,這允許省略更多模組。在此範例中,當 test 輸出未使用時,將會省略 ./something

若要取得關於未使用輸出的資訊,需要 optimization.usedExports。若要移除無副作用的模組,需要 optimization.sideEffects

可以分析下列符號

  • 函式宣告
  • 類別宣告
  • export default 或具有下列變數宣告
    • 函式表達式
    • 類別表達式
    • 順序表達式
    • /*#__PURE__*/ 表達式
    • 局部變數
    • 匯入繫結

回饋:如果您發現此分析有任何遺漏,請回報問題,我們會考慮新增。

使用 eval() 會讓模組放棄此最佳化,因為 evaled 程式碼可以參照範圍內的任何符號。

此最佳化也稱為深度範圍分析。

CommonJs 樹狀搖晃

Webpack 過去會選擇不分析 CommonJs 輸出和 require() 呼叫所使用的輸出。

Webpack 5 新增支援一些 CommonJs 建構,允許消除未使用的 CommonJs 匯出,並追蹤從 require() 呼叫中引用的匯出名稱。

支援下列建構

  • exports|this|module.exports.xxx = ...
  • exports|this|module.exports = require("...")(重新匯出)
  • exports|this|module.exports.xxx = require("...").xxx(重新匯出)
  • Object.defineProperty(exports|this|module.exports, "xxx", ...)
  • require("abc").xxx
  • require("abc").xxx()
  • 從 ESM 匯入
  • require() 一個 ESM
  • 標記的 exportType(對非嚴格 ESM 匯入進行特殊處理)
    • Object.defineProperty(exports|this|module.exports, "__esModule", { value: true|!0 })
    • exports|this|module.exports.__esModule = true|!0
  • 計畫在未來支援更多建構

在偵測到無法分析的程式碼時,webpack 會放棄,並且完全不會追蹤這些模組的匯出資訊(基於效能考量)。

副作用分析

package.json 中的 "sideEffects" 標記允許手動標記模組為無副作用,這允許在未使用的狀態下刪除它們。

Webpack 5 也可以根據原始碼的靜態分析,自動標記模組為無副作用。

針對每個執行時期的最佳化

Webpack 5 現在能夠(而且預設會)針對每個執行時期分析和最佳化模組(執行時期通常等於一個進入點)。這允許僅在真正需要這些進入點中匯出。進入點不會互相影響(只要每個進入點使用一個執行時期)。

模組串接

模組串接也適用於每個執行時期,允許每個執行時期進行不同的串接。

模組串接已成為一級公民,任何模組和依賴項現在都可以實作它。最初 webpack 5 已新增對 ExternalModules 和 json 模組的支持,更多功能可能會很快推出。

一般樹狀搖晃改進

export * 已獲得改進,可追蹤更多資訊,不再將 default 輸出標記為已使用。

當 webpack 確定有衝突的輸出時,export * 現在會顯示警告。

import() 允許透過 /* webpackExports: ["abc", "default"] */ 魔術註解手動樹狀搖晃模組。

開發與生產相似性

我們嘗試在開發模式的建置效能和避免僅限生產的問題之間找到一個良好的折衷方案,方法是提高兩種模式之間的相似性。

Webpack 5 在兩種模式下都預設啟用 sideEffects 最佳化。在 webpack 4 中,此最佳化會導致一些僅限生產的錯誤,因為 package.json 中的 "sideEffects" 旗標不正確。在開發中啟用此最佳化可以更快、更容易地找出這些問題。

在許多情況下,開發和生產會在檔案系統大小寫敏感度不同的不同作業系統上進行,因此 webpack 5 在大小寫有問題時會新增一些警告/錯誤。

改善的程式碼產生

Webpack 會偵測 ASI 發生時機,並在未插入分號時產生較短的程式碼。Object(...) -> (0, ...)

Webpack 會將多個 export getter 合併成單一執行時期函式呼叫:r.d(x, "a", () => a); r.d(x, "b", () => b); -> r.d(x, {a: () => a, b: () => b});

output.environment 中現在有其他選項。它們允許指定 webpack 產生的執行時期程式碼可以使用哪些 ECMAScript 功能。

通常不會直接指定此選項,而是會使用 target 選項。

Webpack 4 過去只會發射 ES5 程式碼。Webpack 5 現在可以同時產生 ES5 和 ES6/ES2015 程式碼。

只支援現代瀏覽器會產生較短的程式碼,使用箭頭函式和使用 const 宣告並搭配 export default 的 TDZ 產生更符合規範的程式碼。

改善的 target 選項

在 webpack 4 中,target 是在 "web""node"(以及其他一些選項)之間進行粗略選擇。Webpack 5 在此處提供更多選項。

target 選項現在會影響產生的程式碼中比以前更多的內容

  • 區塊載入方法
  • 區塊格式
  • wasm 載入方法
  • 在工作執行緒中載入區塊和 wasm 的方法
  • 使用的全域物件
  • 是否應自動決定 publicPath
  • 產生的程式碼中使用的 ECMAScript 功能/語法
  • 預設啟用 externals
  • 某些 Node.js 相容層的行為(global__filename__dirname
  • 模組解析(browser 欄位、exportsimports 條件)
  • 某些載入器可能會根據此變更行為

對於其中一些項目,"web""node" 之間的選擇過於粗略,我們需要更多資訊。因此,我們允許指定最小版本,例如 "node10.13",並推斷出更多關於目標環境的屬性。

現在還可以透過陣列合併多個目標,而 webpack 將會判斷所有目標的最小屬性。在使用無法提供完整資訊的目標(例如 "web""node",沒有版本號碼)時,使用陣列也很有用。例如,["web", "es2020"] 會合併這兩個部分目標。

有一個目標 "browserslist",它將使用 browserslist 資料來判斷環境的屬性。當專案中有 browserslist 設定檔時,此目標也會預設使用。當沒有此類設定檔時,預設會使用 "web" 目標。

有些組合和功能尚未實作,將會導致錯誤。它們是為未來功能做準備。範例

  • ["web", "node"] 將會導致通用區塊載入方法,但尚未實作
  • ["web", "node"] + output.module: true 將會導致模組區塊載入方法,但尚未實作
  • "web" 將會導致 http(s): 匯入被視為 module 外部程式,但尚未實作(解決方法:externalsPresets: { web: false, webAsync: true },它將會改用 import())。

SplitChunks 和模組大小

模組現在會以比單一數字更好的方式表達大小。現在有不同類型的尺寸。

SplitChunksPlugin 現在知道如何處理這些不同的尺寸,並將它們用於 minSizemaxSize。預設情況下,只處理 javascript 尺寸,但現在你可以傳遞多個值來管理它們

module.exports = {
  optimization: {
    splitChunks: {
      minSize: {
        javascript: 30000,
        webassembly: 50000,
      },
    },
  },
};

你仍然可以使用單一數字表示尺寸。在這種情況下,webpack 將自動使用預設尺寸類型。

mini-css-extract-plugin 使用 css/mini-extra 作為尺寸類型,並自動將此尺寸類型新增到預設類型中。

重大變更:效能

持續快取

現在有一個檔案系統快取。它可以選擇加入,並可以使用以下設定啟用

module.exports = {
  cache: {
    // 1. Set cache type to filesystem
    type: 'filesystem',

    buildDependencies: {
      // 2. Add your config as buildDependency to get cache invalidation on config change
      config: [__filename],

      // 3. If you have other things the build depends on you can add them here
      // Note that webpack, loaders and all modules referenced from your config are automatically added
    },
  },
};

重要事項

預設情況下,webpack 假設 webpack 所在的 node_modules 目錄由套件管理員修改。node_modules 的雜湊和時間戳記會被略過。相反地,出於效能考量,只會使用套件名稱和版本。只要未指定 resolve.symlinks: false,符號連結 (例如 npm/yarn link) 是沒問題的 (無論如何都要避免)。除非你使用 snapshot.managedPaths: [] 取消此最佳化,否則請勿直接編輯 node_modules 中的檔案。使用 Yarn PnP 時,webpack 假設 yarn 快取是不可變的 (通常是這樣)。你可以使用 snapshot.immutablePaths: [] 取消此最佳化

快取將預設儲存在 node_modules/.cache/webpack(使用 node_modules 時)或 .yarn/.cache/webpack(使用 Yarn PnP 時)。如果所有外掛程式都能正確處理快取,您可能永遠不需要手動刪除它。

許多內部外掛程式也會使用持續性快取。範例:SourceMapDevToolPlugin(快取 SourceMap 產生)或 ProgressPlugin(快取模組數量)

持續性快取會自動建立多個快取檔案,視使用情況而定,以最佳化快取的讀寫存取。

預設情況下,時間戳記將用於開發模式的快照,而檔案雜湊則用於生產模式。檔案雜湊允許在 CI 上使用持續性快取。

編譯器閒置和關閉

編譯器現在需要在使用後關閉。編譯器現在會進入和離開閒置狀態,並有這些狀態的掛鉤。外掛程式可以使用這些掛鉤來執行不重要的工作。(例如,持續性快取會將快取緩慢儲存到磁碟)。在編譯器關閉時 - 所有剩餘的工作都應盡快完成。呼叫回會將關閉信號標示為已完成。

外掛程式及其各自的作者應預期有些使用者可能會忘記關閉編譯器。因此,所有工作最終也應在閒置時完成。在工作執行時應防止程序退出。

webpack() 外觀會在傳遞呼叫回時自動呼叫 close

移轉:使用 Node.js API 時,請務必在完成時呼叫 Compiler.close

檔案發射

Webpack 過去在第一次建置時會發射所有輸出檔案,但在增量(監控)建置時會略過未變更的檔案。假設在 webpack 執行時,沒有其他因素會變更輸出檔案。

加入持續快取後,即使重新啟動 webpack 程序,也應提供類似監控的體驗,但假設在 webpack 未執行時,沒有其他因素會變更輸出目錄,這是一個過於強烈的假設。

因此,webpack 現在會檢查輸出目錄中的現有檔案,並將其內容與記憶體中的輸出檔案進行比較。只有在檔案已變更時,才會寫入檔案。這僅在第一次建置時執行。任何增量建置都會在執行中的 webpack 程序產生新資產時,寫入檔案。

我們假設 webpack 和外掛僅在內容變更時才產生新資產。快取應確保在輸入相等時,不會產生新資產。不遵循此建議會降低效能。

標示為 [immutable](包括內容雜湊)的檔案,在已存在同名檔案時,永遠不會寫入。我們假設在檔案內容變更時,內容雜湊也會變更。這通常是正確的,但在 webpack 或外掛開發期間可能並不總是正確。

重大變更:長期存在的問題

單一檔案目標的程式碼分割

僅允許啟動單一檔案(例如 node、WebWorker、electron main)的目標,現在支援由執行階段自動載入引導所需的相依項目。

這允許使用 opimization.splitChunks 搭配 chunks: "all"optimization.runtimeChunk 來處理這些目標。

請注意,對於區塊載入為非同步的目標,這也使得初始評估變成非同步。當使用 output.library 時,這可能會造成問題,因為輸出的值現在是一個 Promise。

已更新的解析器

enhanced-resolve 已更新至 v5。這帶來以下改進

  • 解析器追蹤更多相依項目,例如遺失的檔案
  • 別名可能有多個替代方案
  • 現在可以將別名設為 false
  • 支援 exportsimports 欄位等功能
  • 效能提升

不含 JS 的區塊

不包含任何 JS 程式碼的區塊,將不再產生 JS 檔案。這允許區塊僅包含 CSS。

重大變更:未來

實驗

並非所有功能從一開始就穩定。在 webpack 4 中,我們新增了實驗性功能,並在變更日誌中註明它們是實驗性的,但從設定檔中並不總是能清楚看出這些功能是實驗性的。

在 webpack 5 中,有一個新的 experiments 設定檔選項,用於啟用實驗性功能。這讓哪些功能已啟用/使用變得一目瞭然。

Webpack 遵循語意化版本控制,但會對實驗性功能例外處理。實驗性功能可能會在次要的 Webpack 版本中包含重大變更。發生這種情況時,我們會在變更日誌中加入明確的說明。這讓我們可以針對實驗性功能進行更快速的迭代,同時也能讓我們在主要版本中停留更久的時間以提供穩定的功能。

以下實驗將隨 webpack 5 一起發布

  • 舊的 WebAssembly 支援,例如 webpack 4 中的(experiments.syncWebAssembly
  • 根據 更新的規範 提供新的 WebAssembly 支援(experiments.asyncWebAssembly
    • 這會讓 WebAssembly 模組變成非同步模組
  • 頂層 Await 第 3 階段提案(experiments.topLevelAwait
    • 在頂層使用 await 會讓模組變成非同步模組
  • 以模組形式發布套件(experiments.outputModule
    • 這會從套件中移除包裝的 IIFE,強制執行嚴格模式,透過 <script type="module"> 進行延遲載入,並在模組模式中進行最小化。

請注意,這也表示 WebAssembly 支援現在預設為停用狀態。

最低 Node.js 版本

最低支援的 Node.js 版本已從 6 提升至 10.13.0(LTS)。

移轉:升級至最新可用的 Node.js 版本。

組態變更

結構變更

  • entry: {} 現在允許空物件(允許使用外掛程式來新增項目)
  • target 支援陣列、版本和瀏覽器清單
  • cache: Object 已移除:不再能設定為記憶體快取物件
  • cache.type 已新增:現在可以在 "memory""filesystem" 之間選擇
  • cache.type = "filesystem" 新增新的組態選項
    • cache.cacheDirectory
    • cache.name
    • cache.version
    • cache.store
    • cache.hashAlgorithm
    • cache.idleTimeout
    • cache.idleTimeoutForInitialStore
    • cache.buildDependencies
  • snapshot.resolveBuildDependencies 已新增
  • snapshot.resolve 已新增
  • snapshot.module 已新增
  • snapshot.managedPaths 已新增
  • snapshot.immutablePaths 已新增
  • resolve.cache 已新增:允許停用/啟用安全解析快取
  • resolve.concord 已移除
  • resolve.moduleExtensions 已移除
  • resolve.alias 值現在可以是陣列或 false
  • resolve.restrictions 已新增:允許限制潛在的解析結果
  • resolve.fallback 已新增:允許別名化無法解析的請求
  • resolve.preferRelative 已新增:允許解析模組請求也是相對請求
  • 已移除原生 Node.js 模組的自動 polyfill
    • node.Buffer 已移除
    • node.console 已移除
    • node.process 已移除
    • node.*(原生 Node.js 模組)已移除
    • MIGRATIONresolve.aliasProvidePlugin。錯誤會提供提示。(請參閱 node-libs-browser 以取得 v4 中使用的 polyfill 和模擬)
  • output.filename 現在可以是函式
  • output.assetModuleFilename 已新增
  • output.jsonpScriptType 已重新命名為 output.scriptType
  • devtool 更加嚴格
    • 格式:false | eval | [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
  • 新增 optimization.chunkIds: "deterministic"
  • 新增 optimization.moduleIds: "deterministic"
  • 已棄用 optimization.moduleIds: "hashed"
  • 已移除 optimization.moduleIds: "total-size"
  • 已移除模組和區塊 ID 的已棄用標記
    • 已移除 optimization.hashedModuleIds
    • 已移除 optimization.namedChunks(也移除 NamedChunksPlugin
    • 已移除 optimization.namedModules(也移除 NamedModulesPlugin
    • 已移除 optimization.occurrenceOrder
    • 移轉:使用 chunkIdsmoduleIds
  • optimization.splitChunks test 不再比對區塊名稱
    • 移轉:使用測試函式 (module, { chunkGraph }) => chunkGraph.getModuleChunks(module).some(chunk => chunk.name === "name")
  • 新增 optimization.splitChunks minRemainingSize
  • optimization.splitChunks filename 現在可以是函式
  • optimization.splitChunks 大小現在可以是包含每個來源類型大小的物件
    • minSize
    • minRemainingSize
    • maxSize
    • maxAsyncSize
    • maxInitialSize
  • 新增 optimization.splitChunks maxAsyncSizemaxInitialSize,位於 maxSize 旁邊:允許為初始和非同步區塊指定不同的最大大小
  • 已移除 optimization.splitChunks name: true:不再支援自動名稱
    • 移轉:使用預設值。chunkIds: "named" 會為您的檔案提供有用的名稱以進行除錯
  • 新增 optimization.splitChunks.cacheGroups[].idHint:提供有關如何選擇命名區塊 ID 的提示
  • 已移除 optimization.splitChunks automaticNamePrefix
    • 移轉:改用 idHint
  • optimization.splitChunks filename 不再限於初始區塊
  • 新增 optimization.splitChunks usedExports,在比較模組時包含已使用的匯出
  • 新增 optimization.splitChunks.defaultSizeTypes:在使用數字表示大小時指定大小類型
  • 新增 optimization.mangleExports
  • optimization.minimizer "..." 可用於參照預設值
  • optimization.usedExports "global" 值已新增,允許停用每個執行階段的分析,並改為在全域執行(效能較佳)
  • optimization.noEmitOnErrors 已重新命名為 optimization.emitOnErrors,且邏輯已反轉
  • 已新增 optimization.realContentHash
  • 已移除 output.devtoolLineToLine
    • 移轉:無替換
  • 現在允許使用 output.chunkFilename: Function
  • 現在禁止使用 output.hotUpdateChunkFilename: Function:它從未運作過。
  • 現在禁止使用 output.hotUpdateMainFilename: Function:它從未運作過。
  • output.importFunctionName: string 指定用於取代 import() 的名稱,以允許在非受支援的環境中進行多型填補
  • 已新增 output.charset:將其設定為 false 會省略腳本標籤上的 charset 屬性
  • output.hotUpdateFunction 已重新命名為 output.hotUpdateGlobal
  • output.jsonpFunction 已重新命名為 output.chunkLoadingGlobal
  • output.chunkCallbackFunction 已重新命名為 output.chunkLoadingGlobal
  • 已新增 output.chunkLoading
  • 已新增 output.enabledChunkLoadingTypes
  • 已新增 output.chunkFormat
  • module.rules resolveparser 將以不同的方式合併(物件會深度合併,陣列可能會包含 "..." 以參照前一個值)
  • 已新增 module.rules parser.worker:允許設定受支援的工作執行緒
  • 已移除 module.rules queryloaders
  • module.rules options 傳遞字串已不建議使用
    • 移轉:改為傳遞選項物件,如果此選項不受支援,請在載入器上開啟問題
  • module.rules mimetype 已新增:允許比對 DataURI 的 mimetype
  • module.rules descriptionData 已新增:允許比對 package.json 中的資料
  • module.defaultRules "..." 可用於參考預設值
  • stats.chunkRootModules 已新增:顯示區塊的根模組
  • stats.orphanModules 已新增:顯示未發射的模組
  • stats.runtime 已新增:顯示執行階段模組
  • stats.chunkRelations 已新增:顯示父/子/兄弟區塊
  • stats.errorStack 已新增:顯示 webpack 內部錯誤堆疊追蹤
  • stats.preset 已新增:選擇預設值
  • stats.relatedAssets 已新增:顯示與其他資源相關的資源(例如 SourceMaps)
  • stats.warningsFilter 已棄用,建議使用 ignoreWarnings
  • BannerPlugin.banner 簽章已變更
    • data.basename 已移除
    • data.query 已移除
    • 移轉:從 filename 中萃取
  • SourceMapDevToolPlugin lineToLine 已移除
    • 移轉:無替換
  • [hash] 作為完整編譯的雜湊現已棄用
    • 移轉:改用 [fullhash] 或使用其他雜湊選項
  • [modulehash] 已棄用
    • 移轉:改用 [hash]
  • [moduleid] 已棄用
    • 移轉:改用 [id]
  • [filebase] 已移除
    • 移轉:改用 [base]
  • 檔案型範本的新佔位符(例如 SourceMapDevToolPlugin)
    • [name]
    • [base]
    • [path]
    • [ext]
  • externals 在傳遞函式時,現在具有不同的簽章 ({ context, request }, callback)
    • 移轉:變更簽章
  • externalsPresets 已新增
  • experiments 已新增(請參閱上方的實驗區段)
  • watchOptions.followSymlinks 已新增
  • watchOptions.ignored 現在可以是 RegExp
  • 現在已公開 webpack.util.serialization

預設值變更

  • 當 browserslist 設定檔可用時,target 現在預設為 "browserslist"
  • 現在預設只為 node_modules 啟用 module.unsafeCache
  • 在生產模式下,optimization.moduleIds 預設為 deterministic,而非 size
  • 在生產模式下,optimization.chunkIds 預設為 deterministic,而非 total-size
  • none 模式下,optimization.nodeEnv 預設為 false
  • 在生產模式下,optimization.splitChunks.minSize 預設為 20k
  • 在生產模式下,optimization.splitChunks.enforceSizeThreshold 預設為 50k
  • optimization.splitChunks minRemainingSize 預設為 minSize
    • 在剩餘部分過小的情況下,這將導致建立較少的分割區塊
  • optimization.splitChunks maxAsyncRequestsmaxInitialRequests 預設值已增加至 30
  • optimization.splitChunks.cacheGroups.vendors 已重新命名為 optimization.splitChunks.cacheGroups.defaultVendors
  • optimization.splitChunks.cacheGroups.defaultVendors.reuseExistingChunk 現在預設為 true
  • optimization.minimizer 目標預設現在在 terser 選項中使用 compress.passes: 2
  • 當使用 cache 時,resolve(Loader).cache 預設為 true
  • resolve(Loader).cacheWithContext 預設為 false
  • resolveLoader.extensions 移除了 .json
  • 在 node-target 中,node.global node.__filenamenode.__dirname 預設為 false
  • stats.errorStack 預設為 false

與載入器相關的變更

this.getOptions

這個新的 API 應能簡化載入器中選項的使用方式。它允許傳遞 JSON 架構進行驗證。請參閱 公關 以取得詳細資料

this.exec

這已從載入器內容中移除

遷移:這可以在載入器本身實作

this.getResolve

載入器 API 中的 getResolve(options) 將以不同的方式合併選項,請參閱 module.rules resolve

由於 webpack 5 區分不同的發布依賴關係,因此傳遞 dependencyType 作為選項(例如 "esm""commonjs" 或其他)可能是合理的。

主要內部變更

以下變更僅與外掛作者相關

新的外掛順序

webpack 5 中的外掛現在會在套用組態預設值之前套用。這允許外掛套用自己的預設值,或作為組態預設值。

但這也是一個重大變更,因為外掛無法依賴在套用時設定的組態值。

遷移:僅在插件掛鉤中存取組態。或最好完全避免存取組態,並透過建構函式取得選項。

執行時期模組

執行時期程式碼的大部分已移至所謂的「執行時期模組」。這些特殊模組負責新增執行時期程式碼。它們可以新增到任何區塊,但目前總是新增到執行時期區塊。「執行時期需求」控制哪些執行時期模組(或核心執行時期部分)新增到套件。這可確保僅將使用的執行時期程式碼新增到套件。未來,執行時期模組也可以新增到隨選載入區塊,以在需要時載入執行時期程式碼。

在多數情況下,核心執行時期允許內嵌入口模組,而不是使用 __webpack_require__ 呼叫它。如果套件中沒有其他模組,則根本不需要 __webpack_require__。這與模組串接結合得很好,其中多個模組串接成單一模組。

在最佳情況下,根本不需要執行時期程式碼。

遷移:如果您在插件中將執行時期程式碼注入 webpack 執行時期,請考慮改用執行時期模組。

序列化

已新增序列化機制,允許在 webpack 中序列化複雜物件。它具有選擇性語意,因此應該序列化的類別需要明確標示(並實作其序列化)。已對大多數模組、所有相依性和一些錯誤執行此操作。

遷移:使用自訂模組或相依性時,建議使它們可序列化,以受益於持續快取。

快取插件

已新增具有插件介面的 Cache 類別。此類別可寫入快取並從快取讀取。根據組態,不同的插件可以新增功能到快取。MemoryCachePlugin 新增記憶體內快取。FileCachePlugin 新增持續性(檔案系統)快取。

FileCachePlugin 使用序列化機制將快取項目儲存到磁碟,並從磁碟中還原。

凍結 Hook 物件

具有 hooks 的類別會凍結其 hooks 物件,因此無法再透過這種方式新增自訂 hook。

移轉:建議使用 WeakMap 和靜態 getXXXHooks(XXX) (例如 getCompilationHook(compilation)) 方法來新增自訂 hook。內部類別使用與自訂 hook 相同的機制。

Tapable 升級

已移除 webpack 3 外掛的相容性層。它在 webpack 4 中已遭棄用。

已移除或棄用一些較少使用的 tapable API。

移轉:使用新的 tapable API。

階段性 Hook

在封裝程序的幾個步驟中,都有針對不同階段的多個 hook。例如 optimizeDependenciesBasic optimizeDependenciesoptimizeDependenciesAdvanced。這些 hook 已被移除,改用可搭配 stage 選項使用的單一 hook。請參閱 OptimizationStages 以取得可能的階段值。

移轉:改為使用剩下的 hook。您可以新增 stage 選項。

Main/Chunk/ModuleTemplate 已棄用

已重新調整套件範本。MainTemplate/ChunkTemplate/ModuleTemplate 已遭棄用,而 JavascriptModulesPlugin 現在負責 JS 範本。

在重新調整之前,JS 輸出是由 Main/ChunkTemplate 處理,而其他輸出 (例如 WASM、CSS) 則是由外掛處理。這看起來像是 JS 是第一類,而其他輸出是第二類。重新調整後會改變這種情況,所有輸出都由其外掛處理。

仍然可以連接到範本的某些部分。這些 hook 現在位於 JavascriptModulesPlugin,而非 Main/ChunkTemplate 中。(是的,外掛也可以有 hook。我稱它們為附加 hook。)

有一個相容層,因此 Main/Chunk/ModuleTemplate 仍然存在,但只會將 tap 呼叫委派給新的 hook 位置。

移轉:遵循棄用訊息中的建議。主要指向不同位置的 hook。

進入點描述符

如果將物件傳遞為進入點,則值可能是字串、字串陣列或描述符

module.exports = {
  entry: {
    catalog: {
      import: './catalog.js',
    },
  },
};

描述符語法可用於將其他選項傳遞給進入點。

進入點輸出檔名

預設情況下,進入區塊的輸出檔名會從 output.filename 中萃取,但您可以為特定進入點指定自訂輸出檔名

module.exports = {
  entry: {
    about: { import: './about.js', filename: 'pages/[name][ext]' },
  },
};

進入點依賴

預設情況下,每個進入區塊都會儲存它使用的所有模組。使用 dependOn 選項,您可以將模組從一個進入區塊共用到另一個區塊

module.exports = {
  entry: {
    app: { import: './app.js', dependOn: 'react-vendors' },
    'react-vendors': ['react', 'react-dom', 'prop-types'],
  },
};

應用程式區塊不會包含 react-vendors 所具有的模組。

進入點函式庫

進入描述符允許為每個進入點傳遞不同的 library 選項。

module.exports = {
  entry: {
    commonjs: {
      import: './lib.js',
      library: {
        type: 'commonjs-module',
      },
    },
    amd: {
      import: './lib.js',
      library: {
        type: 'amd',
      },
    },
  },
};

進入點執行時期

進入描述符允許為每個進入點指定 runtime。當指定時,會建立一個包含此進入點之執行時期程式碼的區塊。當多個進入點指定相同的 runtime 時,該區塊將包含所有這些進入點的共用執行時期。這表示它們可以在同一個 HTML 頁面上一起使用。

module.exports = {
  entry: {
    app: {
      import: './app.js',
      runtime: 'app-runtime',
    },
  },
};

進入點區塊載入

條目描述符允許為每個條目指定 chunkLoading。此條目的執行階段會使用它來載入區塊。

module.exports = {
  entry: {
    app: {
      import: './app.js',
    },
    worker: {
      import: './worker.js',
      chunkLoading: 'importScripts',
    },
  },
};

順序和 ID

Webpack 過去會在編譯階段以特定方式對模組和區塊排序,以遞增順序指派 ID。現在不再這樣做。順序不再用於產生 ID,而是由外掛完全控制 ID 的產生。

用於最佳化模組和區塊順序的掛鉤已移除。

遷移:您無法再依賴編譯階段中模組和區塊的順序。

陣列轉換為集合

  • Compilation.modules 現在是集合
  • Compilation.chunks 現在是集合
  • Chunk.files 現在是集合

有一個相容性層會印出不建議使用的警告。

遷移:使用集合方法,而非陣列方法。

Compilation.fileSystemInfo

這個新類別可用於以快取方式存取檔案系統的資訊。目前,它允許同時詢問檔案和目錄的時間戳記。時間戳記的資訊會從監視器傳送(如果可能),否則由檔案系統存取來決定。

未來,將會加入詢問檔案內容雜湊的功能,而模組將能夠使用檔案內容(而非檔案雜湊)來檢查有效性。

遷移:不要使用 file/contextTimestamps,而改用 compilation.fileSystemInfo API。

現在目錄可以進行時間戳記,這允許序列化 ContextModules。

已新增 Compiler.modifiedFiles(在 Compiler.removedFiles 旁邊),以更輕鬆地參照已變更的檔案。

檔案系統

除了 compiler.inputFileSystemcompiler.outputFileSystem 之外,還有一個新的 compiler.intermediateFileSystem,用於所有不被視為輸入或輸出的檔案系統動作,例如寫入記錄、快取或剖析輸出。

檔案系統現在具有 fs 介面,不再需要像 joinmkdirp 這樣的額外方法。但如果它們有像 joindirname 這樣的函式,則會使用它們。

熱模組替換

HMR 執行階段已重構為執行階段模組。HotUpdateChunkTemplate 已合併到 ChunkTemplate 中。ChunkTemplates 和外掛程式現在也應該處理 HotUpdateChunk

HMR 執行階段的 javascript 部分已與核心 HMR 執行階段分開。現在其他模組類型也可以用自己的方式處理 HMR。未來,這將允許為 mini-css-extract-plugin 或 WASM 模組進行 HMR。

移轉:由於這是一個新推出的功能,因此沒有任何需要移轉的內容。

import.meta.webpackHot 公開與 module.hot 相同的 API。這也可以從嚴格的 ESM 模組(.mjs,package.json 中的類型:「module」)使用,這些模組無法存取 module

工作佇列

Webpack 過去透過呼叫函式呼叫函式的處理模組,以及限制並行的 semaphore 來處理模組處理。Compilation.semaphore 已被移除,非同步佇列現在處理工作佇列和處理。每個步驟都有獨立的佇列

  • Compilation.factorizeQueue:為一組相依性呼叫模組工廠。
  • Compilation.addModuleQueue:將模組加入編譯佇列(可能會從快取中還原模組)。
  • Compilation.buildQueue:必要時建置模組(可能會將模組儲存在快取中)。
  • Compilation.rebuildQueue:手動觸發時重新建置模組。
  • Compilation.processDependenciesQueue:處理模組的相依性。

這些佇列有一些掛勾,可用於監控和攔截工作處理。

未來,多個編譯器可能會一起工作,而工作排程可以透過攔截這些佇列來完成。

移轉:由於這是一個新推出的功能,因此沒有任何需要移轉的內容。

記錄

Webpack 內部現在包含一些記錄。stats.logginginfrastructureLogging 選項可用於啟用這些訊息。

模組和區塊圖

Webpack 過去會將已解析的模組儲存在相依性中,並將包含的模組儲存在區塊中。現在已不再如此。所有關於模組如何在模組圖中連接的資訊現在都儲存在 ModuleGraph 類別中。所有關於模組如何與區塊連接的資訊現在都儲存在 ChunkGraph 類別中。依賴於區塊圖等資訊也儲存在相關的類別中。

這表示以下關於模組的資訊已移至

  • 模組連接 -> ModuleGraph
  • 模組發出者 -> ModuleGraph
  • 模組最佳化中止 -> ModuleGraph(待辦事項:檢查是否應改為 ChunkGraph)
  • 模組 usedExports -> ModuleGraph
  • 模組 providedExports -> ModuleGraph
  • 模組預訂順序索引 -> ModuleGraph
  • 模組後訂順序索引 -> ModuleGraph
  • 模組深度 -> ModuleGraph
  • 模組設定檔 -> ModuleGraph
  • 模組 ID -> ChunkGraph
  • 模組雜湊 -> ChunkGraph
  • 模組執行時間需求 -> ChunkGraph
  • 模組在區塊中 -> ChunkGraph
  • 模組是區塊中的入口 -> 區塊圖
  • 模組是區塊中的執行時期模組 -> 區塊圖
  • 區塊執行時期需求 -> 區塊圖

Webpack 用於在從快取還原時將模組從圖形中斷開。這不再是必要的。模組不會儲存有關圖形的資訊,而且技術上可以在多個圖形中使用。這使得快取更容易。

對於這些變更的大部分,有一個相容層,在使用時會列印不建議使用的警告。

遷移:在 ModuleGraph 和 ChunkGraph 上使用新的 API

初始化片段

DependenciesBlockVariables 已被移除,改為使用 InitFragments。DependencyTemplates 現在可以新增 InitFragments 以將程式碼注入到模組來源的頂端。InitFragments 允許重複資料刪除。

遷移:使用 InitFragments,而不是在來源中插入負索引的項目。

模組來源類型

模組現在必須透過 Module.getSourceTypes() 定義它們支援的來源類型。根據此,不同的外掛程式會使用這些類型呼叫 source()。例如,對於來源類型 javascriptJavascriptModulesPlugin 會將來源程式碼嵌入到套件中。來源類型 webassembly 會讓 WebAssemblyModulesPlugin 發射 wasm 檔案。自訂來源類型也受支援,例如 mini-css-extract-plugin 可能會使用來源類型 stylesheet 將來源程式碼嵌入到 css 檔案中。

模組類型和來源類型之間沒有關係。例如,模組類型 json 也使用來源類型 javascript,而模組類型 webassembly/experimental 使用來源類型 javascriptwebassembly

遷移:自訂模組需要實作這些新的介面方法。

統計資料的外掛程式

統計資料 presetdefaultjsontoString 現在已由外掛系統內建。已將目前的統計資料轉換為外掛。

遷移:現在您可以自訂統計資料,而不用取代整個統計資料功能。現在可以將額外資訊新增到統計資料 json 中,而不用寫入個別檔案。

新的監控

webpack 使用的監視器已重新編寫。它先前使用 chokidar 和原生依賴項 fsevents(僅限 macOS)。現在它只基於原生 Node.js fs。這表示 webpack 中沒有原生依賴項了。

它也會擷取更多關於檔案系統的資訊,同時進行監控。它現在會擷取 mtimes 和監控事件時間,以及關於遺失檔案的資訊。因此,WatchFileSystem API 稍有變更。同時,我們也將陣列轉換為集合,物件轉換為對應。

發射後的 SizeOnlySource

Webpack 現在會以 SizeOnlySource 變體取代 Compilation.assets 中的來源,以減少記憶體用量。

多次發射資源

警告 多個資源發射不同內容到同一個檔案名稱 已變成錯誤。

ExportsInfo

儲存模組輸出資訊的方式已重新編寫。ModuleGraph 現在為每個 Module 提供一個 ExportsInfo,其中儲存每個輸出的資訊。它也會儲存關於未知輸出的資訊,以及模組是否以僅副作用的方式使用。

會為每個輸出儲存下列資訊

  • 輸出是否已使用?是、否、無法靜態得知、未確定。(另請參閱 optimization.usedExports
  • 是否提供輸出?是、否、靜態未知、未決定。(另請參閱 optimization.providedExports
  • 是否可以重新命名輸出名稱?是、否、未決定。
  • 如果已重新命名輸出,則為新名稱。(另請參閱 optimization.mangleExports
  • 嵌套 ExportsInfo,如果輸出是附有資訊的物件
    • 用於重新輸出命名空間物件:import * as X from "..."; export { X };
    • 用於表示 JSON 模組中的結構

程式碼產生階段

編譯功能現在將程式碼產生作為獨立的編譯階段。它不再隱藏在 Module.source()Module.getRuntimeRequirements() 中執行。

這應該使流程更清晰。它還允許報告此階段的進度,並在分析時使程式碼產生更明顯。

移轉Module.source()Module.getRuntimeRequirements() 現在已棄用。請改用 Module.codeGeneration()

依賴關係參考

Webpack 過去有一個單一方法和類型來表示依賴關係參考(Compilation.getDependencyReference 傳回 DependencyReference)。此類型用於包含有關此參考的所有資訊,例如引用的模組、已匯入哪些輸出、是否為弱參考,以及一些與排序相關的資訊。

將所有這些資訊組合在一起會使取得參考變得昂貴,而且它也經常被呼叫(每次有人需要資訊時)。

在 webpack 5 中,程式碼庫的這部分已重新整理,並且方法已拆分。

  • 可以從 ModuleGraphConnection 讀取引用的模組
  • 可以透過 Dependency.getReferencedExports() 取得匯入的輸出名稱
  • Dependency 類別上有一個 weak 旗標
  • 排序僅與 HarmonyImportDependencies 相關,且可以透過 sourceOrder 屬性取得

表示性依賴關係

NormalModules 中現在有一種新的依賴類型:表示依賴關係

這些依賴關係僅在程式碼產生階段使用,但在模組圖形建立期間不會使用。因此,它們永遠不會有參照模組或影響匯出/匯入。

這些依賴關係的處理成本較低,webpack 會在可能的情況下使用它們

已棄用的載入器

  • null-loader

    它將被棄用。使用

    module.exports = {
      resolve: {
        alias: {
          xyz$: false,
        },
      },
    };

    或使用絕對路徑

    module.exports = {
      resolve: {
        alias: {
          [path.resolve(__dirname, '....')]: false,
        },
      },
    };

次要變更

  • Compiler.name:使用絕對路徑產生編譯器名稱時,請務必在名稱的兩部分中使用 |! 將它們分開。
    • 現在已棄用使用空白作為分隔符號。(路徑可能包含空白)
    • 提示:| 在統計資料字串輸出中會以空白取代。
  • SystemPlugin 現在預設已停用。
    • 遷移:避免使用它,因為規格已被移除。您可以使用 Rule.parser.system: true 重新啟用它
  • ModuleConcatenationPlugin:合併不再受 DependencyVariables 阻止,因為它們已被移除
    • 這表示它現在可以在 moduleglobalprocess 或 ProvidePlugin 的情況下合併
  • 已移除 Stats.presetToOptions
    • 遷移:改用 compilation.createStatsOptions
  • 已移除 SingleEntryPluginSingleEntryDependency
    • 遷移:使用 EntryPluginEntryDependency
  • 區塊現在可以有多個進入模組
  • 已移除 ExtendedAPIPlugin
    • 遷移:不再需要,__webpack_hash____webpack_chunkname__ 隨時可以使用,並在需要時注入執行時間程式碼。
  • ProgressPlugin 不再使用 tapable 背景進行 reportProgress
    • 遷移:改用 ProgressPlugin.getReporter(compiler)
  • ProvidePlugin 現在已重新啟用 .mjs 檔案
  • Stats json errorswarnings 不再包含字串,而是包含將資訊拆分為屬性的物件。
    • 遷移:存取屬性上的資訊。例如:message
  • Compilation.hooks.normalModuleLoader 已棄用
    • 遷移:改用 NormalModule.getCompilationHooks(compilation).loader
  • NormalModuleFactory 中的掛鉤從瀑布式改為退出式,變更並重新命名會傳回瀑布式函式的掛鉤
  • 已移除 compilationParams.compilationDependencies
    • 外掛程式可以透過新增至 compilation.file/context/missingDependencies 來新增對編譯的依賴項
    • 相容性層會將 compilationDependencies.add 委派給 fileDependencies.add
  • stats.assetsByChunkName[x] 現在永遠都是陣列
  • 已新增 __webpack_get_script_filename__ 函式來取得腳本檔案的檔名
  • package.json 中的 "sideEffects" 將由 glob-to-regex 處理,而非 micromatch
    • 這可能會在極端情況下變更語意
  • 已從 IgnorePlugin 中移除 checkContext
  • 新的 __webpack_exports_info__ API 允許內省輸出使用
  • SourceMapDevToolPlugin 現在也適用於非區塊資產
  • 當引用的環境變數不存在且沒有備用選項時,EnvironmentPlugin 現在會顯示錯誤
  • 從架構中移除 serve 屬性

其他次要變更

  • 已移除內建目錄,並以執行時期模組取代內建模組
  • 已移除已棄用的功能
    • BannerPlugin 現在僅支援一個可以是物件、字串或函式的引數
  • 已移除 CachePlugin
  • Chunk.entryModule 已棄用,改用 ChunkGraph
  • Chunk.hasEntryModule 已棄用
  • Chunk.addModule 已棄用
  • Chunk.removeModule 已棄用
  • Chunk.getNumberOfModules 已棄用
  • Chunk.modulesIterable 已棄用
  • Chunk.compareTo 已棄用
  • Chunk.containsModule 已棄用
  • Chunk.getModules 已棄用
  • Chunk.remove 已棄用
  • Chunk.moveModule 已棄用
  • Chunk.integrate 已棄用
  • Chunk.canBeIntegrated 已棄用
  • Chunk.isEmpty 已棄用
  • Chunk.modulesSize 已棄用
  • Chunk.size 已棄用
  • Chunk.integratedSize 已棄用
  • Chunk.getChunkModuleMaps 已棄用
  • Chunk.hasModuleInGraph 已棄用
  • Chunk.updateHash 簽章已變更
  • Chunk.getChildIdsByOrders 簽章已變更 (待辦事項:考慮移至 ChunkGraph)
  • Chunk.getChildIdsByOrdersMap 簽章已變更 (待辦事項:考慮移至 ChunkGraph)
  • Chunk.getChunkModuleMaps 已移除
  • Chunk.setModules 已移除
  • 已移除不建議使用的 Chunk 方法
  • 已新增 ChunkGraph
  • 已移除 ChunkGroup.setParents
  • 已移除 ChunkGroup.containsModule
  • 已移除 Compilation.cache,改用 Compilation.getCache()
  • ChunkGroup.remove 不再會中斷群組與區塊的連線
  • ChunkGroup.compareTo 簽章已變更
  • ChunkGroup.getChildrenByOrders 簽章已變更
  • ChunkGroup 索引和索引已重新命名為前/後順序索引
    • 舊的 getter 已棄用
  • ChunkTemplate.hooks.modules 簽章已變更
  • ChunkTemplate.hooks.render 簽章已變更
  • ChunkTemplate.updateHashForChunk 簽章已變更
  • 已移除 Compilation.hooks.optimizeChunkOrder
  • 已移除 Compilation.hooks.optimizeModuleOrder
  • 已移除 Compilation.hooks.advancedOptimizeModuleOrder
  • 已移除 Compilation.hooks.optimizeDependenciesBasic
  • 已移除 Compilation.hooks.optimizeDependenciesAdvanced
  • 已移除 Compilation.hooks.optimizeModulesBasic
  • 已移除 Compilation.hooks.optimizeModulesAdvanced
  • 已移除 Compilation.hooks.optimizeChunksBasic
  • 已移除 Compilation.hooks.optimizeChunksAdvanced
  • 已移除 Compilation.hooks.optimizeChunkModulesBasic
  • 已移除 Compilation.hooks.optimizeChunkModulesAdvanced
  • 已移除 Compilation.hooks.optimizeExtractedChunksBasic
  • Compilation.hooks.optimizeExtractedChunks 已移除
  • Compilation.hooks.optimizeExtractedChunksAdvanced 已移除
  • Compilation.hooks.afterOptimizeExtractedChunks 已移除
  • Compilation.hooks.stillValidModule 已新增
  • Compilation.hooks.statsPreset 已新增
  • Compilation.hooks.statsNormalize 已新增
  • Compilation.hooks.statsFactory 已新增
  • Compilation.hooks.statsPrinter 已新增
  • Compilation.fileDependenciesCompilation.contextDependenciesCompilation.missingDependencies 現在是 LazySet
  • Compilation.entries 已移除
    • 遷移:改用 Compilation.entryDependencies
  • Compilation._preparedEntrypoints 已移除
  • dependencyTemplates 現在是 DependencyTemplates 類別,而非原始的 Map
  • Compilation.fileTimestampscontextTimestamps 已移除
    • 遷移:改用 Compilation.fileSystemInfo
  • Compilation.waitForBuildingFinished 已移除
    • 遷移:改用新的佇列
  • Compilation.addModuleDependencies 已移除
  • Compilation.prefetch 已移除
  • Compilation.hooks.beforeHash 現在會在建立模組雜湊後呼叫
    • 遷移:改用 Compiliation.hooks.beforeModuleHash
  • Compilation.applyModuleIds 已移除
  • Compilation.applyChunkIds 已移除
  • 已新增 Compiler.root,指向根編譯器
    • 它可以用於在 WeakMap 中快取資料,而非靜態範圍
  • 已新增 Compiler.hooks.afterDone
  • Source.emitted 不再由編譯器設定
    • 遷移:改為檢查 Compilation.emittedAssets
  • 已新增 Compiler/Compilation.compilerPath:它是編譯器樹中編譯器的唯一名稱。(在根編譯器範圍中唯一)
  • Module.needRebuild 已棄用
    • 遷移:改用 Module.needBuild
  • Dependency.getReference 簽章已變更
  • Dependency.getExports 簽章已變更
  • Dependency.getWarnings 簽章已變更
  • Dependency.getErrors 簽章已變更
  • Dependency.updateHash 簽章已變更
  • 已移除 Dependency.module
  • 現在 DependencyTemplate 有基礎類別
  • 已移除 MultiEntryDependency
  • 已新增 EntryDependency
  • 已移除 EntryModuleNotFoundError
  • 已移除 SingleEntryPlugin
  • 已新增 EntryPlugin
  • 已新增 Generator.getTypes
  • 已新增 Generator.getSize
  • Generator.generate 簽章已變更
  • 已新增 HotModuleReplacementPlugin.getParserHooks
  • Parser 已移至 JavascriptParser
  • ParserHelpers 已移至 JavascriptParserHelpers
  • 已移除 MainTemplate.hooks.moduleObj
  • 已移除 MainTemplate.hooks.currentHash
  • 已移除 MainTemplate.hooks.addModule
  • 已移除 MainTemplate.hooks.requireEnsure
  • 已移除 MainTemplate.hooks.globalHashPaths
  • 已移除 MainTemplate.hooks.globalHash
  • 已移除 MainTemplate.hooks.hotBootstrap
  • 已變更 MainTemplate.hooks 的一些簽章
  • 已棄用 Module.hash
  • 已棄用 Module.renderedHash
  • 已移除 Module.reasons
  • 已棄用 Module.id
  • 已棄用 Module.index
  • 已棄用 Module.index2
  • 已棄用 Module.depth
  • 已棄用 Module.issuer
  • 已移除 Module.profile
  • 已移除 Module.prefetched
  • 已移除 Module.built
  • 已移除 Module.used
    • 移轉:改用 Module.getUsedExports
  • 已棄用 Module.usedExports
    • 移轉:改用 Module.getUsedExports
  • 已棄用 Module.optimizationBailout
  • 已移除 Module.exportsArgument
  • 已棄用 Module.optional
  • 已移除 Module.disconnect
  • 已移除 Module.unseal
  • 已移除 Module.setChunks
  • 已棄用 Module.addChunk
  • Module.removeChunk 已棄用
  • Module.isInChunk 已棄用
  • Module.isEntryModule 已棄用
  • Module.getChunks 已棄用
  • Module.getNumberOfChunks 已棄用
  • Module.chunksIterable 已棄用
  • Module.hasEqualsChunks 已移除
  • Module.useSourceMap 已移至 NormalModule
  • Module.addReason 已移除
  • Module.removeReason 已移除
  • Module.rewriteChunkInReasons 已移除
  • Module.isUsed 已移除
    • 遷移:改用 isModuleUsedisExportUsedgetUsedName
  • Module.updateHash 簽章已變更
  • Module.sortItems 已移除
  • Module.unbuild 已移除
    • 遷移:改用 invalidateBuild
  • 已新增 Module.getSourceTypes
  • 已新增 Module.getRuntimeRequirements
  • Module.size 簽章已變更
  • ModuleFilenameHelpers.createFilename 簽章已變更
  • 已新增 ModuleProfile 類別,其中包含更多資料
  • ModuleReason 已移除
  • ModuleTemplate.hooks 簽章已變更
  • ModuleTemplate.render 簽章已變更
  • Compiler.dependencies 已移除
    • 遷移:改用 MultiCompiler.setDependencies
  • MultiModule 已移除
  • MultiModuleFactory 已移除
  • NormalModuleFactory.fileDependenciesNormalModuleFactory.contextDependenciesNormalModuleFactory.missingDependencies 現在是 LazySet
  • RuntimeTemplate 方法現在採用 runtimeRequirements 引數
  • 已移除 serve 屬性
  • 已移除 Stats.jsonToString
  • 已移除 Stats.filterWarnings
  • 已移除 Stats.getChildOptions
  • 已移除 Stats 輔助方法
  • Stats.toJson 簽章已變更(已移除第二個引數)
  • 已移除 ExternalModule.external
  • HarmonyInitDependency 已移除
  • Dependency.getInitFragments 已棄用
    • 遷移:改用 apply initFragements
  • DependencyReference 現在會對模組使用函式,而不是模組
  • HarmonyImportSpecifierDependency.redirectedId 已移除
    • 遷移:改用 setId
  • acorn 5 -> 8
  • 測試
    • HotTestCases 現在會針對多個目標執行 async-node node web webworker
    • TestCases 現在也會針對檔案系統快取執行,並使用 store: "instant"store: "pack"
    • TestCases 現在也會針對確定性模組 ID 執行
  • 已新增工具來排序匯入(已在 CI 中檢查)
  • 執行時期的區塊名稱對應不再包含區塊名稱等於區塊 ID 的項目
  • resolvedModuleId resolvedModuleIdentifierresolvedModule 新增到 Stats 中的原因,這些原因會指向最佳化前(例如範圍提升)的模組
  • 在 Stats toString 輸出中顯示 resolvedModule
  • 已升級 loader-runner:https://github.com/webpack/loader-runner/releases/tag/v3.0.0
  • 出於效能考量,Compilation 中的 file/context/missingDependencies 不再排序
    • 請勿依賴順序
  • 已將 webpack-sources 升級至版本 2:https://github.com/webpack/webpack-sources/releases/tag/v2.0.1
  • 已移除 webpack-command 支援
  • 針對 schema 驗證使用 schema-utils@2
  • Compiler.assetEmitted 的第二個參數已改善,並提供更多資訊
  • BannerPlugin 會略過尾隨空白
  • 已從 LimitChunkCountPlugin 中移除 minChunkSize 選項
  • 將與 javascript 相關的檔案重新整理到子目錄中
    • webpack.JavascriptModulesPlugin -> webpack.javascript.JavascriptModulesPlugin
  • 已新增 Logger.getChildLogger
  • 將 DllPlugin 的 entryOnly 預設值變更為 true
  • 移除特殊要求縮短邏輯並使用單一相對路徑以取得可讀的模組名稱
  • 允許 SourceMaps 中的 webpack:// URL 提供相對於 webpack 根目錄路徑的相對路徑
  • 新增 API 以產生和處理針對 webpack 設定的 CLI 參數
  • 當使用 System.js 作為 libraryTarget 時,新增 __system_context__ 作為 System.js 的內容
  • 新增 DefinePlugin 的 bigint 支援
  • 新增 bigint 支援以進行基本評估,例如數學
  • 移除在雜湊建立後修改編譯雜湊的能力
  • 移除 HotModuleReplacementPlugin 多步驟模式
  • emitAsset 中的 assetInfo 現在會在使用巢狀物件或陣列時進行合併
  • [query] 現在是基於類似資產的 filename 路徑的有效佔位符
  • 新增 Compilation.deleteAsset 以正確刪除資產和非共用相關資產
  • 公開 require("webpack-sources") 作為 require("webpack").sources
  • terser 5
  • Webpack 可以在句首寫成大寫 W

2 貢獻者

sokrachenxsan