最新の JavaScript を公開、配布、インストールして、アプリケーションの高速化を実現

最新の JavaScript の依存関係と出力を有効にして、パフォーマンスを向上させます。

90% を超えるブラウザは最新の JavaScript を実行できますが、 従来の JavaScript の普及がパフォーマンスの問題の原因となっている 今すぐウェブで公開されています。

最新の JavaScript

最新の JavaScript は、特定の ECMAScript で記述されたコードとして特徴付けられていない 最新のバージョンでサポートされている構文で できます。Chrome、Edge、Firefox、Safari などの最新のウェブブラウザは ブラウザ市場の 90% 以上を占める 基盤となる同じレンダリング エンジンを使用する複数のブラウザ間で、 5% 増加しますつまり、世界のウェブ トラフィックの 95% がブラウザからのものです 過去 10 日間で最も広く使用されている JavaScript 言語機能をサポートしており、 、

  • クラス(ES2015)
  • Arrow 関数(ES2015)
  • Generator(ES2015)
  • ブロックのスコープ設定(ES2015)
  • 分解(ES2015)
  • 休息とスプレッドのパラメータ(ES2015)
  • オブジェクトの省略形(ES2015)
  • Async/await(ES2017)

通常、新しいバージョンの言語仕様の機能には、 最新のブラウザ間で一貫したサポートを提供します。たとえば、多くの ES2020 や ES2021 機能のサポートはブラウザ市場の 70% にとどまっており、 これらの機能を直接使用しても 安全というには不十分ですこの 「モダン」とは言えJavaScript は動くターゲットであり、ES2017 には 幅広いブラウザとの互換性 よく使用される最新の構文機能のほとんどが含まれています。 つまり、ES2017 は今日の最新の構文に最も近いものです

従来の JavaScript

従来の JavaScript は、上記の言語の使用を明示的に回避するコードです。 説明します。ほとんどのデベロッパーは最新の構文でソースコードを記述しますが、 すべてを以前の構文にコンパイルし、ブラウザのサポートを強化します。コンパイル ブラウザのサポートは強化されますが、 考えています多くの場合、サポートは約 95% から 98% 削減できます。

  • 通常、従来の JavaScript は、従来の JavaScript よりも 最新のコードを利用できます。ツールの欠陥と構成ミスがしばしば発生する このギャップがさらに広がります

  • インストールされているライブラリが一般的な本番環境の 90% を占める 使用できます。ライブラリ コードでは、以前の JavaScript がさらに大きく 回避できる可能性のあるポリフィルとヘルパーの重複によるオーバーヘッド 開発できます

npm 上の最新の JavaScript

最近、Node.js では "exports" フィールドを標準化して、 パッケージのエントリ ポイント:

{
  "exports": "./index.js"
}

"exports" フィールドで参照されるモジュールは、少なくとも 12.8 は ES2019 をサポートしています。つまり、Terraform で参照されるモジュールは、 "exports" フィールドは、最新の JavaScript で記述できます。パッケージ コンシューマは、 "exports" フィールドを含むモジュールに最新のコードが含まれていると想定し、次の場合はトランスパイルされる できます。

最新のみ

最新のコードでパッケージを公開し、 依存関係として使用する場合は、コンシューマがトランスパイルを処理できます。 "exports" フィールド。

{
  "name": "foo",
  "exports": "./modern.js"
}

最新(以前のフォールバックあり)

パッケージを公開するには、"exports" フィールドと "main" を使用します。 古いコードに対応する ES5 + CommonJS のフォールバックも できます。

{
  "name": "foo",
  "exports": "./modern.js",
  "main": "./legacy.cjs"
}

以前のフォールバックと ESM バンドラ最適化による最新モデル

"module" フィールドは、フォールバックの CommonJS エントリポイントの定義に加えて、 同様の以前のフォールバック バンドルを指すために使用されますが、 JavaScript モジュールの構文(importexport)。

{
  "name": "foo",
  "exports": "./modern.js",
  "main": "./legacy.cjs",
  "module": "./module.js"
}

webpack や Rollup などの多くのバンドラが、このフィールドを活用して このモジュールの機能を ツリー シェイキング。 これはまだ従来のバンドルであり、Google Cloud で提供される import/export 構文が使用されるため、この方法を使用して最新のコードを バンドル用に最適化されたままの 従来のフォールバックです

アプリケーションでの最新 JavaScript

一般的な本番環境の大部分はサードパーティの依存関係によって構成されている ウェブ アプリケーションの JavaScript コード。npm の依存関係は従来、 公開されているため、これは安全な前提ではなく、 依存関係の更新によってアプリケーションでのブラウザ サポートが機能しなくなるリスクがあります。

最新の JavaScript に移行する npm パッケージの数が増えるにつれ、 処理できるようにビルドツールを設定することが重要です。また、 利用している npm パッケージの一部は、すでに最新のバージョンを使っている可能性が高い 提供します。最新のコードを使用するためのさまざまなオプション npm から入手することもできますが、 依存関係を同じ構文にトランスパイルすることで、 使用します。

Webpack

Webpack 5 以降では、webpack が使用する構文を設定できるようになりました。 コードの生成時に発生します。これは、 「接着剤」にのみ影響し、コードをコンパイルします。 ブラウザのサポート ターゲットを指定するには、 browserslist 構成 プロジェクトに追加するか、webpack の構成で直接行います。

module.exports = {
  target: ['web', 'es2017'],
};

また、最適化されたバンドルを生成するように Webpack を構成することも、 最新の ES モジュールをターゲットにする場合は不要なラッパー関数を省略 できます。また、 <script type="module">

module.exports = {
  target: ['web', 'es2017'],
  output: {
    module: true,
  },
  experiments: {
    outputModule: true,
  },
};

さまざまな Webpack プラグインを使用して、 従来のブラウザにも対応しながら、最新の JavaScript をコンパイルして配布できます。 ダウンロードします

プラグインの最適化

Optimize Plugin: ウェブパック 最終的にバンドルされたコードを最新の JavaScript から以前の JavaScript に変換するプラグイン 個々のソースファイルではなくこれは自己完結型の構成であり すべてが最新の JavaScript であり、 複数の出力や構文に対応する特殊分岐が利用されます。

オプティマイズ プラグインは、個々のモジュールではなくバンドルで動作するため、 アプリケーションのコードと依存関係を平等に処理します。これにより、 最新の JavaScript 依存関係を使用しても安全です。なぜなら、 バンドルされ、正しい構文にトランスパイルされます。また、P-MAX よりも 2 つのコンパイル ステップを必要とする従来のソリューションと、引き続き生成 最新のブラウザと従来のブラウザで別々にバンドルする必要があります。この 2 つのバンドルセットは、 使用して読み込まれるように設計されている module/nomodule パターン:

// webpack.config.js
const OptimizePlugin = require('optimize-plugin');

module.exports = {
  // ...
  plugins: [new OptimizePlugin()],
};

Optimize Plugin はカスタム Webpack よりも高速かつ効率的です 構成で使用します。これは、 また、Babel の実行を処理し、 Terser を使用して、バンドルごとに最適な設定を 説明します。最後に、生成された 従来のバンドルは専用のスクリプトに抽出されるため、 新しいブラウザで重複して読み込まれたり、不必要に読み込まれたりする可能性があります。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
比較: ソース モジュールの 2 回分のトランスパイルと、生成されたバンドルのトランスパイル

BabelEsmPlugin

BabelEsmPlugin: Webpack Google Cloud SDK などの @babel/preset-env 既存のバンドルの最新バージョンを生成し、トランスパイルされたコードを 最新のブラウザで利用できます。最も人気のある既製のソリューションで module/nomodule: Next.jsPreact CLI

// webpack.config.js
const BabelEsmPlugin = require('babel-esm-plugin');

module.exports = {
  //...
  module: {
    rules: [
      // your existing babel-loader configuration:
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
  plugins: [new BabelEsmPlugin()],
};

BabelEsmPlugin はさまざまな webpack の構成をサポートしています。これは、 主に 2 つの別々のアプリケーションのビルドを実行します。2 回コンパイルすると 大規模なアプリケーションの場合は時間が少し長くなりますが、 BabelEsmPlugin: 既存の webpack 構成にシームレスに統合 非常に便利なオプションの一つです

node_modules をトランスパイルするように babel-loader を設定する

前の 2 つのプラグインのいずれかなしで babel-loader を使用している場合: 最新の JavaScript npm を使用するには、重要な手順があります。 説明します。2 つの異なる babel-loader 構成を定義すると、 node_modules にある最新の言語機能を、 Babel プラグインとプリセットを使用します。残念ながら、 モジュール/nomodule 設定用の最新のバンドルと以前のバンドルを生成しますが、 最新の JavaScript を含む npm パッケージをインストールして使用できる パフォーマンスを向上できます

webpack-plugin-modern-npm この手法を使用して、"exports" フィールドを持つ npm 依存関係をコンパイルします。 を package.json に追加します。これらは最新の構文が含まれている可能性があるためです。

// webpack.config.js
const ModernNpmPlugin = require('webpack-plugin-modern-npm');

module.exports = {
  plugins: [
    // auto-transpile modern stuff found in node_modules
    new ModernNpmPlugin(),
  ],
};

別の方法として、この手法をウェブパックに手動で実装することもできます。 package.json"exports" フィールドを確認して構成します。 解消されます。簡潔にするためにキャッシュを省略すると、 実装は次のようになります。

// webpack.config.js
module.exports = {
  module: {
    rules: [
      // Transpile for your own first-party code:
      {
        test: /\.js$/i,
        loader: 'babel-loader',
        exclude: /node_modules/,
      },
      // Transpile modern dependencies:
      {
        test: /\.js$/i,
        include(file) {
          let dir = file.match(/^.*[/\\]node_modules[/\\](@.*?[/\\])?.*?[/\\]/);
          try {
            return dir && !!require(dir[0] + 'package.json').exports;
          } catch (e) {}
        },
        use: {
          loader: 'babel-loader',
          options: {
            babelrc: false,
            configFile: false,
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
};

この方法を使用する場合は、Terraform で最新の構文がサポートされていることを確認する必要があります。 圧縮しますTerser と および uglify-es 保持するため {ecma: 2017} を指定するオプションがあり、場合によっては 圧縮時とフォーマット時に ES2017 構文を生成します。

傘下参入

Rollup には、統合の一部として複数のバンドルのセットを生成するサポートが組み込まれています。 最新のコードを生成できます。その結果、 公式プラグインを使用して最新のバンドルと以前のバンドルを生成するように構成できる すでにご存じかもしれません

@rollup/plugin-babel

傘下参入を使用すると getBabelOutputPlugin() メソッド (ロールアップの 公式 Babel プラグイン) は、個々のソース モジュールではなく、生成されたバンドル内のコードを変換します。 Rollup には、統合の一部として複数のバンドルのセットを生成するサポートが組み込まれています。 それぞれ独自のプラグインを持つ 1 つのビルドで構成できます。これを使用して 異なるバンドルを渡すことで、最新のバージョンとレガシーに異なるバンドルを Babel 出力プラグインの構成:

// rollup.config.js
import {getBabelOutputPlugin} from '@rollup/plugin-babel';

export default {
  input: 'src/index.js',
  output: [
    // modern bundles:
    {
      format: 'es',
      plugins: [
        getBabelOutputPlugin({
          presets: [
            [
              '@babel/preset-env',
              {
                targets: {esmodules: true},
                bugfixes: true,
                loose: true,
              },
            ],
          ],
        }),
      ],
    },
    // legacy (ES5) bundles:
    {
      format: 'amd',
      entryFileNames: '[name].legacy.js',
      chunkFileNames: '[name]-[hash].legacy.js',
      plugins: [
        getBabelOutputPlugin({
          presets: ['@babel/preset-env'],
        }),
      ],
    },
  ],
};

その他のビルドツール

Rollup と webpack は高度な構成が可能です。つまり、通常は各プロジェクトが 依存関係で最新の JavaScript 構文を有効にする必要がある。 より高レベルのビルドツールもあり、ルールよりも規則とデフォルトが優先されます。 ParcelSnowpackViteWMR などの構成です。これらのツールのほとんどは npm 依存関係に最新の構文が含まれていると想定し、 正しい構文レベルを確認してください。

webpack と Rollup の専用プラグインに加え、最新の JavaScript 以前のフォールバックを含むバンドルは、 devolution です。社会的に ビルドシステムの出力を変換してレガシー ソフトウェアを JavaScript バリアントにより、バンドルと変換によって最新の 出力ターゲットを指定します。