Babel ロードマップ
このドキュメントでは、私たちのチームメンバーが今年取り組みたいと考えているいくつかの改善点を概説しています。
これは、Babelにもたらされるすべての新機能や重要な変更の完全なリストからは程遠いですが、プロジェクトが進む方向に興味がある場合の良い概要です。リストされているすべての項目を実際に完了できるとは限らず、一部を翌年に延期する可能性があります。それらのいくつかは明確な開始点と終了点がありますが、他のものはより多くの調査またはRFCが必要です。
貴社が興味があり、特定の項目を直接スポンサーしたい場合は、ご連絡ください!
Babel 2021 ロードマップ
Babel 8
私たちは1年以上Babel 8のリリースについて議論してきました(当初は約1年前に予定していました)!しかし、今ではこれまで以上にリリースに近づいています!
残りのタスクの大部分は追跡中の課題にありますが、依然としていくつかのブロッカーがあります。
- 2021年4月30日にメンテナンスが終了するNode.js 10のサポートを削除したいと考えています。
- Babelを純粋なESMパッケージとしてリリースしたいと考えています。現在、ソースをNode.jsのESM実装と互換性があるように変換するプロセスを進めており、その過程で、現在Babelを使用してESMをCJSにコンパイルしている人にとって、それをより簡単にする方法を検討しています。
typescript-eslint
プロジェクトとTypeScript ASTを連携させようとしています。私たちのASTは*ほぼ*同一ですが、完全に連携させるために、いくつかの小さな破壊的変更を導入する必要があります。- 私たちのリリースインフラストラクチャはまだプレリリース、または複数の「main」ブランチ(Babel 8用とBabel 7用)の使用をサポートしていません。
- Babel 7のメンテナンスポリシーはまだ決定していません。
新しいTC39提案の実装
Babelは現在、すべてのStage 3提案を解析でき、トップレベルのawait、import assertions、JSONモジュール(依存関係グラフで動作するバンドラーによって最適に処理されます)を除くすべてを変換できます。
トップレベルのawait、import assertions、JSONモジュールを除き、すべてのStage 2提案をサポートしています。
- デコレーター提案の新しい反復(解析と変換の両方を実装する必要があります)。
- Module Blocks提案の変換(Babel 7.13.0で解析を実装しました)。
デコレーターのサポートを実装し、モジュールブロックの変換をどのように実装できるか調査します。
多くのStage 1提案をサポートしていませんが、パイプライン演算子とdo式に関する最近の更新がありました。これらの提案を既にサポートしており、コミュニティも非常に楽しみにしているため、実装を更新します。
パターンマッチングなど、まだ実装していない他の提案もあります。これは、彼らのチャンピオンが構文とセマンティクスに大きな変更を加えることを期待しているためです。ただし、それらの開発を綿密に追跡しており、安定し次第、Babelに実装します。
@babel/preset-env
を@babel/core
に移動
最小限のBabel変換設定には、少なくとも3つのパッケージが必要です。
@babel/core
@babel/preset-env
- Babel「ランナー」(
@babel/cli
、babel-loader
、@rollup/plugin-babel
など)
@babel/preset-env
を@babel/core
に直接移動することには、2つの大きな利点があります。
- シンプルなプロジェクトでBabelを設定するのが容易になります。
babel.config.json
でcompileJS: true
オプションを有効にするだけで済みます(将来はデフォルトになる可能性もあります--@babel/eslint-parser
はソースをコンパイルしないため、デフォルトにはできません)。 - プラグインのバージョンが
@babel/core
のバージョンと同期していることを確認し、バージョンが一致しない/互換性のないパッケージによって発生するほとんどのバグを回避します。 - ESMに移行すると、
transformSync
でプラグインを同期的に解決してロードすることが困難になります。これにより、問題が発生するのを防ぎます。
安定したECMAScript機能の*プラグイン*を@babel/core
に移動するためのRFCが既にあります。これは、この方向への最初のステップです。
現在の@babel/preset-env
アーキテクチャでは、targets
に基づいて公式プラグインを自動的に有効または無効にするために、特別に処理する必要があります。ただし、これには2つの欠点があります。
- 特定のプラグインの互換性データは、プラグインの実装から完全に分離されています(依存関係ではなく、内部的な暗黙的なピア依存関係のようなものです:プラグイン -> @babel/core -> @babel/compat-data)。
- 公式プラグインは
@babel/core
から特別な扱いを受けますが、サードパーティプラグインにも公式プラグインと同じ機能があることを確認したいと考えています。
babel-polyfills
プロジェクトの開発を継続
Babel 8で@babel/preset-env
から古いcore-js@2
のサポートを削除することに既に決定しています。また、特定のサードパーティポリフィルを宣伝することをやめたいと考えています。これは、ユーザーにそれがBabel自体の部分であるという印象を与える可能性があります。
これは2つの異なる方法で発生する可能性があります。
- Babel 8で
@babel/preset-env
からcore-js@3
を削除し、ユーザーにbabel-plugin-polyfill-corejs3
に移行することを推奨します(バージョン7.10.0以降、@babel/preset-env
が内部的に使用しているものです)。 @babel/preset-env
でcore-js@3
のサポートを維持しますが、変換プラグインを移動する際に@babel/core
に移行しません。
どちらのパスを選択する場合でも、ユーザーが設定でcore-js
の統合を更新する必要があるときに、少なくとも1つの代替手段を提供したいと考えています。core-js
は、可能な限り最高の仕様準拠を保証する非常に優れたポリフィルですが、ユーザーは異なるトレードオフを好む場合があります。
(Nicolò)は@ljharbと協力して、@es-shims
プロジェクトが少なくともすべてのES2015+機能(実際にはES5+を目指しています)をサポートするようにしているため、Babelユーザーは少なくとも2つのオプションから自由に選択できます。
これは、core-js@3
の組み込みサポートを削除する*前*に発生する必要があり、es-shims
に関心のある人が2回移行する必要がないようにします。
粒度の高い変換のためのtargets
の使用を拡張
当初から、@babel/preset-env
はtargets
オプションを使用して、変換プラグインを自動的に有効または無効にしていました。
ただし、Babelプラグインとブラウザーに実装されている機能との間に1対1のマッピングはありません。
たとえば、さまざまなクラスフィールドの種類(パブリックとプライベート、静的とインスタンス)に対して単一のプラグインがありますが、ブラウザーにはさまざまな互換性マトリックスがあります。
- Firefox 73とSafari 14は、パブリックインスタンスフィールドのみをサポートしています。
- Firefox 75以降は、パブリックインスタンスフィールドと静的フィールドをサポートしています。
- Chrome 79以降は、パブリックフィールドとプライベートフィールドをサポートしていますが、一部のオプションチェーン式ではプライベートフィールドをサポートしていません。
- Chrome 84以降は、プライベートフィールドとプライベートメソッドを完全にサポートしています。
- Safari TP 121はプライベートフィールドを完全にサポートしていますが(
?.
でも)、プライベートメソッドはサポートしていません。
機能ごとにプラグインを作成するのは最適ではありません。たとえば、プライベートメソッドをプライベートフィールドに変換してから、必要に応じて古い構文に変換できます。ただし、必要に応じてトランスパイルダウンする必要があることがわかっている場合、中間ステップなしでプライベートメソッドを古い構文に直接変換することで、より良い/最適化された出力を生成できます。
Babel 7.13.0以降、プラグイン内でtargets
オプションを直接読み取ることができるため、プラグインを変更して、特定のECMAScript機能の*部分的な*コンパイルを自動的に実行できます。これにより、出力サイズとランタイムパフォーマンスに利点があります。
先行事例
このアプローチは完全に新しいものではありません。@_developitとのコラボレーションのおかげで、Babel 7.9.0で@babel/preset-env
の新しいbugfixes: true
オプションを導入しました。このオプションが有効になっており、esmodules: true
をコンパイルターゲットとして使用している場合、一部の機能を部分的にコンパイルするだけです。これが、当初この可能性について考えたきっかけですが、現在の部分的な変換は、より新しいターゲット(たとえば、defaults, not ie 11
)を使用する場合にはあまり役に立ちません。
オブジェクトスプレッドをコンパイルする際にObject.assign
を使用できるかどうかを決定するために、既にtargets
オプションを使用しています。
行動計画
この目標は、並行して実行できる2つの大きなタスクに分割できます。
- 現実世界のbrowserslistクエリを収集し、一般的なクエリ(たとえば、
defaults
または>2%, not dead
)が将来どのように進化するかをシミュレートすることにより、これらの最適化が役立つ場所を特定する必要があります。 - 他のプラグインと引き続きうまく機能することを確認しながら(変換の組み合わせの可能性が大幅に増加するため)、必要な最適化を実際に実装する必要があります。
新しいコンパイラのassumptions
を調査
Babel 7.13.0では、loose
モードオプションの機能を正式化し、ユーザーにより粒度の細かい制御を提供する(多くの場合、すべての仮定ではなく、一部の仮定のみを有効にできるため)新しいトップレベルのassumptions
オプションを導入しました。
ただし、loose
モードでコンパイルする際に既に作成した仮定のオプションのみを含めました。これで、ユーザーが必要とする可能性のある新しい仮定を調査できます。
既にいくつかの提案があります。
- #8222 - すべてのESMインポートが実際に不変であると仮定し、ライブバインディングに必要なコードを回避します。
- #11356 - コンパイル済みのクラスはネイティブクラスを継承しないと仮定し、ネイティブクラスの可能性のあるインスタンス化に必要なランタイムのパフォーマンスコストを回避します。
実装すべき新しい仮定は、以下の方法で確認できます。
- コンパイル結果が「分かりにくい」出力になる機能を手動で確認します。これは通常、多くの開発者が気にしないエッジケースによって発生します。
- 開発者が自身のアプリケーションでどの仮定が機能し、どの仮定が機能しないかをテストできるため、コミュニティからのフィードバックを求めます。
Babel REPL のオーバーホール
Babel REPL は、Babel がソースコードをどのように変換するのかを学習するための便利な環境です。
現在の制限
- REPL は
assumptions
設定をサポートしていません。https://babel.dokyumento.jp/assumptions には仮定ごとのミニREPLがありますが、これらのassumptions
がどのように連携するかを示すことはできません。 - REPL はプラグインオプションをサポートしていません。
@babel/plugin-proposal-record-and-tuple
や@babel/plugin-proposal-decorators
など、一部のプラグインには必須のオプションがあります。https://github.com/babel/website/issues/1292、https://github.com/babel/website/issues/2224、https://github.com/babel/website/pull/1970
望ましい機能
- AST Explorer(既存のものと統合)
- 完全なスタックトレースを含む stderr をエラーログとして出力
- stdout を出力として出力
- UI から Babel のバージョンを変更
babel-website の未解決issueの少なくとも15%がREPLに関連しています:https://github.com/babel/website/issues?q=is%3Aissue+is%3Aopen+label%3Arepl
教育/デバッグツール
REPL/ASTExplorerに関連して、私たち自身とサードパーティプラグインの一般的なプラグイン開発を支援するためのツールがさらに必要です。これはむしろ探索的な性質のものであり、AST自体の様々な視覚化、デバッグなどがあります。
既に進行中のもの(Henryが断続的に取り組んでいるもの)
- Codesandbox を使用して、https://astexplorer.net と同様の方法で、カスタム設定を使用してシンプルなBabelプラグインを作成します。
- 視覚化:入力から出力へのマッピングを視覚化して、Babelがコードを変換する方法を理解するのに役立ちます。JavaScriptユーザーに新しい構文を理解させたり、変換の特定のデモを行うためのドキュメントにも役立ちます。
- マッピング:ソースマップのような構造で入力から出力へのマッピングを行います。逆マッピングを使用して、どのプラグインによってコードが出力されたのかを特定し、デバッグに役立ちます。
考えていることのインタラクティブな例については、https://babel-explorer.netlify.app/ をご覧ください(下部のセクターをクリックしてマウスを押したままにしてください!)