# 配置文件

# 配置文件类型 (opens new window)

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

历史:

Version Changes
v7.21.0 支持.babelrc.ctsbabel.config.cts(实验性)
v7.8.0 支持.babelrc.mjsbabel.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"钥匙。

# 项目范围的配置 (opens new window)

Babel 7.x 中的新功能,Babel 有一个“根” 目录的概念,默认为当前工作目录。对于项目范围的配置,Babel 将自动在此根目录中搜索babel.config.json文件或使用支持的扩展名的等效文件。 (opens new window) 或者,用户可以使用显式的 “configFile” 值来覆盖默认的配置文件搜索行为。

由于项目范围的配置文件与配置文件的物理位置是分开的,因此它们非常适合必须广泛应用的配置,甚至允许插件和预设轻松应用于符号链接包中或符号链接包中的文件,这在传统上是非常痛苦node_modules的在 Babel 6.x 中配置。

这个项目范围的配置的主要缺点是,因为它依赖于工作目录,如果工作目录不是 monorepo root,那么在 monorepos 中使用它会更痛苦。有关如何在该上下文中使用配置文件的示例,请参阅monorepo文档。 (opens new window)

也可以通过将“configFile” (opens new window) 设置为 来禁用项目范围的配置false

# 文件相关配置 (opens new window)

Babel通过从正在编译的“文件名” (opens new window) 开始搜索目录结构来加载文件或使用支持的扩展的 (opens new window) .babelrc.json等效文件(受以下警告限制)。这可能很强大,因为它允许您为包的子部分创建独立的配置。文件相关的配置也被合并 (opens new window) 到项目范围的配置值之上,使它们可能对特定的覆盖有用,尽管这也可以通过“覆盖” (opens new window) 来完成。

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

  • package.json一旦找到包含 a 的目录,搜索将停止,因此相对配置仅适用于单个包。
  • 正在编译的“文件名” 必须在 “babelrcRoots” 包内,否则将完全跳过搜索。

这些警告意味着:

  • .babelrc.jsonfiles仅适用于它们自己的包中的文件
  • .babelrc.json包中不是 Babel 的“root”的文件将被忽略,除非你选择使用“babelrcRoots” (opens new window)

有关如何配置具有许多包的 monorepos 的更多讨论,请参阅monorepo文档。 (opens new window) 也可以通过将“babelrc” 设置为false.

# 6.x 与 7.x加载 .babelrc

来自 Babel 6.x 的用户可能会在这两个 Babel 7.x 中新增的边缘情况下被绊倒。添加这两个限制是为了解决 Babel 6.x 中的常见脚枪问题:

  • .babelrc应用于node_modules依赖项的文件,通常是意外的。
  • .babelrc当人们期望文件表现得像正常的依赖项时,文件无法应用于符号链接。node_modules
  • .babelrc依赖项中的文件node_modules会被检测到,即使它们里面的插件和预设通常没有安装,甚至可能在编译文件的 Babel 版本中无效。

这些情况主要会给具有 monorepo 结构的用户带来问题,因为如果你有

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

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

一种替代方法是在每个使用“扩展” (opens new window).babelrc子包中创建一个

.babelrc.json

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

不幸的是,这种方法可能有点重复,并且根据 Babel 的使用方式,可能需要设置"babelrcRoots" (opens new window)

.babelrc鉴于此,将 重命名为 项目范围的 "babel.config.json" 可能更可取。如上面项目范围部分所述,这可能需要显式设置“configFile”, (opens new window) 因为如果工作目录不正确,Babel 将找不到配置文件。

# 支持的文件扩展名 (opens new window)

Babel 可以使用 Node.js 本机支持的任何文件扩展名进行配置,如配置文件类型 部分所述:

  • babel.config.json并被.babelrc.json解析为 JSON5,​​并且应该包含一个与 Babel 接受的选项 (opens new window) 格式匹配的对象。从那以后他们就得到了支持v7.7.0

我们建议尽可能使用此文件类型:如果您有复杂的配置,这些配置是有条件的或在构建时以其他方式计算的,则 JS 配置文件很方便。然而,缺点是 JS 配置的静态分析性较差,因此对可缓存性、linting、IDE 自动完成等有负面影响。由于 和babel.config.json.babelrc.json静态 JSON 文件,它允许使用 Babel 的其他工具(如捆绑器)缓存结果Babel safely,这可能是一个巨大的构建性能胜利。

  • babel.config.cjs.babelrc.cjs允许您将配置定义为 CommonJS,使用module.exports. 从那以后他们就得到了支持v7.7.0

  • babel.config.mjs.babelrc.mjs使用原生 ECMAScript 模块。它们受 Node.js 13.2+(或通过--experimental-modules标志的旧版本)支持。请记住,原生 ECMAScript 模块是异步的(这就是为什么import()总是返回一个承诺!):因此,.mjs同步调用 Babel 时配置文件将抛出异常。从那以后他们就得到了支持v7.8.0

  • babel.config.js并且当您的文件包含该选项时.babelrc.js表现得像等价物,否则它们与文件完全相同。.mjs``package.json"type": "module" (opens new window) .cjs

  • babel.config.cts.babelrc.cts允许您将配置定义为 Typescript + CommonJS。您必须@babel/preset-typescript使用 来安装或运行 Babel ts-node

🚧 此功能是实验性的。目前还不能使用babel.config.tsbabel.config.mts文件,等待 Node.js ESM 加载程序 API 的稳定。

JavaScript 配置文件既可以导出一个对象,也可以导出一个在调用时将返回生成的配置的函数。返回函数的配置被赋予了一些特殊的权力,因为它们可以访问 Babel 本身公开的 API。有关详细信息,请参阅配置函数 API 。 (opens new window)

出于兼容性原因,.babelrc.babelrc.json.

# 单体仓库

Monorepo 结构化存储库通常包含许多包,这意味着它们经常遇到文件相关配置 和一般配置文件加载中提到的警告。本节旨在帮助用户了解如何进行 monorepo 配置。

对于 monorepo 设置,要理解的核心是 Babel 将你的工作目录视为它的逻辑“根” (opens new window) ,如果你想在特定子包中运行 Babel 工具而不将 Babel 作为一个整体应用于 repo,这会导致问题。

另外,决定是使用.babelrc.json (opens new window) 文件还是仅使用中央babel.config.json (opens new window) . .babelrc.json 子文件夹特定的配置不需要文件,就像在 Babel 6 中那样,因此在 Babel 7 中通常不需要它们,有利于babel.config.json (opens new window) .

#文件 (opens new window) babel.config.json

任何 monorepo 结构的第一步应该是babel.config.json (opens new window) 在存储库根目录中创建一个文件。这建立了 Babel 的核心概念,即你的存储库的基本目录。即使你想使用.babelrc.json (opens new window) 文件来配置每个单独的包,重要的是要有一个存储库级别选项的地方。

您通常可以将所有 repo 配置放在 root 中babel.config.json (opens new window) 。使用"overrides" (opens new window) ,您可以轻松指定仅适用于存储库某些子文件夹的配置,这通常比.babelrc.json在存储库中创建许多文件更容易遵循。

您可能会遇到的第一个问题是,默认情况下,Babel 期望从设置为“root” (opens new window) babel.config.json 的目录加载文件,这意味着如果您创建一个,但在单个包中运行 Babel,例如babel.config.json (opens new window)

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

Babel 在该上下文中使用的“根” (opens new window) 不是您的 monorepo 根,它将无法找到该babel.config.json (opens new window) 文件。

如果你所有的构建脚本都相对于你的存储库根目录运行,那么事情应该已经可以正常工作了,但是如果你从一个子包中运行你的 Babel 编译过程,你需要告诉 Babel 在哪里寻找配置。有几种方法可以做到这一点,但推荐的方法是带有 的“rootMode” (opens new window) "upward"选项,这将使 Babel 从工作目录向上搜索您的babel.config.json (opens new window) 文件,并将其位置用作“root” (opens new window) 值。

console.log()测试你的配置是否被检测到的一个有用方法是,如果它是一个 JavaScript 文件,则在其中放置一个调用babel.config.json (opens new window) :日志将在 Babel 第一次加载它时执行。

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

# 命令行界面
babel --root-mode upward src -d lib

# @巴贝尔/注册 (opens new window)

JavaScript

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

# 网页包

webpack.config.js

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

#

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

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

包装器.js

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

并将其保存在某处,然后您可以通过转换选项 (opens new window) babel-jest在 Jest 选项中使用该文件:

是.config.js

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

因此所有 JS 文件都将使用您启用该选项的版本进行处理babel-jest

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

# 其他

有很多工具,但其核心是rootMode如果工作目录还不是 monorepo 根目录,则它们需要启用该选项。

# 分包文件 (opens new window) .babelrc.json

babel.config.json 与要求文件位于“root” (opens new window) 中的方式类似, 默认情况下,.babelrc.json (opens new window) 文件必须位于根包中。这意味着,工作目录影响加载的方式相同babel.config.json (opens new window) ,它也会影响.babelrc.json (opens new window) 加载。

假设你已经像babel.config.json (opens new window) 上面讨论的那样正确加载了你的文件,Babel 将只处理.babelrc.json (opens new window) 根包内的文件(而不是子包),例如

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

编译packages/mod/index.js文件不会加载,packages/mod/.babelrc.json因为它.babelrc.json (opens new window) 在子包中,而不是根包中。

要启用对其的处理.babelrc.json (opens new window) ,您需要使用文件内部的“babelrcRoots” (opens new window) babel.config.json 选项来执行

JavaScript

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

这样 Babel 就会认为所有的packages/*包都允许加载.babelrc.json (opens new window) 文件,连同原始的 repo root。

# 配置函数API (opens new window)

JS 配置文件可能会导出一个将传递给配置函数 API 的函数:

JavaScript

module.exports = function(api) {
  return {};
};

api对象公开了 Babel 本身从其索引模块公开的所有内容,以及特定于配置文件的 API:

# api.version (opens new window)

类型:string

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

# api.cache (opens new window)

JS 配置很棒,因为它们可以动态计算配置,但缺点是它使缓存更难。Babel 希望避免每次编译文件时都重新执行配置函数,因为那样它还需要重新执行该配置中引用的任何插件和预设函数。

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

  • 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()

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

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

# api.env(...) (opens new window)

由于NODE_ENV这是一种相当常见的切换行为的方式,Babel 还包含一个专门用于此目的的 API 函数。此 API 用作检查 Babel 加载的“envName” (opens new window) NODE_ENV的快速方法,如果没有设置其他覆盖环境,它会考虑在内。

它有几种不同的形式:

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

注意:这个函数在内部使用api.cache (opens new window) 上面提到的来确保 Babel 知道这个构建依赖于一个特定的envName. 您不应将它与api.cache.forever()或一起使用api.cache.never()

# api.caller(cb) (opens new window)

caller此 API 用作访问已传递给 Babel 的数据的一种方式。由于 Babel 的许多实例可能在同一个进程中运行,但caller值不同,因此该 API 旨在自动配置api.cache,同样的方式api.env()

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

JavaScript

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

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

  return {
    // ...
  };
};

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

# api.assertVersion(range) (opens new window)

虽然api.version通常很有用,但有时只声明您的版本会很好。这个 API 公开了一种简单的方法来做到这一点:

JavaScript

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

  return {
    // ...
  };
};

Last Updated: 6/14/2023, 8:56:23 AM