本文へスキップ

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/clibabel-loader@rollup/plugin-babelなど)

@babel/preset-env@babel/coreに直接移動することには、2つの大きな利点があります。

  • シンプルなプロジェクトでBabelを設定するのが容易になります。babel.config.jsoncompileJS: 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-envcore-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-envtargetsオプションを使用して、変換プラグインを自動的に有効または無効にしていました。

ただし、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 がソースコードをどのように変換するのかを学習するための便利な環境です。

現在の制限

望ましい機能

  • 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/ をご覧ください(下部のセクターをクリックしてマウスを押したままにしてください!)