babel | 理解babel配置文件—babel.config.js 和 babelrc

之前遇到过一个 babel 转换的问题,在下面这个 monorepo 的目录结构中

.
├── common
│   └── utils.js
├── package.json
└── packages
    └── modulea
        ├── .babelrc
        ├── index.js
        ├── package.json
        └── webpack.config.js

3 directories, 6 files

modulea 引用了外层 common/utils.js,结果在打包时发现common/utils.js 的代码并没有被翻译,但是 modulea 目录内的代码却能正常转换,觉得很奇怪,直到我将 babel 的配置文件由 .babelrc 改成了 babel.config.js 才能正常工作。于是就深究了一下两个配置文件的区别,觉得有点东西理解起来有点绕,于是写下这篇博客记录一下。

babel 7.x 以上开始支持两种类型的配置文件, 分别是.babelrc 和 babel.config.js ,在官方的描述里:

  • babel.config.js 当前项目维度 (Project Wide)的配置文件,相当于一份全局配置,如果 babel 决定应用这个配置文件,则一定会应用到所有文件的转换。
  • .babelrc 相对文件(File Relative)的配置文件, babel 决定一个 js 文件应用哪些配置文件时,会执行如下策略: 如果要转换的这个 js 文件在当前项目内,则会先递归向上搜索最近的一个 .babelrc 文件(直到遇到package.json目录),将其与全局配置合并。如果这个 js 文件不在当前项目内,则只应用全局配置,忽略与这个文件相关的 .babelrc 。

这两个我更愿意将其称为全局配置 (babel.config.js) 和局部配置 (.babelrc) 便于理解一些。

由此便引入了一个非常关键的对 ** 当前项目 ** 的定义问题。

这个定义在官方文档就有说明

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.

大白话就是: 当前所在目录即为*当前项目*根目录,babel 会读取当前所在目录的 babel.config.js 作为全局配置。

下面我们分为几种 case 分别看一下 babel 的应用路径.

Case 1  所有代码都在一个单一工程中

这种情况下 babel.config.js 和 .babelrc 作用几乎一样,唯一不同是 babelrc 可以针对子目录分别配置。

.
├── .babelrc
├── babel.config.js
├── package.json
└── src
    ├── index.js
    └── subdir
        ├── .babelrc
        └── utils.js

2 directories, 6 files

这里, 我们在顶层目录运行 babel src/**/*.js --out-dir dist 。此时会读取当前目录的 babel.config.js 作为全局配置,根据前文所述规则应用的配置如

  • src/index.js 会应用 babel.config.js + .babelrc
  • src/subdir/utils.js 会应用 babel.config.js + src/subdir/.babelrc

如果我们在 src 目录执行 babel **/*.js --outdir ,此时则不会应用 babel.config.js 的规则,但会应用 src 外层 .babelrc 的配置文件。

此时:

  • index.js 会应用 ../.babelrc
  • subdir/index.js 会应用 subdir/.babelrc

这里貌似有点不对劲, index.js 为什么会应用外层 .babelrc , 这个配置文件明明在当前项目"外"。

这里再回顾一下之前说的。

babel 决定一个 js 文件应用哪些配置文件时,会执行如下策略: 如果这个 js 文件在当前项目内,则会先递归向上搜索最近的一个 .babelrc 文件(直到遇到package.json目录),将其与全局配置合并。如果这个 js 文件不在当前项目内,则只应用全局配置,并忽略与这个文件相关的 .babelrc 。

babel决定是否执行向上搜索 .babelrc 这个策略时依据的是当前 js 文件的位置,而不是 .babelrc 的位置。此时的 index.js 在项目范围内,所以会执行向上搜索 .babelrc 的策略。

Case 2  多工程下的项目配置问题

对于 monorepo 项目,全局配置文件就有用的多了。首先看我开头遇到的问题

.
├── common
│   └── utils.js
├── package.json
└── packages
    └── modulea
        ├── .babelrc
        ├── index.js
        ├── package.json
        └── webpack.config.js

3 directories, 6 files

这里我在 packages/modulea 目录里执行打包命令时, .babelrc 只会应用 packages/modulea 里的文件,对于 common 目录下的文件则无法执行转换。即便我们在 common 目录中添加一个 .babelrc 也无济于事,因为 common 里的代码在当前的项目范围外面,只会应用全局配置。所以这种场景就非常适合使用 babel.config.js 。

.
├── common
│   └── utils.js
├── package.json
└── packages
    └── modulea
        ├── babel.config.js <--- 
        ├── index.js
        ├── package.json
        └── webpack.config.js

3 directories, 6 files

改成 babel.config.js 之后 common 目录就能正确进行转换了。

为了清晰记忆上面的规则我来稍微总结一下:

babel 会在当前执行目录搜索 babel.config.js, 若有则读取并作为全局配置,若无则全局配置为空。然后在转换一个具体的js文件时会去判断,如果这个文件在当前执行目录外面,则只应用全局配置。如果这个文件在当前执行路径内,则会去基于这个文件向上搜索最近的一个 .babelrc ,将其与全局配置合并作为转换这个文件的配置。

源自:理解 babel.config.js 和 babelrc - 知乎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值