babel-loader

免責聲明: babel-loader 是由社群成員維護的第三方套件,它可能沒有與 webpack 相同的支援、安全性政策或授權,且並非由 webpack 維護。

此 README 適用於搭配 Babel v7 的 babel-loader v8/v9。如果您使用舊版 Babel v6,請參閱 7.x 分支 文件

NPM Status codecov

此套件允許使用 Babelwebpack 來轉譯 JavaScript 檔案。

注意:輸出問題應回報給 Babel 問題 追蹤器。

安裝

babel-loader支援的 webpack 版本支援的 Babel 版本支援的 Node.js 版本
8.x4.x 或 5.x7.x>= 8.9
9.x5.x^7.12.0>= 14.15.0
npm install -D babel-loader @babel/core @babel/preset-env webpack

用法

webpack 文件:載入器

在 webpack 組態物件中,您需要將 babel-loader 加入模組清單,如下所示

module: {
  rules: [
    {
      test: /\.(?:js|mjs|cjs)$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env', { targets: "defaults" }]
          ]
        }
      }
    }
  ]
}

選項

請參閱 babel 選項

您可以透過使用 options 屬性將選項傳遞給載入器

module: {
  rules: [
    {
      test: /\.(?:js|mjs|cjs)$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env', { targets: "defaults" }]
          ],
          plugins: ['@babel/plugin-proposal-class-properties']
        }
      }
    }
  ]
}

此載入器還支援下列載入器特定選項

  • cacheDirectory:預設為 false。設定後,將使用指定的目錄快取載入器的結果。未來的 webpack 建置會嘗試從快取中讀取,以避免在每次執行時執行可能耗時的 Babel 重新編譯程序。如果在選項中將值設定為 true{cacheDirectory: true}),載入器將使用 node_modules/.cache/babel-loader 中的預設快取目錄,或是在任何根目錄中找不到 node_modules 資料夾時退回到預設的 OS 暫存檔案目錄。

  • cacheIdentifier:預設為由 @babel/core 的版本、babel-loader 的版本、.babelrc 檔案的內容(如果存在),以及環境變數 BABEL_ENV 的值(退回到環境變數 NODE_ENV)組成的字串。如果識別碼變更,可以將此設定為自訂值以強制快取失效。

  • cacheCompression:預設為 true。設定後,每個 Babel 轉換輸出都會使用 Gzip 壓縮。如果您想退出快取壓縮,請將其設定為 false -- 如果您的專案編譯了數千個檔案,這可能會對您的專案有幫助。

  • customize:預設為 null。匯出 custom 回呼的模組路徑,類似傳遞給 .custom() 的路徑。由於你已經建立新的檔案來使用此功能,建議改用 .custom 建立包裝載入器。只有在必須繼續直接使用 babel-loader,但仍想自訂時,才使用此功能。

  • metadataSubscribers:預設為 []。採用內容函式名稱陣列。例如,如果你傳遞 ['myMetadataPlugin'],你會在 webpack 外掛的掛勾中將訂閱函式指定給 context.myMetadataPlugin,而該函式將會呼叫 metadata

疑難排解

babel-loader 很慢!

請確定你轉換的檔案越少越好。由於你可能比對 /\.m?js$/,你可能會轉換 node_modules 資料夾或其他不需要的來源。

若要排除 node_modules,請參閱上方所述的 loaders 設定中的 exclude 選項。

你也可以透過使用 cacheDirectory 選項,將 babel-loader 的速度提升至 2 倍。這會將轉換快取至檔案系統。

我的 node_modules 中的某些檔案未轉譯為 IE 11

雖然我們通常建議不要編譯 node_modules,但你可能需要在使用不支援 IE 11 或任何舊版目標的函式庫時進行編譯。

針對這個情況,你可以使用 testnot 的組合,或 傳遞函式 給你的 exclude 選項。你也可以使用負向先行斷言正規表示法,如 此處 所建議。

{
    test: /\.(?:js|mjs|cjs)$/,
    exclude: {
      and: [/node_modules/], // Exclude libraries in node_modules ...
      not: [
        // Except for a few of them that needs to be transpiled because they use modern syntax
        /unfetch/,
        /d3-array|d3-scale/,
        /@hapi[\\/]joi-date/,
      ]
    },
    use: {
      loader: 'babel-loader',
      options: {
        presets: [
          ['@babel/preset-env', { targets: "ie 11" }]
        ]
      }
    }
  }

Babel 將輔助程式注入每個檔案,並膨脹我的程式碼!

Babel 使用非常小的輔助程式來執行一般函式,例如 _extend。預設情況下,這會新增至需要它的每個檔案。

你也可以將 Babel 執行時間作為獨立模組來需要,以避免重複。

下列設定會停用 Babel 中的自動逐檔案執行時間注入,而需要 @babel/plugin-transform-runtime,並讓所有輔助程式參考都使用它。

請參閱 文件 以取得更多資訊。

注意:你必須執行 npm install -D @babel/plugin-transform-runtime 才能將其包含在你的專案中,並將 @babel/runtime 本身作為相依性,並使用 npm install @babel/runtime

rules: [
  // the 'transform-runtime' plugin tells Babel to
  // require the runtime instead of inlining it.
  {
    test: /\.(?:js|mjs|cjs)$/,
    exclude: /node_modules/,
    use: {
      loader: 'babel-loader',
      options: {
        presets: [
          ['@babel/preset-env', { targets: "defaults" }]
        ],
        plugins: ['@babel/plugin-transform-runtime']
      }
    }
  }
]

注意:transform-runtime 和自訂多重載入 (例如 Promise 函式庫)

由於 @babel/plugin-transform-runtime 包含一個多重載入,其中包含自訂 regenerator-runtimecore-js,因此下列使用 webpack.ProvidePlugin 的一般性假冒方法將無法運作

// ...
        new webpack.ProvidePlugin({
            'Promise': 'bluebird'
        }),
// ...

下列方法也無法運作

require('@babel/runtime/core-js/promise').default = require('bluebird');

var promise = new Promise;

輸出為 (使用 runtime)

'use strict';

var _Promise = require('@babel/runtime/core-js/promise')['default'];

require('@babel/runtime/core-js/promise')['default'] = require('bluebird');

var promise = new _Promise();

前一個 Promise 函式庫在被覆寫之前被參考並使用。

一種方法是在你的應用程式中有一個「開機」步驟,在你的應用程式之前覆寫預設全域變數

// bootstrap.js

require('@babel/runtime/core-js/promise').default = require('bluebird');

// ...

require('./app');

babel 的 Node.js API 已移至 babel-core

如果您收到此訊息,表示您已安裝 npm 套件 babel,並在 webpack 設定中使用載入器的簡寫符號(在 webpack 2.x 中已不再有效)

  {
    test: /\.(?:js|mjs|cjs)$/,
    loader: 'babel',
  }

webpack 接著會嘗試載入 babel 套件,而不是 babel-loader

若要修正此問題,您應該解除安裝 npm 套件 babel,因為它已在 Babel v6 中棄用。(請改為安裝 @babel/cli@babel/core。)如果您的其中一個相依性正在安裝 babel,而您無法自行解除安裝,請在 webpack 設定中使用載入器的完整名稱

  {
    test: /\.(?:js|mjs|cjs)$/,
    loader: 'babel-loader',
  }

排除不應轉譯的函式庫

如果 core-jswebpack/buildin 被 Babel 轉譯,將會造成錯誤。

您需要將它們從 babel-loader 中排除。

{
  "loader": "babel-loader",
  "options": {
    "exclude": [
      // \\ for Windows, / for macOS and Linux
      /node_modules[\\/]core-js/,
      /node_modules[\\/]webpack[\\/]buildin/,
    ],
    "presets": [
      "@babel/preset-env"
    ]
  }
}

頂層函式 (IIFE) 在 Webpack 5 中仍為箭頭函式

該函式是由 Webpack 本身在執行 babel-loader 之後 注入的。預設情況下,Webpack 假設您的目標環境支援部分 ES2015 功能,但您可以使用 output.environment Webpack 選項(文件)覆寫此行為。

若要避免頂層箭頭函式,您可以使用 output.environment.arrowFunction

// webpack.config.js
module.exports = {
  // ...
  output: {
    // ...
    environment: {
      // ...
      arrowFunction: false, // <-- this line does the trick
    },
  },
};

根據 webpack 目標自訂設定

Webpack 支援組合多個 目標。對於您可能想要為每個目標(例如 web node)使用不同 Babel 設定的情況,此載入器透過 Babel 的 caller API 提供 target 屬性。

例如,若要根據 webpack 目標變更傳遞給 @babel/preset-env 的環境目標

// babel.config.js

module.exports = api => {
  return {
    plugins: [
      "@babel/plugin-proposal-nullish-coalescing-operator",
      "@babel/plugin-proposal-optional-chaining"
    ],
    presets: [
      [
        "@babel/preset-env",
        {
          useBuiltIns: "entry",
          // caller.target will be the same as the target option from webpack
          targets: api.caller(caller => caller && caller.target === "node")
            ? { node: "current" }
            : { chrome: "58", ie: "11" }
        }
      ]
    ]
  }
}

自訂載入器

babel-loader 公開一個載入器建構器工具程式,讓使用者可以為每個它處理的檔案新增 Babel 組態的自訂處理。

.custom 接受一個回呼函式,該函式會使用載入器的 babel 實例呼叫,以便工具程式可以確保它使用與載入器本身完全相同的 @babel/core 實例。

在您想要自訂但實際上沒有檔案可以呼叫 .custom 的情況下,您也可以傳遞 customize 選項,並附帶指向匯出您的 custom 回呼函式的檔案的字串。

範例

// Export from "./my-custom-loader.js" or whatever you want.
module.exports = require("babel-loader").custom(babel => {
  // Extract the custom options in the custom plugin
  function myPlugin(api, { opt1, opt2 }) {
    return {
      visitor: {},
    };
  }

  return {
    // Passed the loader options.
    customOptions({ opt1, opt2, ...loader }) {
      return {
        // Pull out any custom options that the loader might have.
        custom: { opt1, opt2 },

        // Pass the options back with the two custom options removed.
        loader,
      };
    },

    // Passed Babel's 'PartialConfig' object.
    config(cfg, { customOptions }) {
      if (cfg.hasFilesystemConfig()) {
        // Use the normal config
        return cfg.options;
      }

      return {
        ...cfg.options,
        plugins: [
          ...(cfg.options.plugins || []),

          // Include a custom plugin in the options and passing it the customOptions object.
          [myPlugin, customOptions],
        ],
      };
    },

    result(result) {
      return {
        ...result,
        code: result.code + "\n// Generated by some custom loader",
      };
    },
  };
});
// And in your Webpack config
module.exports = {
  // ..
  module: {
    rules: [{
      // ...
      loader: path.join(__dirname, 'my-custom-loader.js'),
      // ...
    }]
  }
};

customOptions(options: Object): { custom: Object, loader: Object }

針對載入器的選項,將自訂選項從 babel-loader 的選項中拆分出來。

config(cfg: PartialConfig, options: { source, customOptions }): Object

針對 Babel 的 PartialConfig 物件,傳回應該傳遞給 babel.transformoptions 物件。

result(result: Result): Result

針對 Babel 的結果物件,允許載入器對它進行額外的調整。

授權

MIT