本 README 适用于 Babel v7 配合 babel-loader v8/v9/v10 使用。如果您正在使用旧版 Babel v6,请参阅 7.x 分支文档。
此包允许使用 Babel 和 webpack 转译 JavaScript 文件。
注意:输出问题应在 Babel 的 Issues 跟踪器上报告。
babel-loader 支持的 webpack 版本 支持的 Babel 版本 支持的 Node.js 版本 8.x 4.x 或 5.x 7.x >= 8.9 9.x 5.x ^7.12.0 >= 14.15.0 10.x ^5.61.0 ^7.12.0 || ^8.0.0-alpha ^18.20.0 || ^20.10.0 || >=22.0.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: {
targets: "defaults",
presets: [
['@babel/preset-env']
]
}
}
}
]
}
请参阅 babel
选项。
你可以通过使用 options
属性将选项传递给加载器
module: {
rules: [
{
test: /\.(?:js|mjs|cjs)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
targets: "defaults",
presets: [
['@babel/preset-env']
],
plugins: ['@babel/plugin-proposal-decorators', { version: "2023-11" }]
}
}
}
]
}
此处传递的 options
将与 Babel 配置文件(例如 babel.config.js
或 .babelrc
)合并。
此加载器还支持以下加载器特定选项
cacheDirectory
:默认为 false
。设置后,给定目录将用于缓存加载器的结果。未来的 webpack 构建将尝试从缓存中读取,以避免每次运行都需要执行可能耗时的 Babel 重新编译过程。如果选项中的值设置为 true
({cacheDirectory: true}
),加载器将使用 node_modules/.cache/babel-loader
中的默认缓存目录,如果任何根目录中找不到 node_modules
文件夹,则回退到默认的 OS 临时文件目录。
cacheIdentifier
:默认是由 @babel/core
的版本和 babel-loader
的版本组成的字符串。最终的缓存 ID 将由输入文件路径、通过 Babel.loadPartialConfigAsync
合并的 Babel 配置以及 cacheIdentifier
确定。合并后的 Babel 配置将由 babel.config.js
或 .babelrc
文件(如果存在)或环境变量 BABEL_ENV
和 NODE_ENV
的值决定。cacheIdentifier
可以设置为自定义值,以在标识符更改时强制清除缓存。
cacheCompression
:默认为 true
。设置后,每个 Babel 转换输出都将用 Gzip 压缩。如果你想禁用缓存压缩,请将其设置为 false
—— 如果你的项目转译数千个文件,这可能会有帮助。
customize
:默认为 null
。导出 custom
回调的模块路径,类似于你传递给 .custom()
的回调。由于你必须创建一个新文件才能使用此功能,因此建议你改为使用 .custom
来创建包装加载器。仅当你必须直接使用 babel-loader
但仍想自定义时才使用此功能。
metadataSubscribers
:默认为 []
。接受一个上下文函数名称数组。例如,如果你传递 ['myMetadataPlugin'],你将在你的 webpack 插件的钩子中将订阅函数分配给 context.myMetadataPlugin
,并且该函数将使用 metadata
调用。有关示例,请参阅 https://github.com/babel/babel-loader/main/test/metadata.test.js
。
指定 webpack 选项 stats.loggingDebug
以输出详细的调试日志。
// webpack.config.js
module.exports = {
// ...
stats: {
loggingDebug: ["babel-loader"]
}
}
确保你转换的文件尽可能少。因为你可能匹配了 /\.m?js$/
,所以你可能会转换 node_modules
文件夹或其他不需要的源。
要排除 node_modules
,请参阅上面文档中 loaders
配置中的 exclude
选项。
你还可以通过使用 cacheDirectory
选项将 babel-loader 的速度提高多达 2 倍。这会将转换结果缓存到文件系统。
node_modules
中的某些文件未为 IE 11 转译尽管我们通常建议不要编译 node_modules
,但在使用不支持 IE 11 或任何旧版目标的库时,你可能需要这样做。
为此,你可以使用 test
和 not
的组合,或者向你的 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 为诸如 _extend
等常见函数使用非常小的 helper。默认情况下,这将被添加到每个需要它的文件中。
你可以改为将 Babel 运行时作为一个单独的模块来避免重复。
以下配置禁用了 Babel 中每个文件的自动运行时注入,转而需要 @babel/plugin-transform-runtime
,并使所有 helper 引用都使用它。
有关更多信息,请参阅文档。
注意:你必须运行 npm install -D @babel/plugin-transform-runtime
将其包含在你的项目中,并运行 npm install @babel/runtime
将 @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']
}
}
}
]
由于 @babel/plugin-transform-runtime 包含一个 polyfill,其中包括自定义的 regenerator-runtime 和 core-js,因此以下使用 webpack.ProvidePlugin
的常规 shimming 方法将不起作用
// ...
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-js
和 webpack/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"
]
}
}
该函数由 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 支持打包多个目标。对于你可能希望为每个目标(例如 web
和 node
)使用不同的 Babel 配置的情况,此加载器通过 Babel 的 caller API 提供一个 target
属性。
例如,根据 webpack 目标更改传递给 @babel/preset-env
的环境目标
// babel.config.js
module.exports = api => {
return {
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.transform
的 options
对象。
result(result: Result): Result
给定 Babel 的结果对象,允许加载器对其进行额外调整。