從 v4 升級至 v5

本指南旨在協助您在直接使用 webpack 時,將其移轉至 webpack 5。如果您使用較高層級的工具來執行 webpack,請參閱該工具的移轉說明。

準備工作

Webpack 5 至少需要 Node.js 10.13.0 (LTS),因此如果您仍在執行較舊版本,請務必升級您的 Node.js。

升級 webpack 4 及其外掛程式/載入器

  1. webpack 4 升級至最新可用版本。

    • 在使用 webpack >= 4 時,升級至最新 webpack 4 版本不應需要其他指導。

    • 如果您使用的 webpack 版本低於 4,請參閱 webpack 4 移轉指南

  2. webpack-cli 升級至最新可用版本(在使用時)

  3. 將所有已使用的外掛程式和載入器升級至最新可用版本

    某些外掛程式和載入器可能有測試版,必須使用才能與 webpack 5 相容。升級時務必閱讀每個外掛程式/載入器的發行說明,因為最新版本可能只支援 webpack 5,且會在 v4 中失敗。在這種情況下,建議更新至支援 webpack 4 的最新版本。

確保您的建置沒有錯誤或警告

由於升級了 webpackwebpack-cli、外掛程式和載入器的版本,可能會出現新的錯誤或警告。在建置過程中注意過時警告。

您可以這樣呼叫 webpack,以取得過時警告的堆疊追蹤,找出哪些外掛程式和載入器負責。

node --trace-deprecation node_modules/webpack/bin/webpack.js

由於 webpack 5 移除了所有過時的特性,因此請確保在建置過程中沒有 webpack 過時警告,才能繼續進行。

請務必使用 mode

mode 設定為 productiondevelopment 以確保設定對應的預設值。

更新過時的選項

將下列選項更新為其新版本(如果已使用)

  • optimization.hashedModuleIds: trueoptimization.moduleIds: 'hashed'
  • optimization.namedChunks: trueoptimization.chunkIds: 'named'
  • optimization.namedModules: trueoptimization.moduleIds: 'named'
  • NamedModulesPluginoptimization.moduleIds: 'named'
  • NamedChunksPluginoptimization.chunkIds: 'named'
  • HashedModuleIdsPluginoptimization.moduleIds: 'hashed'
  • optimization.noEmitOnErrors: falseoptimization.emitOnErrors: true
  • optimization.occurrenceOrder: trueoptimization: { chunkIds: 'total-size', moduleIds: 'size' }
  • optimization.splitChunks.cacheGroups.vendorsoptimization.splitChunks.cacheGroups.defaultVendors
  • optimization.splitChunks.cacheGroups.test(module, chunks)optimization.splitChunks.cacheGroups.test(module, { chunkGraph, moduleGraph })
  • Compilation.entriesCompilation.entryDependencies
  • serveserve 已移除,改為使用 DevServer
  • Rule.query(自 v3 起已棄用)→ Rule.options/UseEntry.options
  • Rule.loadersRule.use

測試 webpack 5 相容性

請嘗試在您的 webpack 4 設定中設定下列選項,並檢查建置是否仍能正常運作。

module.exports = {
  // ...
  node: {
    Buffer: false,
    process: false,
  },
};

在為 webpack 5 升級設定時,您必須再次移除這些選項。

將 webpack 升級至 5

現在讓我們將 webpack 升級至版本 5

  • npm:npm install webpack@latest

  • Yarn:yarn add webpack@latest

如果您無法在升級 webpack 4 及其外掛/載入器步驟中將一些外掛/載入器升級到最新版本,請別忘了現在升級它們。

清除設定

  • 考慮從 webpack 設定中移除 optimization.moduleIdsoptimization.chunkIds。預設值可能更好,因為它們支援 生產模式 中的長期快取和 開發模式 中的除錯。

  • 在 webpack 設定中使用 [hash] 佔位符時,請考慮將其變更為 [contenthash]。它不一樣,但已被證實更有效。

  • 如果您使用 Yarn 的 PnP 和 pnp-webpack-plugin,我們有好消息:現在預設支援它。您必須從設定中移除它。

  • 如果您使用 IgnorePlugin 搭配正規表示式作為引數,它現在需要一個 options 物件:new IgnorePlugin({ resourceRegExp: /regExp/ })

  • 如果您使用類似 node.fs: 'empty' 的內容,請將其替換為 resolve.fallback.fs: false

  • 如果您在 webpack Node.js API 中使用 watch: true,請移除它。無需設定它,因為它是由您呼叫的編譯器方法指示,watch()truerun()false

  • 如果您已定義 rules 以使用 raw-loaderurl-loaderfile-loader 載入資源,請改用 資源模組,因為它們將在不久的將來被棄用。

  • 如果您已將 target 設定為函式,請將其更新為 false,並在 plugins 選項中套用該函式。請參閱以下範例

    // for webpack 4
    {
        target: WebExtensionTarget(nodeConfig)
    }
    
    // for webpack 5
    {
        target: false,
        plugins: [
            WebExtensionTarget(nodeConfig)
        ]
    }
  • 如果您已定義 output.library 或 output.libraryTarget,請變更屬性名稱:(output.libraryTarget -> output.library.type, output.library -> output.library.name)。範例

    // for webpack 4
    {
        output: {
          library: 'MyLibrary',
          libraryTarget: 'commonjs2'
        }
    }
    
    // for webpack 5
    {
        output: {
          library: {
            name: 'MyLibrary',
            type: 'commonjs2'
          }
        }
    }

如果您透過匯入使用 WebAssembly,您應遵循此兩步驟流程

  • 透過設定 experiments.syncWebAssembly: true 來啟用已棄用的規格,以取得與 webpack 4 相同的行為。
  • 在成功移轉至 webpack 5 之後,將 experiments 值變更為 experiments: { asyncWebAssembly: true } 以使用 WASM 整合的最新規格。

重新考慮 optimization.splitChunks

  • 建議使用預設值或 optimization.splitChunks: { chunks: 'all' }
  • 在使用自訂設定時,請刪除 name: false 並將 name: string | function 取代為 idHint: string | function
  • 透過設定 optimization.splitChunks.cacheGroups: { default: false, vendors: false } 來關閉預設值是可能的。我們不建議這麼做,但如果您真的想要在 webpack 5 中獲得相同的結果:optimization.splitChunks.cacheGroups: { default: false, defaultVendors: false }

考慮移除預設值

  • 使用 entry: './src/index.js':您可以省略它,這是預設值。
  • 使用 output.path: path.resolve(__dirname, 'dist'):您可以省略它,這是預設值。
  • 使用 output.filename: '[name].js':您可以省略它,這是預設值。

需要支援較舊的瀏覽器,例如 IE 11?

  • 如果您已為專案啟用 browserslist,webpack 5 將會重複使用您的 browserslist 設定,以決定要為執行時期程式碼發出哪種程式碼樣式。

    請務必

    1. target 設定為 browserslist 或移除 target,讓 webpack 自動為您設定 browserslist
    2. IE 11 新增至您的 browserslist 設定。
  • 沒有 browserslist 時,webpack 的執行時期程式碼會使用 ES2015 語法(例如箭頭函式)來建置較小的套件。因此,您需要設定 target: ['web', 'es5'] 來使用 ES5 語法,以適用於不支援 ES2015 語法的瀏覽器(例如 IE11)。

  • 對於 Node.js,建置會在 target 選項中包含支援的 Node.js 版本,而 webpack 會自動找出支援的語法,例如 target: 'node8.6'

清理程式碼

使用 /* webpackChunkName: '...' */

請務必了解其用意

  • 區塊的名稱在此預計為公開的。
  • 它不是僅供開發的名稱。
  • Webpack 會使用它來命名生產和開發模式中的檔案。
  • 即使不使用 webpackChunkName,Webpack 5 也會在 development 模式中自動指派有用的檔案名稱。

使用 JSON 模組中的命名匯出

新的規格不支援此功能,您會收到警告。請改用

import { version } from './package.json';
console.log(version);

使用

import pkg from './package.json';
console.log(pkg.version);

清理建置程式碼

  • 使用 const compiler = webpack(...); 時,請務必在使用後關閉編譯器:compiler.close(callback);
    • 這不適用於 webpack(..., callback) 形式,它會自動關閉。
    • 如果您在監控模式下使用 webpack,直到使用者結束程序,則這是可選的。監控模式中的閒置階段將用於這類工作。

執行單一建置並遵循建議

請務必仔細閱讀建置錯誤/警告。如果沒有相應的建議,請建立問題,我們將嘗試解決。

重複以下步驟,直到您至少解決等級 3 或 4

  • 等級 1:Schema 驗證失敗

    組態選項已變更。應有包含 BREAKING CHANGE: 註記的驗證錯誤,或提示應改用哪個選項。

  • 等級 2:Webpack 退出時發生錯誤

    錯誤訊息應告訴您需要變更什麼。

  • 等級 3:建置錯誤

    錯誤訊息應有 BREAKING CHANGE: 註記。

  • 等級 4:建置警告

    警告訊息應告訴您可以改善什麼。

  • 等級 5:執行時期錯誤

    這很棘手。您可能必須進行偵錯才能找出問題。這裡很難提供一般建議。但我們在下方列出了一些關於執行時期錯誤的常見建議

    • 未定義 process
      • webpack 5 不再包含此 Node.js 變數的 polyfill。避免在前端程式碼中使用它。
      • 想要支援瀏覽器使用嗎?使用 exportsimports package.json 欄位,以根據環境使用不同的程式碼。
        • 也請使用 browser 欄位來支援較舊的 bundler。
        • 替代方案:使用 typeof process 檢查來包裝程式碼區塊。請注意,這會對套件大小產生負面影響。
      • 想要使用 process.env.VARIABLE 的環境變數嗎?您需要在組態中使用 DefinePluginEnvironmentPlugin 來定義這些變數。
        • 考慮改用 VARIABLE,並確保也檢查 typeof VARIABLE !== 'undefined'process.env 是 Node.js 特有的,應避免在前端程式碼中使用。
    • 指向包含 auto 的 URL 的 404 錯誤
      • 並非所有生態系統工具都已準備好透過 output.publicPath: "auto" 迎接新的預設自動 publicPath
        • 改用靜態 output.publicPath: ""
  • 第 6 級:不建議使用的警告

    您可能會收到許多不建議使用的警告。這並非直接問題。外掛需要時間來趕上核心變更。請向外掛報告這些不建議使用的項目。這些不建議使用的項目僅為警告,而且建置仍會運作,只會有小缺點(例如效能較差)。

    • 您可以使用 --no-deprecation 旗標執行節點來隱藏不建議使用的警告,例如:node --no-deprecation node_modules/webpack/bin/webpack.js。這應僅為暫時解決方案。
    • 外掛和載入項貢獻者可以遵循不建議使用的訊息中的建議來改善程式碼。
  • 第 7 級:效能問題

    通常,效能應會隨著 webpack 5 而提升,但也有少數情況效能會變差。

    以下是您可以採取的步驟來改善情況

    • 剖析時間花費在何處。
      • --profile --progress 現在會顯示簡單的效能剖析
      • node --inspect-brk node_modules/webpack/bin/webpack.js + chrome://inspect / edge://inspect(請參閱剖析器索引標籤)。
        • 您可以將這些剖析儲存到檔案中,並在問題中提供這些剖析。
        • 在某些情況下,嘗試使用 --no-turbo-inlining 旗標以取得更好的堆疊追蹤。
    • 在增量建置中建置模組所需的時間,可以透過還原到 webpack 4 中的不安全快取來改善
      • module.unsafeCache: true
      • 但這可能會影響處理部分程式碼庫變更的能力
    • 完整建置
      • 不建議使用的功能的向下相容性層,通常會比新功能有較差的效能。
      • 建立許多警告可能會影響建置效能,即使這些警告遭到忽略。
      • Source Maps 很昂貴。請查看文件中的 devtool 選項,以比較不同的選項。
      • 防毒軟體保護可能會影響檔案系統存取的效能。
      • 持續快取有助於改善重複的完整建置。
      • 模組聯合允許將應用程式分割成多個較小的建置。

一切都正常嗎?

請發推文表示您已成功移轉到 webpack 5。發推文

無法正常運作嗎?

建立一個 問題,並告訴我們您在移轉期間遇到的問題。

本指南中缺少什麼?

請開啟 Pull Request,以協助下一個使用本指南的人。

內部變更

對於有興趣的人,這裡列出 webpack 內部變更,例如:加入類型、重構程式碼和方法重新命名。但它們並非一般使用案例移轉的一部分。

  • Module.nameForConditionModule.updateCacheModuleModule.chunkCondition 不再是選用的。

載入器的 getOptions 方法

Webpack 5 內建 this.getOptions 方法,可在載入器內容中使用。這對過去使用 schema-utils 中較優先的 getOptions 方法的載入器來說,是一個重大變更。

  • this.getOptions 自 webpack 5 起可用
  • 它支援 JSON 作為查詢字串,而非 JSON5:?{arg:true}?{"arg":true}。應考慮使用 JSON5,並在各自的載入器文件檔中將其記錄為已棄用,以支持 JSON。
  • loader-utils 具有解析查詢字串的特定行為(truefalsenull 將不會解析為 string,而是解析為原始值)。這不再適用於新的內建 this.getOptions 方法,它使用原生 querystring 解析(與 Node.js 搭配使用)。在使用 this.getOptions 方法取得選項後,仍可以在載入器程式碼中為這些情況新增自訂行為。
  • 架構引數對於新的 this.getOptions 方法是選用的,但我們強烈建議為載入器選項新增架構驗證。架構中的 title 欄位可用於自訂驗證錯誤訊息,例如 "title": "My Loader ooooptions" 將會以這種方式顯示錯誤:無效的 ooooptions 物件。My Loader 已使用與 API 架構不符的 ooooptions 物件初始化。- ooooptions.foo.bar.baz 應為字串。

10 貢獻者

sokrasalemhilalkeichingerEugeneHlushkoMattGoldwaterrramaachenxsanjamesgeorge007getsnoopyyevhen-logosha