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

すべての主要ブラウザで適切に動作するウェブサイトを構築することは、オープンウェブ エコシステムの基本原則です。ただし、記述するコードが、ターゲットとする各ブラウザでサポートされていることを確認する作業が必要になります。新しい 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 に感謝します。