@babel/preset-env相關問題


剛接觸bable的同學會犯一個錯誤,認為在使用了Babel后就可以暢快的使用 es2015 了,事實上Babel只能轉換語法(如箭頭函數、let、const、class等),像Promise 、Async、Object.assign、Array.find()等api是依賴瀏覽器實現的,想在不支持的瀏覽器上使用新的API,需要采用Polyfill技術,實現Polyfill有多種方式,方式對比請點我

 

Babel 推薦使用 @babel/preset-env 套件來處理轉譯需求。顧名思義,preset 即“預制套件”,包含了各種可能用到的轉譯工具。

之前的以年份為准的 preset 已經廢棄了,現在統一用這個總包。同時,babel 已經放棄開發 stage-* 包,以后的轉譯組件都只會放進 preset-env 包里。

@babel/preset-env默認會支持stage4的特性轉換(當然是針對@babel/preset-env當前版本發布年份的stage4提案)。

 

一、重要參數

1. target

@babel/preset-env 支持一些參數,用來處理哪些 feature 要轉譯,哪些不要。其中比較重要的是 targets,用來指定目標環境。targets 使用 browserslist 來篩選瀏環境,這樣我們就不需要指定所有瀏覽器版本,而可以使用類似 last 2 versions 這樣的描述。具體怎寫,可以看文檔,這里不再贅述。

如果你想知道自己配置的是否合適,可以在倉庫目錄下執行 npx browserslist,列出所有目標瀏覽器。

Babel 官方建議我們把 targets 的內容保存到 .browserslistrc文件中 或者 package.json 里增加一個browserslist節點,不然除了babel外,其他的工具,例如browserslist、post-css等無法從 babel 配置文件里讀取配置。

2. useBuiltIns

接下來,我們可以配置 useBuiltIns這個屬性決定是否引入 polyfill。它有三個可選值:

false,不引入,或者說,Babel 編譯結果不引入。把引入的位置、引入哪些 polyfill 交給用戶處理。

entry, 開發者在核心入口文件中使用 import '@babel/polyfill' 語句引入,其實並不理想,因為大部分瀏覽器不需要這些。

usage, 即“按需引用”。如果目標瀏覽器(從target中知道目標瀏覽器)不支持需要的 feature,那么就自動引入 polyfill,不然的話就不引用。由於目前的打包工具越發智能,隨着 tree shaking 的完善,這樣可以最低限度引入 polyfill。

3. corejs

core-js 目前最新版本是 3.0.1,關於 v3 和 v2 的對比,大家可以看這篇博文:https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md。這里簡單總結一下,core-js 2 封版於 1.5 年之前,所以里面只有對 1.5 年之前 feature 的 polyfill,最近 1.5 年新增的 feature 都不支持,也就存在因為新功能沒有 polyfill 於是在舊瀏覽器里失敗的風險。

所以我們應當升級到最新版,npm i core-js@3 -D 然后修改 babel 配置

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 5%",
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

此選項僅在與useBuiltIns:usage或useBuiltIns:entry一起使用時有效,並確保@babel/preset env為您的核心js版本注入正確的導入。

默認情況下,corejs只會使用stage2及更高階段的特性:如果要使用stage-1(proposal)的polyfill,有三個不同的選項 :

當使用useBuiltIns:“entry”時,可以直接導入一個建議polyfill:import“core js/propositions/string replace all”。

使用useBuiltIns:"usage"時:“用法”有兩種不同的選擇:

    將shippedprovals選項設置為true。這將使polyfills和proposition轉換成為可能,這些建議已經在瀏覽器中發布了一段時間。 

    使用corejs:{version:3,propositions:true}。這將使核心js支持的每一個提案都能實現多元化。 

備注: TC39 將提案分為以下幾個階段:

 

stage0 strawman
任何討論、想法、改變或者還沒加到提案的特性都在這個階段。只有TC39成員可以提交。

 

stage1 proposal

 

(1)產出一個正式的提案。 (2)發現潛在的問題,例如與其他特性的關系,實現難題。 (3)提案包括詳細的API描述,使用例子,以及關於相關的語義和算法。
stage2 draft

 

(1)提供一個初始的草案規范,與最終標准中包含的特性不會有太大差別。草案之后,原則上只接受增量修改。 (2)開始實驗如何實現,實現形式包括polyfill, 實現引擎(提供草案執行本地支持),或者編譯轉換(例如babel)
stage3 candidate

 

(1)候選階段,獲得具體實現和用戶的反饋。此后,只有在實現和使用過程中出現了重大問題才會修改。 (1)規范文檔必須是完整的,評審人和ECMAScript的編輯要在規范上簽字。 (2)至少要在一個瀏覽器中實現,提供polyfill或者babel插件。
stage4 finished

 

(1)已經准備就緒,該特性會出現在下個版本的ECMAScript規范之中。。 (2)需要通過有2個獨立的實現並通過驗收測試,以獲取使用過程中的重要實踐經驗。

 

有關詳細信息,請務必查看 current TC39 proposals 及其 process document

 

二、@babel/polyfill

@babel/polyfill 是對 core-js 的封裝,引入該庫時,實際上是引用了 core-js 的內容和生成器(regenerator-runtime)。 v7.4 之后,這個倉庫就被廢棄了,希要用戶自己選擇使用哪個兼容庫。

換言之,以前是這么引用的:

import "@babel/polyfill";

現在需要:

import "core-js/stable";
import "regenerator-runtime/runtime";

對於絕大部分情況,使用 @babel/preset-env + useBuiltIns: 'usage' 仍然是最好的選則。

 三、babel體系化教程

這個博文講得非常好,完整並且成體系,建議閱讀

https://www.jiangruitao.com/babel/transform-runtime/

 
 


免責聲明!

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



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