[譯] Babel 7.0 帶來的很酷的事情

來看這👋!我是 HenryBabel 的維護者之一。html

編輯:我已經離開了 Behance 並製做了 Patreon,嘗試 全職投入到開源工做上,請你或你的公司考慮捐獻。前端

Babel 簡介

有些人可能把 Babel 看做是一個讓你寫 ES6 代碼的工具。更準確的說,Babel 是把 ES6 代碼轉換爲 ES5 代碼的 JavaScript 編譯器。當它的名字是 6to5 時,這很適合,可是我認爲 Babel 已經變得不僅是這些了。react

如今讓咱們聊一些背景。這一點很是必要,由於不像運行在服務器上的其餘語言(甚至是 Node.js),你能運行的的 JavaScript 版本取決於你的瀏覽器的特定版本。若是你使用最新的瀏覽器,而你的用戶(你想留住的)仍然使用 IE,是沒有關係的。可是,舉個例子,若是你想寫 class A {} ,那麼你就很不幸了 - 你的一些用戶將會獲得一個 SyntaxError 和一個空白頁面。android

因此這就是建立 Babel 的緣由。它容許你寫你想寫的 JavaScript 版本,你知道它會在你支持的全部(更老)的瀏覽器上正確的運行。ios

可是,它並不中止於 「ES6」(有些人喜歡說 ES2015)。Babel 已經確實擴展了他的最初目標,即只編譯 ES6 代碼。如今,它可以編譯任意一個你想要的 ES20XX 版本(JavaScript 最新版本)到 ES5.git

正在進行的進程

關於這個項目的一個有趣的事情是,只要 JavaScript 語法被加進去,Babel 就須要實現一個轉換器去轉化它。程序員

可是你可能會想,爲何咱們要給已經支持該語法的瀏覽器發送一個編譯過的版本(更大的代碼體積)?咱們怎麼知道每一個瀏覽器支持什麼語法?es6

好了,咱們製做了一個讓你可以指定你支持哪一個瀏覽器的工具 babel-preset-en,來幫助解決這個問題。它將會自動地只轉換那些瀏覽器原生不支持的東西。github

除此以外,Babel(由於它在社區的使用)可以影響 JavaScript 語言自身的將來。鑑於它是用於轉換 JS 代碼的工具,它也能夠用於實現提交給 TC39 的任何提案(Ecma Technical Committee 39,一個使 JavaScript 做爲標準向前發展的組織)。web

一個 「提案」 進入到語言中會經歷從 Stage 0 到 Stage 4 的一個完整流程。Babel,做爲一個工具,在正確的地方測試新的想法而且讓開發者在他們的應用中使用它,以便他們能夠向委員會提供反饋。

出於如下緣由,這一點很是重要:委員會想確信他們作出的更改是社區想要的(一致,直觀,有效)。在瀏覽器裏實現一個不明的想法是緩慢的(瀏覽器中的 C++ 對比 Babel 中的 JavaScript),昂貴的,而且要求用戶在瀏覽器中使用一個標誌,而不是更改他們的 Babel 配置文件。

由於 Babel 已經很是普及了,這是有一個好的機會使真正的用途出現。這將使提案比那個沒有廣大社區開發者反饋的實現更好。

並且他不僅是在產品中有用。咱們的在線 REPL 對人們學習 JavaScript 有幫助,而且容許他們測試東西。

我認爲 Babel 是一個可以讓程序員們瞭解 JavaScript 如何工做的很是好的工具。經過給這個項目作貢獻,他們將會學習不少其餘的概念,例如 AST,編譯器,語言規範等等。

咱們真的對這個項目的將來很興奮,而且火燒眉毛的要知道這個團隊可以走到哪裏。請加入並幫助咱們!

個人故事

這裏有一些我但願天天都工做在這個項目上的緣由,特別是做爲一個維護者。大多數當前的維護者,包括我本身,並非建立這個項目的人,而是在一年以後加入的 - 想起我開始的地方仍然很興奮

至於我,我認識到一個需求和一個有趣的項目。我慢慢並持續地有更多的參與,如今我已經可以有了個人僱主,Behance,資助我一半的時間工做在 Babel 上。

有時候「維護」只是意味着修復 bugs,在 Slack 或 Twitter 上回答問題,或是編寫更新日誌(這真的取決於咱們每個人)。可是最近,我已經減小了在 bug 修復和特性上的注意力。取而代之的是我把時間放在了思考更多高層次的問題上,例如:這個項目的將來是什麼?咱們如何就維護者與用戶的數量而言,使咱們的社區增加。咱們如何在資金方面維持這個項目?咱們如何總體的融入 JavaScript 生態系統(教育,TC39,工具)?這裏有沒有一個適合咱們的角色來幫助新人加入開源項目(RGSoCGSoC)?

由於這些問題,這個版本最讓我感到興奮的地方不是那些特性(有不少:初步實施的新提案好比 Pipeline Operator (a |> b),有 TS 團隊提供幫助的 new TypeScript preset 和 .babelrc.js 文件)。

而是我對這些特性所表明的東西更興奮:一年來不懈的努力不去打破一切,平衡用戶的指望(爲何構建這麼慢/代碼輸入這麼大,爲何代碼沒有足夠的兼容,爲何這個工做不能沒有配置,爲何這裏沒有一個對其餘狀況的選擇)和維持一個由志願者組成的堅實團隊。

而且我知道咱們的行業對「主要版本」有一個很大的關注,大肆宣傳特性和 stars,但那只是一個衰落的日子。我想建議咱們繼續想想什麼使生態系統以一個健康的方式持續向前推動。

這可能僅僅意味着思考維護者的心理和情緒上的負擔。這可能意味着思考如何提供指導,指望管理,平衡工做/生活的建議和其餘的人們想要加入的資源,而不僅是鼓勵開發者來期待即時的,免費的幫助。

深刻更新日誌

嗯,我但願你能享受這個長的更新日誌 😊。若是你對幫助咱們感興趣,請讓咱們知道,咱們將很樂意多談。

由於人們想更多地瞭解關於 Babel 如何工做和回饋,咱們開放了一個新的 視頻頁面。這個頁面包含了 Babel 會議談話的視頻,來自團隊成員和社區人們的相關概念。

咱們一樣建立了一個新的 團隊頁面!咱們將在將來使用更多的關於人們在作什麼工做和爲何他們加入的信息來更新這個頁面。對於一個這樣大的項目,這裏有不少方法參與其中並幫忙。

這有一些亮點和簡短的事實:

  • Babel 在 2017 年 10 月 28 日 已經 3 歲了!
  • Daniel 把 babel/babylonbabel/babel-preset-env 移動到 主要的 Babel monorepo 裏,babel/babel。這包含 Git 歷史,標籤和提案。
  • 咱們從 Facebook Open Source 收到了 每個月 1000 美圓的捐贈
  • 這是咱們從一開始收到的最高的月度捐贈(下一個是 100 美圓/月)。
  • 同時,咱們將用咱們的資金去親自會見,並派人去 TC39 會議。這些會議每隔 2 個月在世界各地舉行。
  • 若是一個公司想制定贊助什麼,咱們能建立一個單獨的議題來跟蹤。這在以前是困難的,由於咱們必須用從口袋掏錢支付,或者在同一周找到一個會議發言來幫助支付費用。

你怎麼才能幫忙

若是你的公司願意經過支持一個 JavaScript 開發的基礎部分和他的將來做爲 回報,考慮一下給咱們的 Open Collective 捐獻。你也能貢獻開發時間來幫助維護這個項目。

#1:幫助維護項目(工做中開發人員的時間)

對 Babel 最好的事情就是找願意幫助項目的人,他們可以承擔大量的工做並對需求負責。再說一下,我歷來沒以爲準備好 成爲一個維護者,但不知道怎麼的,就發現已經這樣了。可是我只是一我的,而且個人團隊只有少數幾我的。

#2:幫助資助開發

我無疑是想可以給團隊的人資金使他們可以全職工做。尤爲是 Logan,不久之前離開了他的工做而且用咱們的資金來進行 Babel 的兼職工做。

#3 從其餘渠道作貢獻

例如,Angus 給咱們製做了一個 官方歌曲

升級

咱們也將升級幫助你 重寫你的 package.json/.babelrc 文件 的工具和其餘更多的東西。 理想狀況下,這意味着它將修改任何須要的版本號變動,包的重命名和配置的變動。

當嘗試更新的時候,請伸出手來幫助併發布議題。這是一個參與其中並幫助生態系統更新的絕好的機會。

前一個發佈 總結

  • 放棄對 Node 0.10/0.12/5 的支持
  • 更新 TC39 提案
  • 數字分隔符: 1_000
  • 可選的連接操做符: a?.b
  • import.meta (可解析)
  • 可選的 Catch 綁定:try { a } catch {}
  • BigInt(可解析):2n
  • 分割導出擴展到 export-default-fromexport-ns-form
  • 支持 .babelrc.js(使用 JavaScript 代替 JSON 的配置)
  • 增長一個新的 Typescript Preset 和拆分 React/Flow presets
  • 增長 JSX 分段支持 和 各類 Flow 更新
  • 爲了更小的體積,刪除內部 babel-runtime 依賴

最新更新的 TC39 提案

  • Pipeline 操做符:a |> b
  • Throw 表達式:() => throw 'hi'
  • 無效合併操做符:a ?? b

棄用年份 presets(例如,babel-preset-es20xx)

注意:使用 babel-preset-env

這比你決定使用哪一個 Babel preset 更好的地方是什麼?已經爲你完成了,自動地!

儘管維護數據列表的工做量很大 - 再一次,咱們須要幫助 - 它解決了不少問題。它確保了用戶可以及時瞭解規範。它意味着較少的配置/包的混亂。它意味着一個簡單升級之路。而且它意味着更少的什麼是什麼的問題。

babel-preset-env 實際上是一個很 的 preset,它代替了每一個其餘的你將須要的(es2015,es2016,es2017,es20xx,latest 等等)句法 preset。

它代替了全部的老的 presets 來編譯最新年度的 JavaScript 版本(Stage 4 裏的不管什麼)。可是它也有能力根據你指定的目標環境編譯:它可以處理開發模式,好比最新版本的瀏覽器,或是多重構建,例如 IE 版本。 它甚至有另外一個爲了流行多年的瀏覽器提供的版本

沒有移除 Stage presets(babel-preset-stage-x)

咱們能夠隨時更新它,或許咱們只須要決定一個比當前 presets 更好的系統。

如今,stage presets 只是咱們在每一個 TC39 會議後手動更新的插件列表。要使這個可管理,咱們須要容許主要的版本爲這些「不穩定」的包作緩衝。這是一部分,由於委員會不管怎樣都將重建這些包。因此咱們可能會從一個官方包作這件事,而且以後咱們有能力提供過更好的消息等等。

重命名:Scoped Packages(@babel/x

這裏是一個大約一年前我發佈的投票:

那時候,沒有不少項目使用 scoped packages,因此不少人甚至不知道它們的存在。那時候你可能必須爲了一個 npm org 的帳戶花錢,而如今它是免費的(而且支持也 non-scoped packages)。

搜索 scoped packages 的問題已經被解決了,下載計數也已經生效。惟一一個絆腳石就是一些第三方註冊仍然不支持 scoped packages。可是我想咱們如今正處於一個點,在這裏看起來等待很不合理。

爲何咱們更喜歡 scoped packages:

  • 命名困難:咱們不須要去檢查別人是否決定在他們的插件上使用咱們的命名慣例
  • 在 package squatting 上咱們有相似的問題
  • 有些時候人們建立 babel-preset-20xx 或是其餘的包是由於好玩。咱們必須發佈一個議題,而且發郵件把它要回來
  • 有人有一個合法的包,可是它剛好和咱們想叫的名字是同樣的
  • 有人看到一個新的提案正在 merging(像 optional chaining 或者 pipeline 操做符),而且決定使用一樣的名字來 fork 和 publish。而後,當咱們發佈的時候,咱們就被告知包已經被髮布了 🤔。因此我必須找到他們和 npm 支持團隊雙方的電子郵件,把包拿回來再從新發布。
  • 同一個名字下,什麼是「官方」包,什麼是用戶/社區包?咱們收到了有些人使用錯誤的名字或者非官方包的問題報告,緣由是他們覺得這是 Babel 的一部分。關於這個一個例子是有一份報告說 babel-env 重寫了他們的 .babelrc 文件。他們花了一些時間才意識到它不是 babel-preset-env

因此,這已經很清楚了,咱們應該使用 scoped packages,而且,不論什麼,咱們應該快一些完成它!

scoped name 更改的例子:

  • babel-cli -> @babel/cli
  • babel-core -> @babel/core
  • babel-preset-env -> @babel/preset-env

重命名:-proposal-

如今任何提案都將被以 -proposal- 命名來標記他們尚未在 JavaScript 官方以內。

因此 @babel/plugin-transform-class-properties 變成 @babel/plugin-proposal-class-properties,當它進入 Stage 4 後,咱們會把它命名回去。

重命名:把插件名字裏的年份去掉

以前的 plugins 名字裏有年份,可是如今彷佛並非必須的。

因此 @babel/plugin-transform-es2015-classes 變成 @babel/plugin-transform-classes

由於年份只是用於 es3/es2015,咱們沒有從 es2016 或 es2017 裏改變任何東西。不管怎樣,咱們將那些 presets 設置爲 preset-env,而且,對於字面模板調整,咱們只是簡單地把它添加到字面模板轉換裏。

Peer dependencies 和 integrations

咱們介紹一下 @babel/core 上的 peer dependencies,用於全部的 plugins(@babel/plugin-class-properties),presets(@babel/preset-env)和 top level packages(@babel/clibabel-loader

peerDependencies 是被你的代碼指望使用的依賴,與只被用於實現細節的 dependencies 相反。- Stijn de Witt 在 StackOverflow 上的回答

babel-loaderbabel-core 上 已經有一個 peerDependency 了,因此這個只是把它變成了 @babel/core。這個改變阻止了人們嘗試去安裝這些 Babel 包的錯誤版本。

對於在 babel-core 已經有 peerDependency 和沒有準備好主要更新(由於改變 peer dependency 是一個 breaking change)的工具,咱們已經發布了一個新版本的 babel-core 來橋接新版本上的改變 babel-core@7.0.0-bridge.0。想得到更多地信息,查看 這個議題

相似的,像 gulp-babelrollup-plugin-babel 等等的包都曾經把 babel-core 做爲一個 dependency。如今,這些將僅僅在 @babel/core 上有 peerDependency。由於這個,這些包沒有必要在 @babel/core API 改變的時候升級主要版本

#5224:獨立發佈 experimental packages

我在 Babel 的狀態Versioning 部分提到過這個。這裏是 Github Issue

你可能記得在 Babel 6 以後,Babel 變成了一個擁有它本身的生態系統的一套 npm 包,這個生態系統有 custom presets 和 plugins。

然而,從那之後,咱們一直使用一個 「fixed/synchronized」 的版本系統(因此沒有包是在 v7.0 或者是以上的)。當咱們作一個新的發佈,例如 v6.23.0,只有源代碼更新過的包纔會隨着新版本一塊兒被髮布。其他的包保持原樣。這在實踐中大可能是管用的,由於咱們在咱們的包中使用了 ^

不幸的是,當一個包須要發佈一個主版本時,這種系統須要爲全部的包都發佈一個。這要不意味着咱們作了不少小的 breaking changes(沒必要要的),要不就意味着咱們咱們打包了不少 breaking changes 到一個發佈中。相反,咱們想把 experimental packages(Stage 0 等等)和 全部其餘的(es2015)區分開。

由於這個,當規範變化時,咱們打算將全部的 experimental proposal plugins 的主版本迭代,而不僅是等待去更新全部的 Babel。因此,任何 Stage 4 以前的東西都將以主版本迭代的形式開放給 breaking changes。Stage presets 自身也是同樣的(若是咱們不把他們整個扔掉)。

與這個隨之而來的是咱們要求 TC39 提案使用 -proposal- 的名字的決定,咱們將對插件及其所屬的 preset 作一個主版本迭代(而不是隻作一個可能讓人失望的補丁版本)。而後,咱們將須要棄用舊的版本,而且創建一個無論規範變成什麼樣子都將自動更新令人們保持最新的框架(並使他們不被什麼東西卡住。咱們沒有像 decorators 那麼幸運。)。

.babelrc 中的 env 選項沒有沒棄用

不像最後一個提交,咱們只是修復了合併的行爲來使其更兼容

env 中的配置被賦予了比根配置項更高的優先級。而且如今根據它們的標識來合併,而不是隻是同時使用 plugins 和 presets 這種奇怪的實現,因此如今咱們能夠這樣作:

{  presets: [    ['env', { modules: false}],  ],  env: {    test: {      presets: [         'env'      ],    }  },}
複製代碼

有了 BABEL_ENV=test,它將使用沒有選項的 test 中的配置來替換根環境配置。

支持 [class A extends Array](https://twitter.com/left_pad/status/940723982638157829) (最先的警告)

Babel 將自動包含像 ArrayErrorHTMLElement 的原生 built-ins,因此作這個會在編譯 classes 的時候生效。

速度

preset-env:"useBuiltins":"usage"

babel-preset-env 介紹了編譯語法到不一樣的目標的想法。它同時介紹了經過 useBuiltIns 選項,只爲目標添加不支持的 polyfills 的能力。

因此有了這個選項,一些事情好比:

import "babel-polyfill";
複製代碼

可以變成

import "core-js/modules/es7.string.pad-start";import "core-js/modules/es7.string.pad-end";// ...
複製代碼

若是目標環境恰巧支持 padStartpadEnd 以外的 polyfills。

可是爲了使它更好,咱們應該僅僅引入代碼庫自身「使用」的 polyfills。若是它在代碼中沒有使用 padStart,爲何引入?

"useBuiltins": "usage" 是咱們解決那個想法的第一次嘗試。它在每一個文件的頭部執行了一個引入,可是隻有在找到它在代碼中被使用的時候才添加引用。這個實現意味着咱們可以爲應用引入最小量的,必須的 polyfills(而且只有在目標環境不支持它的時候)。

因此若是你在代碼中使用 Promise,它將在文件的頭部引入它(若是你的目標不支持它)。若是它是重複的,Bundlers 將會刪除重複的部分,因此這個實現不會形成 polyfills 的多重引用。

import "core-js/modules/es6.promise";var a = new Promise();
複製代碼
import "core-js/modules/es7.array.includes";[].includesa.includes
複製代碼

經過類型推斷咱們能知道一個像 .includes 的實例是不是一個 array。在邏輯變得更好以前,獲得一個 false positive 是能夠的,由於它仍舊是優於以前引入整個 polyfill 的。

其餘更新

  • [babel-template](https://github.com/babel/babel/blob/master/packages/babel-template) 更快而且用起來更簡單
  • regeneratorMIT 證書下發布 - 它是用來編譯 generators/async 的依賴
  • 經過 #6952modules-commonjs plugin 的 「lazy」 選項
  • 你如今能在 .babelrc 中使用 envName: "something" 或者 在命令行輸入 babel --envName=something 來取代必須使用process.env.BABEL_ENVprocess.env.NODE_ENV
  • ["transform-for-of", { "assumeArray": true }] 來使全部的 for-of 循環按照規則數組輸出
  • 爲了 preset-env #6831,在鬆散模式中排除 transform-typeof-symbol
  • 實現 PR 來得到更好的語法錯誤消息

發佈以前須要作的

  • Handle [.babelrc](https://github.com/babel/babel/issues/6766) lookup(想在第一次 RC 發佈以前完成)
  • 「overrides」 support:基於全局模式的差別配置
  • babel-core 中的緩存和無效邏輯
  • 圍繞外部 helpers 的更好的 story。
  • 對於迭代和處理 independently 對於 helpers 的獨立性,實現它或者是有一個成熟的計劃,因此咱們不是明確的與 core-js 2 或 3 綁定。人們可能有東西依賴於一個或者其餘,而且不想同時加載二者太多。
  • 無論是一個working decorator 的實現,或者是 functional legacy 的實現,在 7.x’s 的有效期內,有一個明確的路徑實現當前標準的行爲。

感謝

向咱們的志願者團隊致意:

Logan 已經很努力的推動修復不少咱們關於配置及更多的核心問題。他就是那個作了全部困難工做的人。

Brian 已經接管不少 preset-env 的維護工做,不管之前我作過什麼 😛

Daniel 一直在咱們須要的幫助的時候介入,無論是維護 babel-loader 或是幫助遷移 babylon/babel-preset-env 庫。一樣的,NicoloSvenArtemDiogo,在上一年幫助作了更多。

我真的很期待一個發佈(我也累了 - 已經快一年了 😝)。可是我也不想催促任何東西,由於在這個版本中已經有不少的起伏了。我確實學到了不少東西,我相信團隊的其餘成員也是如此。

若是我今年學到了什麼,我應該真正的遵從這個建議而不僅是寫下來。

一樣感謝 Mariko輕推,實際完成了這個發佈(兩個月的製做)。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索