附文:一文讀懂 babel7 的配置文件加載邏輯 blog.csdn.net/weixin_3419…javascript
babel有兩種並行配置文件格式,能夠一塊兒使用,也能夠獨立使用。java
在babel 7.x中,babel有一個「根」目錄的概念,默認爲當前的工做目錄。. 對於項目範圍的配置,babel將自動在這個根目錄中搜索「babel.config.js」。或者,用戶可使用顯式的「config file」值來覆蓋默認的配置文件搜索行爲。node
因爲項目範圍內的配置文件與配置文件的物理位置分離,所以它們很是適合必須普遍應用的配置,甚至容許插件和預設輕鬆應用於節點模塊或符號連接包中的文件,傳統上,這些配置對於在Babel6.x中配置。 這個項目範圍配置的主要缺點是,由於它依賴於工做目錄,因此若是工做目錄不是monorepo根目錄,那麼在monorepo中使用它可能會更痛苦。有關如何在該上下文中使用配置文件的示例,請參閱monorepo文檔。json
經過將「configfile」設置爲false,還能夠禁用項目範圍的配置。api
babel經過從正在編譯的「文件名」開始搜索目錄結構來加載.babelrc(和.babelrc.js/package.json_babel)文件(受如下注意事項限制)。 這可能很強大, 由於它容許您爲包的子部分建立獨立的配置。文件相關配置也在項目範圍的配置值的頂部進行合併,這使得它們對於特定的覆蓋可能有用,儘管也能夠經過「覆蓋」來實現。 一旦找到包含package.json的目錄,搜索將中止,所以相對配置僅適用於單個包。 在編譯的「文件名」必須在「babelrcroots」包中,不然將徹底跳過搜索。緩存
這些注意事項意味着: .babelrc文件僅適用於本身包中的文件 除非您選擇「babelrc root s」,不然將忽略不屬於babel「root」的包中的.babelrc文件。 有關如何配置具備多個包的monorepo的更多討論,請參閱monorepo文檔。 經過將「babelrc」設置爲false,也能夠禁用文件相對配置。安全
來自Babel6.x的用戶可能會遇到這兩個邊緣案例,這在Babel7.x中是新的。這兩個限制是爲了解決Babel6.x中的常見問題而增長的:babel
配置如今將被徹底忽略,由於它跨越包邊界。 另外一種選擇是在每一個使用「extends」做爲 { "extends": "../../.babelrc" }app
不幸的是,這種方法可能有點重複,而且根據Babel的使用方式,可能須要設置「babelrcRoots」。 鑑於此,將.babelrc重命名爲項目範圍的「babel.config.js」可能更爲可取。正如上面的項目範圍部分所提到的,這可能須要顯式設置「config file」,由於若是工做目錄不正確,babel將找不到配置文件。ide
Monorepo結構化存儲庫一般包含許多包,這意味着它們常常遇到文件相關配置和配置文件加載中提到的警告。本節旨在幫助用戶瞭解如何處理Monorepo配置。 對於monorepo設置,要理解的核心是babel將您的工做目錄視爲其邏輯「根」,若是您但願在特定的子包中運行babel工具,而不將babel做爲一個總體應用於repo,則會致使問題。 另外,決定是使用.babelrc文件仍是隻使用中心babel.config.js也很重要。子文件夾特定配置不須要.babelrc文件,就像在babel 6中同樣,所以在babel 7中一般不須要這些文件,而須要babel.config.js。
任何monorepo結構的第一步都應該是在repository根目錄中建立babel.config.js文件。這就創建了babel對存儲庫基本目錄的核心概念。即便您想使用.babelrc文件來配置每一個單獨的包,也必須將其做爲repo級別選項的位置。 您一般能夠將全部repo配置放在根babel.config.js中。使用「overrides」,您能夠輕鬆地指定僅適用於存儲庫的某些子文件夾的配置,這一般比在repo中建立許多.babelrc文件更容易執行。 您可能會遇到的第一個問題是,默認狀況下,babel指望從目錄集中加載babel.config.js文件做爲其「根」,這意味着若是建立babel.config.js,但在單個包中運行babel,例如。
cd packages/some-package; babel src -d dist
在這種狀況下,babel使用的「根」不是monorepo根,它將沒法找到babel.config.js文件。 若是全部的構建腳本都是相對於存儲庫根運行的,那麼事情應該已經開始了,可是若是您是在子包中運行babel編譯過程,那麼您須要告訴babel在哪裏查找配置。有幾種方法能夠作到這一點,但推薦的方法是「向上」的「rootmode」選項,它將使babel從工做目錄向上搜索babel.config.js文件,並將其位置用做「根」值。 測試配置是否被檢測到的一個有用方法是在其中放置一個console.log()調用。由於它是一個JS文件,因此日誌將在babel第一次加載它時執行。 您如何設置此值因項目而異,但如下是幾個示例: CLI babel --root-mode upward src -d lib
@babel/register require("@babel/register")({ rootMode: "upward" });
Webpack module: { rules: [{ loader: "babel-loader", options: { rootMode: "upward", } }] }
jest一般安裝在monorepo的根目錄下,可能不須要配置,可是若是每一個包都安裝了它,那麼不幸的是配置起來可能更復雜。 主要部分是建立一個自定義的jest transformer文件,該文件包裝babel jest的默認行爲,以便設置選項,例如。 module.exports = require("babel-jest").createTransformer({ rootMode: "upward", });
保存到某個地方後,您將經過轉換選項在jest選項中使用該文件代替babel jest: "transform": { "^.+\.jsx?$": "./path/to/wrapper.js" },
所以,全部JS文件都將使用您的babel jest版本處理,並啓用選項。
其餘: 有不少工具,但其核心是,若是工做目錄還不是monorepo根目錄,那麼它們須要啓用rootmode選項。
與babel.config.js文件必須位於「根」中的方式相似,默認狀況下.babelrc文件必須位於根包中。這意味着,與工做目錄影響babel.config.js加載的方式相同,它也影響.babelrc加載。 假設您已經像上面討論的那樣正確加載了babel.config.js文件,babel將只處理根包中的.babelrc文件(而不是子包),例如package.json babel.config.js packages/ mod/ package.json .babelrc index.js
編譯packages/mod/index.js文件將不會加載packages/mod/.babelrc,由於該.babelrc位於子包中,而不是根包。 要啓用該.babelrc的處理,您須要使用babel.config.js文件中的「babelrcroots」選項。babelrcRoots: [ ".", "packages/*", ],
所以,babel將考慮容許加載.babelrc文件的全部包/*包,以及原始repo根。
單個配置文件自己的格式分爲JS文件和JSON5文件。
任何不是.js文件的文件都將被解析爲json5,而且應該包含一個與babel接受的選項格式相匹配的對象。
任何.js文件都將require()ed,而且應該導出配置對象,或者在調用時返回配置對象的函數。主要的好處是,用戶可使用JS邏輯構建配置結構,這可能使配置邏輯更容易共享。.js文件能夠用做項目範圍的配置,也能夠經過.babelrc.js文件進行文件相關配置。 返回配置的函數有一些特殊的功能,由於它們能夠訪問babel自己公開的API。有關詳細信息,請參閱配置函數API。
JS配置文件可能會導出一個將傳遞配置函數API的函數: module.exports = function(api) { return {}; }
api對象公開了babel自己從其索引模塊公開的全部內容,以及配置文件特定的api:
api.version Type: string 正在加載配置文件的babel版本的版本字符串。
api.cache JS配置很是好,由於它們能夠即時計算配置,但缺點是它會使緩存變得更困難。Babel但願避免每次編譯文件時都從新執行config函數,由於這樣它還須要從新執行該配置中引用的任何插件和預設函數。 爲了不這種狀況,babel但願配置函數的用戶告訴它如何管理配置文件中的緩存。
api.env(…) 因爲node_env是一種很是常見的切換行爲的方法,babel還包含一個專門用於此目的的API函數。此API用做快速檢查babel加載時使用的「envname」的方法,若是沒有設置其餘覆蓋環境,則會考慮節點env。 它有幾種不一樣的形式: 若是envname==「production」,則api.env(「production」)返回true。 若是[「development」,「test」]包含(envname),則env([「development」,「test」])返回true。 api.env()返回當前envname字符串。 若是env以「test-」開頭,則api.env(envname=>envname.starts with(「test-」))返回true。 這個函數在內部使用下面提到的api.cache來確保babel知道這個構建依賴於一個特定的envname。
api.caller(cb) 此API用做訪問已傳遞給babel的調用方數據的方法。因爲babel的許多實例可能以不一樣的調用方值在同一進程中運行,所以該API被設計爲自動配置api.cache,與api.env()的方式相同。 調用者值可用做回調函數的第一個參數。最好和相似的東西一塊兒使用 function isBabelRegister(caller) { return !!(caller && caller.name === "@babel/register"); }
module.exports = function(api) { const isRegister = api.caller(isBabelRegister);
return { // ... }; }
根據特定環境切換配置行爲。
api.assertVersion(range) 雖然api.version在通常狀況下頗有用,但有時只聲明您的版本是很好的。此API公開了一種簡單的方法來實現這一點: module.exports = function(api) { api.assertVersion("^7.2");
return { // ... }; };