すべての主要なブラウザで適切に動作するウェブサイトを構築することは、オープン ウェブ エコシステムの基本原則です。ただし、これは、記述するすべてのコードがターゲットとする各ブラウザでサポートされていることを確認する追加の作業が必要になることを意味します。新しい JavaScript 言語機能を使用する場合は、これらの機能をサポートしていないブラウザとの下位互換性のある形式にトランスパイルする必要があります。
Babel は、新しい構文を含むコードを、さまざまなブラウザや環境(Node など)が理解できるコードにコンパイルするために最も広く使用されているツールです。このガイドでは Babel を使用することを前提としているため、まだ Babel をアプリケーションに含めていない場合は、設定手順に沿って Babel をアプリケーションに含める必要があります。アプリでモジュール バンドラとして webpack を使用している場合は、Build Systems で webpack を選択します。
Babel を使用してユーザーに必要なものだけをトランスパイルするには、次の操作を行う必要があります。
- ターゲットとするブラウザを特定します。
- 適切なブラウザ ターゲットを指定して
@babel/preset-envを使用します。 <script type="module">を使用して、トランスパイルされたコードを必要としないブラウザへの送信を停止します。
ターゲットとするブラウザを特定する
アプリケーションのコードのトランスパイル方法を変更する前に、どのブラウザがアプリケーションにアクセスしているかを特定する必要があります。ユーザーが使用しているブラウザと、ターゲットにする予定のブラウザを分析して、十分な情報に基づいて判断します。
@babel/preset-env を使用する
コードをトランスパイルすると、通常、元の形式よりもファイルサイズの大きいファイルが生成されます。コンパイルの量を最小限に抑えることで、バンドルのサイズを縮小し、ウェブページのパフォーマンスを向上させることができます。
Babel では、使用している特定の言語機能をコンパイルするために特定のプラグインを含めるのではなく、プラグインをバンドルしたプリセットが多数用意されています。@babel/preset-env を使用して、ターゲットにするブラウザに必要な変換とポリフィルのみを含めます。
Babel 構成ファイル .babelrc の presets 配列に @babel/preset-env を含めます。
{
"presets": [
[
"@babel/preset-env",
{
"targets": ">0.25%"
}
]
]
}
targets フィールドを使用して、browsers フィールドに適切なクエリを追加することで、含めるブラウザのバージョンを指定します。@babel/preset-env は、ブラウザをターゲットとするさまざまなツール間で共有されるオープンソース構成である browserslist と統合されています。互換性のあるクエリの完全なリストは、browserslist のドキュメントにあります。別の方法として、.browserslistrc ファイルを使用して、ターゲットとする環境を一覧表示することもできます。
">0.25%" 値は、グローバル使用率が 0.25% を超えるブラウザをサポートするために必要な変換のみを含めるよう Babel に指示します。これにより、ユーザーの割合が非常に少ないブラウザ用の不要なトランスパイル済みコードがバンドルに含まれないようにします。
ほとんどの場合、次の構成を使用するよりもこの方法をおすすめします。
"targets": "last 2 versions"
"last 2 versions" 値は、すべてのブラウザの最新の 2 つのバージョン用にコードをトランスパイルします。つまり、Internet Explorer などのサポートが終了したブラウザもサポートされます。これらのブラウザがアプリケーションへのアクセスに使用されることが想定されていない場合、バンドルのサイズが不必要に大きくなる可能性があります。
最終的には、ニーズに合ったブラウザのみをターゲットにするために、適切なクエリの組み合わせを選択する必要があります。
最新のバグ修正を有効にする
@babel/preset-env は、複数の JavaScript 構文機能をコレクションにグループ化し、指定されたターゲット ブラウザに基づいて有効または無効にします。この方法は有効ですが、対象のブラウザに 1 つの機能のバグが含まれている場合、構文機能のコレクション全体が変換されます。このため、必要以上に変換されたコードが生成されることがよくあります。
元々は別のプリセットとして開発された @babel/preset-env のバグ修正オプションは、一部のブラウザで壊れている最新の構文を、それらのブラウザで壊れていない最も近い同等の構文に変換することで、この問題を解決します。結果は、すべてのターゲット ブラウザで互換性を保証する小さな構文の調整がいくつか加えられた、ほぼ同一の最新のコードになります。この最適化を使用するには、@babel/preset-env 7.10 以降がインストールされていることを確認してから、bugfixes プロパティを true に設定します。
{
"presets": [
[
"@babel/preset-env",
{
"bugfixes": true
}
]
]
}
Babel 8 では、bugfixes オプションがデフォルトで有効になります。
<script type="module"> を使用する
JavaScript モジュール(ES モジュール)は、すべての主要なブラウザでサポートされている比較的新しい機能です。モジュールを使用すると、他のモジュールからインポートとエクスポートを行うスクリプトを作成できます。また、@babel/preset-env と組み合わせて、モジュールをサポートするブラウザのみを対象にすることもできます。
特定のブラウザのバージョンやマーケット シェアをクエリする代わりに、.babelrc ファイルの targets フィールド内で "esmodules" : true を指定することを検討してください。
{
"presets":[
[
"@babel/preset-env",
{
"targets":{
"esmodules": true
}
}
]
]
}
Babel でコンパイルされた新しい ECMAScript 機能の多くは、JavaScript モジュールをサポートする環境ですでにサポートされています。これにより、実際に必要なブラウザに対してのみトランスパイルされたコードが使用されるようにするプロセスが簡素化されます。
モジュールをサポートするブラウザは、nomodule 属性を持つスクリプトを無視します。逆に、モジュールをサポートしていないブラウザは、type="module" を含むスクリプト要素を無視します。つまり、モジュールとコンパイル済みのフォールバックを含めることができます。
理想的には、アプリケーションの 2 つのバージョン スクリプトは次のように含まれます。
<script type="module" src="main.mjs"></script>
<script nomodule src="compiled.js" defer></script>
モジュールをサポートするブラウザは main.mjs を取得して実行し、compiled.js を無視します。モジュールをサポートしていないブラウザは、これとは逆の処理を行います。
webpack を使用している場合は、アプリケーションの 2 つの別々のバージョン用に、構成で異なるターゲットを設定できます。
- モジュールをサポートするブラウザ専用のバージョン。
- 任意のレガシー ブラウザで動作するコンパイル済みスクリプトを含むバージョン。トランスパイルでは幅広いブラウザをサポートする必要があるため、ファイルサイズが大きくなります。
レビューをご提供くださった Connor Clark と Jason Miller に感謝いたします。