研究了 babel.config.js 和 babelrc,理解了為什么ES6代碼沒(méi)被轉(zhuǎn)化
點(diǎn)擊上方 前端陽(yáng)光,關(guān)注公眾號(hào)
回復(fù)加群,加入技術(shù)交流群交流群

前言
之前遇到過(guò)一個(gè) babel 轉(zhuǎn)換的問(wèn)題,在下面這個(gè) monorepo 的目錄結(jié)構(gòu)中
.
├── common
│ └── utils.js
├── package.json
└── packages
└── modulea
├── .babelrc
├── index.js
├── package.json
└── webpack.config.js
3 directories, 6 files
modulea 引用了外層 common/utils.js,結(jié)果在打包時(shí)發(fā)現(xiàn)common/utils.js 的代碼并沒(méi)有被翻譯,但是 modulea 目錄內(nèi)的代碼卻能正常轉(zhuǎn)換,覺得很奇怪,直到我將 babel 的配置文件由 .babelrc 改成了 babel.config.js 才能正常工作。于是就深究了一下兩個(gè)配置文件的區(qū)別,覺得有點(diǎn)東西理解起來(lái)有點(diǎn)繞,于是寫下這篇博客記錄一下。
babel 7.x 以上開始支持兩種類型的配置文件, 分別是.babelrc 和 babel.config.js ,在官方的描述里:
babel.config.js 當(dāng)前項(xiàng)目維度 (Project Wide)的配置文件,相當(dāng)于一份全局配置,如果 babel 決定應(yīng)用這個(gè)配置文件,則一定會(huì)應(yīng)用到所有文件的轉(zhuǎn)換。
.babelrc 相對(duì)文件(File Relative)的配置文件, babel 決定一個(gè) js 文件應(yīng)用哪些配置文件時(shí),會(huì)執(zhí)行如下策略: 如果要轉(zhuǎn)換的這個(gè) js 文件在當(dāng)前項(xiàng)目?jī)?nèi),則會(huì)先遞歸向上搜索最近的一個(gè) .babelrc 文件(直到遇到package.json目錄),將其與全局配置合并。如果這個(gè) js 文件不在當(dāng)前項(xiàng)目?jī)?nèi),則只應(yīng)用全局配置,忽略與這個(gè)文件相關(guān)的 .babelrc 。這兩個(gè)我更愿意將其稱為全局配置 (babel.config.js) 和局部配置 (.babelrc) 便于理解一些。
由此便引入了一個(gè)非常關(guān)鍵的對(duì) 當(dāng)前項(xiàng)目 的定義問(wèn)題。
這個(gè)定義在官方文檔就有說(shuō)明
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.
大白話就是: 當(dāng)前所在目錄即為*當(dāng)前項(xiàng)目*根目錄,babel 會(huì)讀取當(dāng)前所在目錄的 babel.config.js 作為全局配置。
下面我們分為幾種 case 分別看一下 babel 的應(yīng)用路徑.
Case 1 所有代碼都在一個(gè)單一工程中
這種情況下 babel.config.js 和 .babelrc 作用幾乎一樣,唯一不同是 babelrc 可以針對(duì)子目錄分別配置.
.
├── .babelrc
├── babel.config.js
├── package.json
└── src
├── index.js
└── subdir
├── .babelrc
└── utils.js
2 directories, 6 files
這里, 我們?cè)陧攲幽夸涍\(yùn)行 babel src/**/*.js --out-dir dist 。此時(shí)會(huì)讀取當(dāng)前目錄的 babel.config.js 作為全局配置,根據(jù)前文所述規(guī)則應(yīng)用的配置如
src/index.js 會(huì)應(yīng)用 babel.config.js + .babelrc。 src/subdir/utils.js 會(huì)應(yīng)用 babel.config.js + src/subdir/.babelrc
如果我們?cè)?src 目錄執(zhí)行 babel **/*.js --outdir ,此時(shí)則不會(huì)應(yīng)用 babel.config.js 的規(guī)則,但會(huì)應(yīng)用 src 外層 .babelrc 的配置文件。
此時(shí):
index.js 會(huì)應(yīng)用 ../.babelrc subdir/index.js 會(huì)應(yīng)用 subdir/.babelrc
這里貌似有點(diǎn)不對(duì)勁, index.js 為什么會(huì)應(yīng)用外層 .babelrc , 這個(gè)配置文件明明在當(dāng)前項(xiàng)目"外"。
這里再回顧一下之前說(shuō)的。
babel 決定一個(gè) js 文件應(yīng)用哪些配置文件時(shí),會(huì)執(zhí)行如下策略: 如果這個(gè) js 文件在當(dāng)前項(xiàng)目?jī)?nèi),則會(huì)先遞歸向上搜索最近的一個(gè) .babelrc 文件(直到遇到package.json目錄),將其與全局配置合并。如果這個(gè) js 文件不在當(dāng)前項(xiàng)目?jī)?nèi),則只應(yīng)用全局配置,并忽略與這個(gè)文件相關(guān)的 .babelrc 。
babel決定是否執(zhí)行向上搜索 .babelrc 這個(gè)策略時(shí)依據(jù)的是當(dāng)前 js 文件的位置,而不是 .babelrc 的位置。此時(shí)的 index.js 在項(xiàng)目范圍內(nèi),所以會(huì)執(zhí)行向上搜索 .babelrc 的策略。
Case 2 多工程下的項(xiàng)目配置問(wèn)題
對(duì)于 monorepo 項(xiàng)目,全局配置文件就有用的多了。首先看我開頭遇到的問(wèn)題
.
├── common
│ └── utils.js
├── package.json
└── packages
└── modulea
├── .babelrc
├── index.js
├── package.json
└── webpack.config.js
3 directories, 6 files
這里我在 packages/modulea 目錄里執(zhí)行打包命令時(shí), .babelrc 只會(huì)應(yīng)用 packages/modulea 里的文件,對(duì)于 common 目錄下的文件則無(wú)法執(zhí)行轉(zhuǎn)換。即便我們?cè)?common 目錄中添加一個(gè) .babelrc 也無(wú)濟(jì)于事,因?yàn)?common 里的代碼在當(dāng)前的項(xiàng)目范圍外面,只會(huì)應(yīng)用全局配置。所以這種場(chǎng)景就非常適合使用 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 目錄就能正確進(jìn)行轉(zhuǎn)換了。
為了清晰記憶上面的規(guī)則我來(lái)稍微總結(jié)一下:
babel 會(huì)在當(dāng)前執(zhí)行目錄搜索 babel.config.js, 若有則讀取并作為全局配置,若無(wú)則全局配置為空。然后在轉(zhuǎn)換一個(gè)具體的js文件時(shí)會(huì)去判斷,如果這個(gè)文件在當(dāng)前執(zhí)行目錄外面,則只應(yīng)用全局配置。如果這個(gè)文件在當(dāng)前執(zhí)行路徑內(nèi),則會(huì)去基于這個(gè)文件向上搜索最近的一個(gè) .babelrc ,將其與全局配置合并作為轉(zhuǎn)換這個(gè)文件的配置。

往期推薦
我組建了技術(shù)交流群,里面有很多 大佬,歡迎進(jìn)來(lái)交流、學(xué)習(xí)、共建。回復(fù) 加群 即可。后臺(tái)回復(fù)「電子書」即可免費(fèi)獲取 27本 精選的前端電子書!回復(fù)內(nèi)推,可內(nèi)推各廠內(nèi)推碼
“分享、點(diǎn)贊、在看” 支持一波??
