babel升級7.x的心得


本文參考文獻(https://zhuanlan.zhihu.com/p/43249121)(https://zhuanlan.zhihu.com/p/97884144

Babel 7.x

最近 babel 發布了 7.0。因為上面部分都是針對 6.x 編寫的,所以我們關注一下 7.0 帶來的變化(核心機制方面沒有變化,插件,preset,解析轉譯生成這些都沒有變化)

我只挑選一些和開發者關系比較大的列在這里,省略的多數是針對某一個 plugin 的改動。完整的列表可以參考官網

preset 的變更:淘汰 es201x,刪除 stage-x,強推 env (重點)

淘汰 es201x 的目的是把選擇環境的工作交給 env 自動進行,而不需要開發者投入精力。凡是使用 es201x 的開發者,都應當使用 env 進行替換。但這里的淘汰 (原文 deprecated) 並不是刪除,只是不推薦使用了,不好說 babel 8 就真的刪了。

與之相比,stage-x 就沒那么好運了,它們直接被刪了。這是因為 babel 團隊認為為這些 “不穩定的草案” 花費精力去更新 preset 相當浪費。stage-x 雖然刪除了,但它包含的插件並沒有刪除(只是被更名了,可以看下面一節),我們依然可以顯式地聲明這些插件來獲得等價的效果。完整列表

為了減少開發者替換配置文件的機械工作,babel 開發了一款 babel-upgrade 的工具,它會檢測 babel 配置中的 stage-x 並且替換成對應的 plugins。除此之外它還有其他功能,我們一會兒再詳細看。(總之目的就是讓你更加平滑地遷移到 babel 7)

npm package 名稱的變化 (重點)

這是 babel 7 的一個重大變化,把所有 babel-* 重命名為 @babel/*,例如:

  1. babel-cli 變成了 @babel/cli
  2. babel-preset-env 變成了 @babel/preset-env。進一步,還可以省略 preset 而簡寫為 @babel/env或者@babel/preset-env
  3. babel-plugin-transform-arrow-functions 變成了 @babel/plugin-transform-arrow-functions。和 preset 一樣,plugin 也可以省略,於是簡寫為 @babel/transform-arrow-functions

這個變化不單單應用於 package.json 的依賴中,包括 .babelrc 的配置 (pluginspresets) 也要這么寫,為了保持一致。例如

{
  "presets": [
-   "env"
+   "@babel/preset-env"
  ]
}

順帶提一句,上面提過的 babel 解析語法的內核 babylon 現在重命名為 @babel/parser,看起來是被收編了。

上文提過的 stage-x 被刪除了,它包含的插件雖然保留,但也被重命名了。babel 團隊希望更明顯地區分已經位於規范中的插件 (如 es2015 的 babel-plugin-transform-arrow-functions) 和僅僅位於草案中的插件 (如 stage-0 的 @babel/plugin-proposal-function-bind)。方式就是在名字中增加 proposal,所有包含在 stage-x 的轉譯插件都使用了這個前綴,語法插件不在其列。

最后,如果插件名稱中包含了規范名稱 (-es2015--es3- 之類的),一律刪除。例如 babel-plugin-transform-es2015-classes 變成了 @babel/plugin-transform-classes。(這個插件我自己沒有單獨用過,慚愧)

不再支持低版本 node

babel 7.0 開始不再支持 nodejs 0.10, 0.12, 4, 5 這四個版本,相當於要求 nodejs >= 6 (當前 nodejs LTS 是 8,要求也不算太過分吧)。

這里的不再支持,指的是在這些低版本 node 環境中不能使用 babel 轉譯代碼,但 babel 轉譯后的代碼依然能在這些環境上運行,這點不要混淆。

only 和 ignore 匹配規則的變化

在 babel 6 時,ignore 選項如果包含 *.foo.js,實際上的含義 (轉化為 glob) 是 ./**/*.foo.js,也就是當前目錄 包括子目錄 的所有 foo.js 結尾的文件。這可能和開發者常規的認識有悖。

於是在 babel 7,相同的表達式 *.foo.js 只作用於當前目錄,不作用於子目錄。如果依然想作用於子目錄的,就要按照 glob 的完整規范書寫為 ./**/*.foo.js 才可以。only 也是相同。

這個規則變化只作用於通配符,不作用於路徑。所以 node_modules 依然包含所有它的子目錄,而不單單只有一層。(否則全世界開發者都要爆炸)

@babel/node 從 @babel/cli 中獨立了

和 babel 6 不同,如果要使用 @babel/node,就必須單獨安裝,並添加到依賴中。

babel-upgrade

在提到刪除 stage-x 時候提過這個工具,它的目的是幫助用戶自動化地從 babel 6 升級到 7。

這款升級工具的功能包括:(這里並不列出完整列表,只列出比較重要和常用的內容)

  1. package.json
  2. 把依賴(和開發依賴)中所有的 babel-* 替換為 @babel/*
  3. 把這些 @babel/* 依賴的版本更新為最新版 (例如 ^7.0.0)
  4. 如果 scripts 中有使用 babel-node,自動添加 @babel/node 為開發依賴
  5. 如果有 babel 配置項,檢查其中的 plugins 和 presets,把短名 (env) 替換為完整的名字 (@babel/preset-env)
  6. .babelrc
  7. 檢查其中的 plugins 和 presets,把短名 (env) 替換為完整的名字 (@babel/preset-env)
  8. 檢查是否包含 preset-stage-x,如有替換為對應的插件並添加到 plugins

使用方式如下:

# 不安裝到本地而是直接運行命令,npm 的新功能 npx babel-upgrade --write # 或者常規方式 npm i babel-upgrade -g babel-upgrade --write

babel-upgrade 工具本身也還在開發中,還列出了許多 TODO 沒有完成,因此之后的功能可能會更加豐富,例如上面提過的 ignore 的通配符轉化等等。

 

遇到的問題

  1. Error: Cannot find module 'babel-register'
    代碼入口中使用babel的插件未替換
    require('register')({
        presets: ['env']
    });
    module.exports = require('./app.js');
    ====替換為=============================================================
    require('@babel/register')({
        presets: ['@babel/env']
    });
    module.exports = require('./app.js');
  2. ReferenceError: regeneratorRuntime is not defined
    require('@babel/register')({
        presets: ['@babel/env','@babel/react']});
    //添加以下兩個引用
    require( "core-js/stable");
    require("regenerator-runtime/runtime");
    module.exports = require('./app.js');

  3. Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>' 不能混用import和exports語法
    //.babelrc 添加一個plugin插件
      "plugins": [
        "@babel/plugin-transform-modules-commonjs"
      ]

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM