跳至主内容

配置 Babel

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

Babel 是可配置的!许多其他工具也有类似的配置文件:ESLint(.eslintrc)、Prettier(.prettierrc)。

所有 Babel API 的选项均可使用。但如果选项需要 JavaScript 实现,建议使用 JavaScript 配置文件

你的使用场景是什么?

  • 你正在使用 monorepo?

  • 你需要编译 node_modules

babel.config.json 就是为你准备的!

  • 你的配置仅适用于项目的特定部分?

.babelrc.json 就是为你准备的!

  • Guy Fieri 是你的偶像?

我们推荐使用 babel.config.json 格式

babel.config.json

在项目根目录(即 package.json 所在位置)创建名为 babel.config.json 的文件,内容如下:

babel.config.json
{
"presets": [...],
"plugins": [...]
}

查看 babel.config.json 文档 获取更多配置选项

.babelrc.json

在项目中创建名为 .babelrc.json 的文件,内容如下:

.babelrc.json
{
"presets": [...],
"plugins": [...]
}

查看 .babelrc 文档 获取更多配置选项

package.json

或者,你可以通过 package.json 中的 babel 字段指定 .babelrc.json 配置:

package.json
{
"name": "my-package",
"version": "1.0.0",
"babel": {
"presets": [ ... ],
"plugins": [ ... ],
}
}

JavaScript 配置文件

你也可以使用 JavaScript 编写 babel.config.js参考我们的实现)和 .babelrc.js 文件:

babel.config.js
module.exports = function (api) {
api.cache(true);

const presets = [ ... ];
const plugins = [ ... ];

return {
presets,
plugins
};
}

你可以访问任何 Node.js API,例如根据进程环境进行动态配置:

babel.config.js
module.exports = function (api) {
api.cache(true);

const presets = [ ... ];
const plugins = [ ... ];

if (process.env["ENV"] === "prod") {
plugins.push(...);
}

return {
presets,
plugins
};
}

更多细节请参阅 JavaScript 配置文件专用文档

使用 CLI (@babel/cli)

Shell
babel --plugins @babel/plugin-transform-arrow-functions script.js

查看 babel-cli 文档 获取更多配置选项

使用 API (@babel/core)

JavaScript
require("@babel/core").transformSync("code", {
plugins: ["@babel/plugin-transform-arrow-functions"],
});

查看 babel-core 文档 获取更多配置选项

打印有效配置

你可以让 Babel 在指定输入路径上打印有效配置

# *nix or WSL
BABEL_SHOW_CONFIG_FOR=./src/myComponent.jsx npm start

BABEL_SHOW_CONFIG_FOR 同时接受绝对和相对_文件_路径。相对路径将从 cwd 解析

当 Babel 处理完 BABEL_SHOW_CONFIG_FOR 指定的输入文件后,会将有效配置打印到控制台。示例输出如下:

Babel configs on "/path/to/cwd/src/index.js" (ascending priority):
config /path/to/cwd/babel.config.json
{
"sourceType": "script",
"plugins": [
"@foo/babel-plugin-1"
],
"extends": "./my-extended.js"
}

config /path/to/cwd/babel.config.json .env["test"]
{
"plugins": [
[
"@foo/babel-plugin-3",
{
"noDocumentAll": true
},
]
]
}

config /path/to/cwd/babel.config.json .overrides[0]
{
"test": "src/index.js",
"sourceMaps": true
}

config /path/to/cwd/.babelrc
{}

programmatic options from @babel/cli
{
"sourceFileName": "./src/index.js",
"presets": [
"@babel/preset-env"
],
"configFile": "./my-config.js",
"caller": {
"name": "@babel/cli"
},
"filename": "./src/index.js"
}

Babel 会按优先级升序列出配置来源。以上述示例为例,优先级顺序为:

babel.config.json < .babelrc < programmatic options from @babel/cli

换言之,babel.config.json 会被 .babelrc 覆盖,而 .babelrc 又会被编程式选项覆盖

对于每个配置源,Babel 会按优先级升序列出适用的配置项(例如 overridesenv)。通常每个配置源至少包含一个配置项——即配置文件的根内容。如果配置了 overridesenv,Babel 不会在根节点输出,而是以 .overrides[index] 的形式单独输出配置项(index 表示项的位置)。这有助于判断该配置项是否对输入生效以及它将覆盖哪些配置。

如果输入文件被 ignoreonly 规则排除,Babel 将提示该文件已被忽略。

Babel 如何合并配置项

Babel 的配置合并机制相对直接:当配置项存在且值不为 undefined 时,新选项会覆盖已有选项。但存在以下特殊情况:

  • 对于 assumptionsparserOptsgeneratorOpts 选项,采用对象合并策略而非整体替换

  • 对于 pluginspresets 数组,根据插件/预设对象/函数的身份标识(结合条目名称)进行替换

常规配置项(除插件/预设外)的合并

例如,考虑以下配置:

JavaScript
{
sourceType: "script",
assumptions: {
setClassFields: true,
iterableIsArray: false
},
env: {
test: {
sourceType: "module",
assumptions: {
iterableIsArray: true,
},
}
}
};

NODE_ENVtest 时,sourceType 选项会被替换,而 assumptions 选项会被合并。最终生效的配置为:

JavaScript
{
sourceType: "module", // sourceType: "script" is overwritten
assumptions: {
setClassFields: true,
iterableIsArray: true, // assumptions are merged by Object.assign
},
}

插件/预设的合并

例如,考虑以下配置:

JavaScript
plugins: [
'./other',
['./plug', { thing: true, field1: true }]
],
overrides: [{
plugins: [
['./plug', { thing: false, field2: true }],
]
}]

overrides 配置项会被合并到顶层选项之上。关键在于,plugins 数组并非整体替换顶层的数组。合并逻辑会识别到 "./plug" 是同一个插件,于是 { thing: false, field2: true } 将替换原有选项,最终生成如下配置:

JavaScript
plugins: [
'./other',
['./plug', { thing: false, field2: true }],
],

由于合并基于插件身份标识+名称,在同一个 plugins/presets 数组中重复使用同名插件会导致错误。例如:

JavaScript
plugins: ["./plug", "./plug"];

这会被视为错误,因为它等同于 plugins: ['./plug']。此外,即使

JavaScript
plugins: [["./plug", { one: true }], ["./plug", { two: true }]];

这被认为是一个错误,因为第二个总是会替换第一个。

如需实例化插件的两个独立副本,必须通过唯一名称进行区分:

JavaScript
plugins: [
["./plug", { one: true }, "first-instance-name"],
["./plug", { two: true }, "second-instance-name"],
];

此时每个实例具有唯一名称,因此拥有独立身份标识。