最新のブラウザに最新のコードを提供し、ページの読み込みを高速化する

すべての主要ブラウザで適切に動作するウェブサイトを構築することは、オープンウェブ エコシステムの基本原則です。ただし、記述するコードが、ターゲットとする各ブラウザでサポートされていることを確認する作業が必要になります。新しい JavaScript 言語機能を使用したい場合は、まだサポートされていないブラウザ用に、これらの機能を下位互換性のある形式にトランスパイルする必要があります。

Babel は、新しい構文を含むコードを、さまざまなブラウザや環境(Node など)が理解できるコードにコンパイルするために最も広く使用されているツールです。このガイドでは Babel を使用していることを前提としています。まだ Babel をアプリケーションに追加していない場合は、設定手順に沿って追加する必要があります。アプリでモジュール バンドラとして webpack を使用している場合は、Build Systemswebpack を選択します。

Babel を使用してユーザーに必要なものだけをトランスパイルするには、次の操作を行う必要があります。

  1. ターゲットとするブラウザを特定します。
  2. 適切なブラウザ ターゲットで @babel/preset-env を使用します。
  3. <script type="module"> を使用すると、変換されたコードを必要としないブラウザに送信しないようにできます。

ターゲットとするブラウザを特定する

アプリケーションのコードがトランスパイルされる方法を変更する前に、アプリケーションにアクセスするブラウザを特定する必要があります。ユーザーが現在使用しているブラウザと、ターゲットとするブラウザを分析して、十分な情報に基づいて意思決定を行います。

@babel/preset-env を使用する

通常、コードをトランスパイルすると、元の形式よりもファイルサイズが大きくなります。コンパイルする量を最小限に抑えることで、バンドルのサイズを小さくし、ウェブページのパフォーマンスを向上させることができます。

使用している特定の言語機能を個別にコンパイルするために特定のプラグインを組み込む代わりに、Babel にはプラグインをバンドルする多数のプリセットが用意されています。@babel/preset-env を使用して、ターゲットとするブラウザに必要な変換とポリフィルのみを含めます。

Babel 構成ファイル .babelrcpresets 配列に @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 に感謝します。