Skip to main content

配置文件

配置文件类型​

🌐 Configuration File Types

Babel 有两种并行的配置文件格式,可以一起使用,也可以单独使用。

🌐 Babel has two parallel config file formats, which can be used together, or independently.

历史
版本更新内容
v7.21.0支持 .babelrc.cts 和 babel.config.cts(实验性)
v7.8.0支持 .babelrc.mjs 和 babel.config.mjs
v7.7.0支持 .babelrc.json、.babelrc.cjs、babel.config.json、babel.config.cjs
  • 项目范围的配置
    • babel.config.* 文件,扩展名包括:.json、.js、.cjs、.mjs、.cts。
  • 文件相关配置
    • .babelrc.* 文件,扩展名包括:.json、.js、.cjs、.mjs、.cts。
    • .babelrc 文件,没有扩展名。
    • package.json 文件,带有 "babel" 密钥。

项目范围的配置​

🌐 Project-wide configuration

在 Babel 7.x 中新增了一个“根”目录概念,默认是当前工作目录。对于整个项目的配置,Babel 会在这个根目录中自动搜索 babel.config.json 文件,或者使用 支持的扩展名 的同类文件。或者,用户也可以使用明确的 “configFile” 值来覆盖默认的配置文件搜索行为。

🌐 New in Babel 7.x, Babel has a concept of a "root" directory, which defaults to the current working directory. For project-wide configuration, Babel will automatically search for a babel.config.json file, or an equivalent one using the supported extensions, in this root directory. Alternatively, users can use an explicit "configFile" value to override the default config file search behavior.

因为项目范围的配置文件与配置文件的物理位置分开,所以它们非常适合需要广泛应用的配置,甚至允许插件和预设轻松应用到 node_modules 中的文件或符号链接的包里,而这些在 Babel 6.x 中配置起来通常很麻烦。

🌐 Because project-wide config files are separated from the physical location of the config file, they can be ideal for configuration that must apply broadly, even allowing plugins and presets to easily apply to files in node_modules or in symlinked packages, which were traditionally quite painful to configure in Babel 6.x.

这个项目级配置的主要缺点是,因为它依赖于工作目录,如果工作目录不是 monorepo 根目录,在 monorepo 中使用起来会更麻烦。有关如何在这种情况下使用配置文件的示例,请参见 monorepo 文档。

🌐 The primary downside of this project-wide config is that, because it relies on the working directory, it can be more painful to use in monorepos if the working directory is not the monorepo root. See the monorepo documentation for examples of how to use config files in that context.

通过将 "configFile" 设置为 false,也可以禁用整个项目的配置。

🌐 Project-wide configs can also be disabled by setting "configFile" to false.

文件相关配置​

🌐 File-relative configuration

Babel 会加载 .babelrc.json 文件,或者使用 支持的扩展 的等效文件,它会从正在编译的 "文件名" 开始,沿目录结构向上搜索(受下面注意事项的限制)。 这很强大,因为它允许你为包的子部分创建独立的配置。相对于文件的配置也会 合并 到项目范围的配置值之上,这使它在特定覆盖情况下可能很有用,尽管这也可以通过 "overrides" 来实现。

🌐 Babel loads .babelrc.json files, or an equivalent one using the supported extensions, by searching up the directory structure starting from the "filename" being compiled (limited by the caveats below). This can be powerful because it allows you to create independent configurations for subsections of a package. File-relative configurations are also merged over top of project-wide config values, making them potentially useful for specific overrides, though that can also be accomplished through "overrides".

使用文件相对配置时需要考虑一些边缘情况:

🌐 There are a few edge cases to consider when using a file-relative config:

  • 一旦找到包含 package.json 的目录,搜索就会停止,所以相对配置只在单个包内生效。
  • 正在编译的 "filename" 必须位于 "babelrcRoots" 包内,否则搜索将会被完全跳过。

这些警告意味着:

🌐 These caveats mean that:

  • .babelrc.json 文件只适用于它们自己包内的文件
  • 除非你通过 "babelrcRoots" 选择加入,否则不在 Babel ‘根’ 的包中的 .babelrc.json 文件会被忽略。

请查看 monorepo 文档,了解更多关于如何配置包含许多包的 monorepo 的讨论。通过将 "babelrc" 设置为 false,也可以禁用相对于文件的配置。

🌐 See the monorepo documentation for more discussion on how to configure monorepos that have many packages. File-relative configs can also be disabled by setting "babelrc" to false.

note

出于兼容性原因,.babelrc 是 .babelrc.json 的别名。

6.x 与 7.x 的 .babelrc 加载​

🌐 6.x vs 7.x .babelrc loading

来自 Babel 6.x 的用户很可能会在这两个边缘情况上碰壁,这在 Babel 7.x 中是新的。 这两项限制是为了应对 Babel 6.x 中常见的问题而增加的:

🌐 Users coming from Babel 6.x will likely trip up on these two edge cases, which are new in Babel 7.x. These two restrictions were added to address common footguns in Babel 6.x:

  • .babelrc 文件应用到 node_modules 依赖上,常常出乎意料。
  • .babelrc 文件 未能 应用到符号链接的 node_modules 上,而人们本以为它们会像普通依赖一样工作。
  • .babelrc 文件中的 node_modules 依赖会被检测到,即使其中的插件和预设通常没安装,甚至在编译该文件的 Babel 版本中可能都不适用。

这些情况主要会给使用单一代码库结构的用户带来问题,因为如果你有

🌐 These cases will primarily cause issues for users with a monorepo structure, because if you have

.babelrc
packages/
mod1/
package.json
src/index.js
mod2/
package.json
src/index.js

配置现在将被完全忽略,因为它跨越了包边界。

🌐 the config will now be entirely ignored, because it is across a package boundary.

一种替代方法是在每个子包中创建一个 .babelrc,它使用 "extends" 作为

🌐 One alternative would be to create a .babelrc in each sub-package that uses "extends" as

.babelrc.json
{ "extends": "../../.babelrc" }

不幸的是,这种方法可能有点重复,而且根据 Babel 的使用方式,可能需要设置 "babelrcRoots" 。

🌐 Unfortunately, this approach can be a bit repetitive, and depending on how Babel is being used, could require setting "babelrcRoots".

鉴于此,把 .babelrc 重命名为项目范围的 "babel.config.json" 可能更合适。如上面项目范围部分提到的,这可能需要显式设置 "configFile",因为如果工作目录不正确,Babel 是找不到配置文件的。

🌐 Given that, it may be more desirable to rename the .babelrc to be a project-wide "babel.config.json". As mentioned in the project-wide section above, this may then require explicitly setting "configFile" since Babel will not find the config file if the working directory isn't correct.

支持的文件扩展名​

🌐 Supported file extensions

Babel 可以使用 Node.js 原生支持的任何文件扩展名进行配置,如 Configuration File Types 部分所述:

🌐 Babel can be configured using any file extension natively supported by Node.js, as mentioned in Configuration File Types section:

  • babel.config.json 和 .babelrc.json 会被解析为 JSON5,并且应该包含一个符合 Babel 接受的 options 格式的对象。从 v7.7.0 开始,它们就已经被支持了。

    我们建议尽可能使用这种文件类型:如果你的配置比较复杂,需要根据条件或在构建时计算,JS 配置文件会很方便。不过,缺点是 JS 配置文件不太容易做静态分析,因此会对缓存、代码检查、IDE 自动补全等产生负面影响。由于 babel.config.json 和 .babelrc.json 是静态 JSON 文件,这让使用 Babel 的其他工具(比如打包器)可以安全地缓存 Babel 的结果,这对构建性能来说是个很大的提升。

  • babel.config.cjs 和 .babelrc.cjs 允许你使用 module.exports 将你的配置定义为 CommonJS。它们从 v7.7.0 开始就被支持了。

  • babel.config.mjs 和 .babelrc.mjs 使用原生 ECMAScript 模块。它们在 Node.js 13.2 及以上版本支持(或者在旧版本通过 --experimental-modules 标志支持)。请记住,原生 ECMAScript 模块是异步的(这就是为什么 import() 总是返回一个 promise!):因此,当同步调用 Babel 时,.mjs 配置文件会抛出错误。自 v7.8.0 起,它们就已经被支持了。

  • babel.config.js 和 .babelrc.js 当你的 package.json 文件包含 "type": "module" 选项时,表现得像 .mjs 对应的版本,否则它们和 .cjs 文件完全一样。

Babel 也支持 TypeScript 配置文件,可以使用 .ts/.mts/.cts 扩展名来代替 .js/.mjs/.cjs。

🌐 Babel also supports TypeScript config files, using .ts/.mts/.cts extensions in place of .js/.mjs/.cjs.

JavaScript 配置文件可以导出一个对象,或者导出一个函数,调用该函数时会返回生成的配置。返回函数的配置拥有一些特殊功能,因为它们可以访问 Babel 本身提供的 API。更多信息请参见 配置函数 API。

🌐 JavaScript configuration files can either export an object, or a function that when called will return the generated configuration. Function-returning configs are given a few special powers because they can access an API exposed by Babel itself. See Config Function API for more information.

大仓​

🌐 Monorepos

采用 Monorepo 结构的仓库通常包含许多包,这意味着它们经常会遇到 基于文件的配置 和配置文件加载中提到的注意事项。本节旨在帮助用户了解如何处理 Monorepo 配置。

🌐 Monorepo-structured repositories usually contain many packages, which means that they frequently run into the caveats mentioned in file-relative configuration and config file loading in general. This section is aimed at helping users understand how to approach monorepo configuration.

在 monorepo 设置中,需要理解的核心是 Babel 会把你的工作目录当作它的逻辑根,如果你想在某个特定子包中运行 Babel 工具而不让 Babel 应用于整个仓库,这就会导致问题。

🌐 With monorepo setups, the core thing to understand is that Babel treats your working directory as its logical "root", which causes problems if you want to run Babel tools within a specific sub-package without having Babel apply to the repo as a whole.

另外,决定你是想使用 .babelrc.json 文件还是只用一个中央 babel.config.json 也很重要。.babelrc.json 文件不像 Babel 6 那样对子文件夹的特定配置是必需的,所以在 Babel 7 中通常不需要它们,而是更倾向于使用 babel.config.json。

🌐 Separately, it is also important to decide if you want to use .babelrc.json files or just a central babel.config.json. .babelrc.json files are not required for subfolder-specific configuration like they were in Babel 6, so often they are not needed in Babel 7, in favor of babel.config.json.

根 babel.config.json 文件​

🌐 Root babel.config.json file

在任何 monorepo 结构中,第一步应该是在仓库根目录创建一个 babel.config.json 文件。这可以建立 Babel 的核心概念——你的仓库的基目录。即使你想使用 .babelrc.json 文件来配置每个单独的包,拥有一个用于仓库级别选项的地方也是很重要的。

🌐 The first step in any monorepo structure should be to create a babel.config.json file in repository root. This establishes Babel's core concept of the base directory of your repository. Even if you want to use .babelrc.json files to configure each separate package, it is important to have as a place for repo-level options.

你通常可以把所有的仓库配置放在根目录下的 babel.config.json。 使用 "overrides",你可以轻松地指定仅适用于仓库某些子文件夹的配置,这通常比在整个仓库中创建很多 .babelrc.json 文件更容易理解。

🌐 You can often place all of your repo configuration in the root babel.config.json. With "overrides", you can easily specify configuration that only applies to certain subfolders of your repository, which can often be easier to follow than creating many .babelrc.json files across the repo.

你可能会遇到的第一个问题是,默认情况下,Babel 期望从设置为其“根”的目录加载babel.config.json文件,这意味着如果你创建了babel.config.json,但在单独的包内运行 Babel,例如。

🌐 The first issue you'll likely run into is that by default, Babel expects to load babel.config.json files from the directory set as its "root", which means that if you create a babel.config.json, but run Babel inside an individual package, e.g.

Shell
cd packages/some-package;
babel src -d dist

在那个上下文中,Babel 使用的 "root" 并 不是 你的 monorepo 根目录,而且它也找不到 babel.config.json 文件。

🌐 the "root" Babel is using in that context is not your monorepo root, and it won't be able to find the babel.config.json file.

如果你所有的构建脚本都是相对于你的仓库根目录运行的,应该已经可以正常工作,但如果你是在子包里运行 Babel 编译过程,你需要告诉 Babel 去哪里找配置文件。有几种方法可以做到这一点,但推荐的方式是使用带有 "upward" 的 "rootMode" 选项,这会让 Babel 从当前工作目录向上查找 babel.config.json 文件,并把它的位置作为 "root" 的值。

🌐 If all of your build scripts run relative to your repository root, things should already work, but if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the "rootMode" option with "upward", which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the "root" value.

测试你的配置是否被检测到的一个有用方法是,如果它是一个 babel.config.json JavaScript 文件,可以在里面放一个 console.log() 调用:日志会在 Babel 第一次加载它时执行。

🌐 One helpful way to test if your config is being detected is to place a console.log() call inside of it if it is a babel.config.json JavaScript file: the log will execute the first time Babel loads it.

设置此值的方式因项目而异,但这里有几个示例:

🌐 How you set this value varies by project, but here are a few examples:

命令行接口​

🌐 CLI

Shell
babel --root-mode upward src -d lib

@babel/register​

JavaScript
require("@babel/register")({
rootMode: "upward",
});

Webpack​

webpack.config.js
module: {
rules: [
{
loader: "babel-loader",
options: {
rootMode: "upward",
},
},
];
}

Jest​

Jest 通常安装在 monorepo 的根目录,可能不需要配置,但如果按包安装的话,配置起来就可能会更复杂。

🌐 Jest is often installed at the root of the monorepo and may not require configuration, but if it is installed per-package it can unfortunately be more complex to configure.

主要部分是创建一个自定义的 jest 转换器文件,封装 babel-jest 的默认行为,以便设置选项,例如。

🌐 The main part is creating a custom jest transformer file that wraps babel-jest's default behavior in order to set the option, e.g.

wrapper.js
module.exports = require("babel-jest").default.createTransformer({
rootMode: "upward",
});

把它保存到某个地方后,你就可以在 Jest 配置中的 babel-jest 位置使用这个文件,通过 transform 选项 来实现:

🌐 and with that saved somewhere, you'd then use that file in the place of babel-jest in your Jest options via the transform option:

jest.config.js
"transform": {
"^.+\\.jsx?$": "./path/to/wrapper.js"
},

所以所有的 JS 文件都会使用你启用选项的 babel-jest 版本来处理。

🌐 so all JS files will be processed with your version of babel-jest with the option enabled.

note

当使用 babel-jest < 27 时,你必须省略 .default 部分:require("babel-jest").createTransformer({ ...。

其他的​

🌐 Others

有很多工具,但关键是如果工作目录还不是 monorepo 根目录,它们需要启用 rootMode 选项。

🌐 There are tons of tools, but at the core of it is that they need the rootMode option enabled if the working directory is not already the monorepo root.

子包 .babelrc.json 文件​

🌐 Subpackage .babelrc.json files

类似于 babel.config.json 文件需要放在 "root" 的方式,.babelrc.json 文件默认也必须放在根 package 中。这意味着,就像工作目录会影响 babel.config.json 的加载一样,它也会影响 .babelrc.json 的加载。

🌐 Similar to the way babel.config.json files are required to be in the "root", .babelrc.json files must be in the root package, by default. This means that, the same way the working directory affects babel.config.json loading, it also affects .babelrc.json loading.

假设你已经按照上面讨论的方式正确加载了你的babel.config.json文件,Babel只会处理该根包内的.babelrc.json文件(不会处理子包),所以比如说

🌐 Assuming you've already gotten your babel.config.json file loaded properly as discussed above, Babel will only process .babelrc.json files inside that root package (and not subpackages), so given for instance

package.json
babel.config.js
packages/
mod/
package.json
.babelrc.json
index.js

编译 packages/mod/index.js 文件不会加载 packages/mod/.babelrc.json,因为这个 .babelrc.json 在一个子包里,而不是根包。

🌐 compiling the packages/mod/index.js file will not load packages/mod/.babelrc.json because this .babelrc.json is within a sub-package, not the root package.

要处理那个 .babelrc.json,你会想在你的 babel.config.json 文件里使用 "babelrcRoots" 选项来做

🌐 To enable processing of that .babelrc.json, you will want to use the "babelrcRoots" option from inside your babel.config.json file to do

JavaScript
babelrcRoots: [
".",
"packages/*",
],

这样 Babel 会将所有 packages/* 包视为允许加载 .babelrc.json 文件的,同时包括原始的仓库根目录。

🌐 so that Babel will consider all packages/* packages as allowed to load .babelrc.json files, along with the original repo root.

配置函数接口​

🌐 Config Function API

JS 配置文件可能会导出一个函数,该函数将配置 API 作为参数:

🌐 JS config files may export a function that gets the config API as a parameter:

babel.config.js
/**
* @param {import("@babel/core").ConfigAPI} api
* @returns {import("@babel/core").InputOptions}
*/
module.exports = function(api) {
return {};
};

ConfigAPI 对象 api 提供以下属性或方法:

🌐 The ConfigAPI object api provides the following properties or methods:

api.version​

类型: string

🌐 Type: string

正在加载配置文件的 Babel 版本的版本字符串。

🌐 The version string for the Babel version that is loading the config file.

api.cache​

JS 配置很棒,因为它们可以即时计算配置,但缺点是这会让缓存变得更难。Babel 想要避免每次编译文件时都重新执行配置函数,因为那样它也需要重新执行配置中引用的任何插件和预设函数。

🌐 JS configs are great because they can compute a config on the fly, but the downside there is that it makes caching harder. Babel wants to avoid re-executing the config function every time a file is compiled, because then it would also need to re-execute any plugin and preset functions referenced in that config.

为避免这种情况,Babel 希望配置函数的用户告诉它如何在配置文件中管理缓存。

🌐 To avoid this, Babel expects users of config functions to tell it how to manage caching within a config file.

  • api.cache.forever() - Permacache 计算的配置并且永远不会再次调用该函数。
  • api.cache.never() - 不要缓存这个配置,每次都重新执行函数。
  • api.cache.using(() => process.env.NODE_ENV) - 基于 NODE_ENV 的值进行缓存。每当 using 回调返回的值与预期值不同时,整个配置函数会被重新调用,并且会在缓存中添加一个新条目。
  • api.cache.invalidate(() => process.env.NODE_ENV) - 基于 NODE_ENV 的值进行缓存。每当 using 回调返回的值不是预期的那个时,整体的配置函数会被再次调用,并且缓存中的所有条目都会被替换成新的结果。
  • api.cache(true) - 和 api.cache.forever() 一样
  • api.cache(false) - 和 api.cache.never() 一样

因为实际回调结果用于检查缓存条目是否有效,建议:

🌐 Since the actual callback result is used to check if the cache entry is valid, it is recommended that:

  • 回调应该很小并且没有副作用。
  • 回调应该返回尽可能小范围的值。例如,上面使用的 .using(() => process.env.NODE_ENV) 并不理想,因为它会根据检测到的 NODE_ENV 的数量创建不确定数量的缓存条目。做 .using(() => process.env.NODE_ENV === "development") 会更安全,因为这样缓存条目只能是 true 或 false。

api.env(...)​

由于 NODE_ENV 是切换行为的一个相当常见的方式,Babel 也包含了一个专门针对这个用途的 API 函数。这个 API 被用作快速检查 Babel 加载时的 "envName",如果没有设置其他覆盖环境,它会考虑 NODE_ENV。

🌐 Since NODE_ENV is a fairly common way to toggle behavior, Babel also includes an API function meant specifically for that. This API is used as a quick way to check the "envName" that Babel was loaded with, which takes NODE_ENV into account if no other overriding environment is set.

它有几种不同的形式:

🌐 It has a few different forms:

  • api.env("production") 如果 envName === "production" 就返回 true。
  • api.env(["development", "test"]) 如果 ["development", "test"].includes(envName) 就返回 true。
  • api.env() 返回当前的 envName 字符串。
  • api.env(envName => envName.startsWith("test-")) 如果环境以 "test-" 开头,则返回 true。
note

这个函数在内部使用了上面提到的 api.cache 来确保 Babel 知道这个构建依赖于特定的 envName。你不应该把它和 api.cache.forever() 或 api.cache.never() 一起使用。

api.caller(cb)​

这个 API 用来作为访问传递给 Babel 的 caller 数据的方式。由于同一个进程中可能运行着多个 Babel 实例,且每个实例的 caller 值不同,这个 API 被设计成可以像 api.env() 一样自动配置 api.cache。

🌐 This API is used as a way to access the caller data that has been passed to Babel. Since many instances of Babel may be running in the same process with different caller values, this API is designed to automatically configure api.cache, the same way api.env() does.

caller 值可以作为回调函数的第一个参数使用。最好与类似的东西一起使用

🌐 The caller value is available as the first parameter of the callback function. It is best used with something like

JavaScript
function isBabelRegister(caller) {
return !!(caller && caller.name === "@babel/register");
}

module.exports = function(api) {
const isRegister = api.caller(isBabelRegister);

return {
// ...
};
};

根据特定环境切换配置行为。

🌐 to toggle configuration behavior based on a specific environment.

api.assertVersion(range)​

虽然 api.version 通常很有用,但有时直接声明你的版本也挺好的。这个 API 提供了一个简单的方式来实现这一点:

🌐 While api.version can be useful in general, it's sometimes nice to just declare your version. This API exposes a simple way to do that with:

JavaScript
module.exports = function(api) {
api.assertVersion("^7.2");

return {
// ...
};
};

api.addExternalDependency(name: string)​

已添加于:v7.17.0

🌐 Added in: v7.17.0

这个 API 允许插件或预设指明一个外部依赖。@babel/core 不会解析外部依赖,而是由调用者来处理通过 babel.transformSync 方法返回的 .externalDependencies 属性提供的任何依赖。

🌐 This API allows the plugin or preset to indicate an external dependency. @babel/core does not resolve external dependencies, instead it is up to the caller to handle any dependencies made available in the .externalDependencies property returned from the babel.transformSync method.

my-babel-preset.js
module.exports = function(api) {
// Indicate that the preset depends on the .browserslistrc file
api.addExternalDependency(".browserslistrc");

return {
// ...
};
};