18

と組み合わせて使用​​する@babel/preset-envのさまざまな構成に対して、さまざまな出力が得られます。ドキュメントを読みましたが、ベスト プラクティスがどうあるべきかを理解できませんでした。useBuiltIns@babel/transform-runtime

たとえば、ブラウザのターゲット リストに Edge 18 が含まれている場合にポリフィルを追加し@babel/preset-envます。useBuiltInsstring.replace

しかし、@babel/transform-runtime代わりに使用すると、そのポリフィルは追加されません。


だから、この質問から始めます:

Does `string.replace` need to be polyfilled for Edge 18?

caniusemdnおよびcompat-tableは優れた教育リソースですが、実際には開発者ツールのデータ ソースとして使用することを意図したものではありません: compat-tableES 関連のデータの適切なセットが含まれているだけで、@babel/preset-env によって使用されますが、いくつかの制限があります。

そしてさらに:

このため、core-js-compatパッケージを作成しました。このパッケージは、さまざまなターゲット エンジンに対する core-js モジュールの必要性に関するデータを提供します。を使用する場合core-js@3@babel/preset-env代わりにその新しいパッケージを使用しますcompat-table.

そこで、ターゲット ブラウザを に渡し、core-js-compat必要なすべての polfill を出力しました。下の画像でわかるように、ほとんどが Edge 18 をサポートするために、かなりの数の文字列メソッドをポリフィルする必要があります。

ここに画像の説明を入力

ここまでは順調ですね。string.replace Edge 18 ではポリフィルが必要なようです。


バベルの設定

最初のアプローチ:@babel/preset-envおよびuseBuiltIns: 'usage'

useBuiltIns: 'usage'からファイルごとのポリフィルを取り込むために使用する場合core-js:

// babel.config.js

  presets: [
    [
      '@babel/preset-env',
      {
        debug: false,
        bugfixes: true,
        useBuiltIns: 'usage',
        corejs: { version: "3.6", proposals: true }
      }
    ],
    '@babel/preset-flow',
    '@babel/preset-react'
  ],

の場合debug: true、Babel は次のポリフィルをPriceColumn.jsファイルに追加すると言います:

// Console output

[/price-column/PriceColumn.js] Added following core-js polyfills:

  es.string.replace { "edge":"17", "firefox":"71", "ios":"12", "safari":"12" }
  es.string.split { "edge":"17" }
  web.dom-collections.iterator { "edge":"17", "ios":"12", "safari":"12" }

1 つの違いは、上記の出力に見られるのとは異なり、es.string.replacetargetと書かれていることです。これは私が行ったことがあるかもしれませんが、今のところは問題ありません。edge: 17edge: 18core-js-compat

Babel がトランスパイルされたPriceColumn.jsファイルの先頭に追加する追加事項:

// PriceColumn.js

"use strict";

require("core-js/modules/es.string.replace");

require("core-js/modules/es.string.split");

require("core-js/modules/web.dom-collections.iterator");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

繰り返しますが、これまでのところとても良いです。


2番目のアプローチ:@babel/runtimeおよび@babel/transform-runtime

core-jsのドキュメントによると:

@babel/runtimeオプションを使用すると、 でcorejs: 3の作業が簡素化されます core-js-purecore-js JS 標準ライブラリの最新機能の使用を、グローバルな名前空間の汚染なしのバージョンからのインポートに自動的に置き換えます。

いいですね - 試してみましょう!

コメントアウトしてプラグイン設定useBuiltInsを追加:@babel/transform-runtime

// babel.config.js

  presets: [
    [
      '@babel/preset-env',
      {
        debug: true,
        // bugfixes: true,
        // useBuiltIns: 'usage',
        // corejs: { version: '3.6', proposals: true }
      }
    ],
    '@babel/preset-flow',
    '@babel/preset-react'
  ],
  plugins: [
    [
      '@babel/transform-runtime',
      {
        corejs: { version: 3, proposals: true },
        version: '^7.8.3'
      }
    ]
  ],

コンソール出力には、次のように表示されます。

Using polyfills: No polyfills were added, since the `useBuiltIns` option was not set.

ファイルの先頭に何が追加されたかを確認します。

// PriceColumn.js

"use strict";

var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");

var _Object$defineProperty = require("@babel/runtime-corejs3/core-js/object/define-property");

_Object$defineProperty(exports, "__esModule", {
  value: true
});

exports.default = void 0;

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/objectSpread2"));

var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/instance/map"));

そのため、さまざまなものhelpersが追加されましたが、es.string.*ポリフィルの兆候はありません。それらはもう必要ありませんか?彼らはすでに「ヘルパー」によって持ち込まれていますか? オブジェクト スプレッドと配列マップは、文字列インスタンス メソッドのポリフィルと関係があるようには見えないので、そうではないと思います。


ついに

私の最後の試みは、両方のアプローチを組み合わせて、推奨事項に従うことでした:

ここに画像の説明を入力

a) にcorejs設定@babel/preset-env:

// babel.config.js

  presets: [
    [
      '@babel/preset-env',
      {
        debug: true,
        // bugfixes: true,
        useBuiltIns: 'usage',
        corejs: { version: '3.6', proposals: true }
      }
    ],
    '@babel/preset-flow',
    '@babel/preset-react'
  ],
  
  plugins: [
    [
      '@babel/transform-runtime',
      {
        // corejs: { version: 3, proposals: true },
        version: '^7.8.3'
      }
    ]
  ]

これは出力です:

// PriceColumn.js

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

require("core-js/modules/es.string.replace");

require("core-js/modules/es.string.split");

require("core-js/modules/web.dom-collections.iterator");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

b)corejsに設定@babel/transform-runtime:

  • 2 番目のアプローチと同じ (上記参照)

さまざまなアプローチの出力を比較する

だけを使用useBuiltIns

  • 必要な文字列ポリフィルを取り込みますが、グローバル名前空間を汚染します。

だけを使用@babel/runtime-transform

  • 文字列ポリフィルは取り込まれませんが、配列マップとオブジェクト スプレッド用に他のヘルパー/ポリフィルが取り込まれます ??

と の両方を組み合わせてuseBuiltIns使用@babel/transform-runtime​​:

  • 必要な文字列ポリフィルを取り込みますが、グローバル名前空間を汚染します。
  • また、オブジェクト スプレッド ポリフィルも取り込みます (ただし、配列マップ ポリフィルは除きます)。
  • @babel/runtime/helpers/objectSpread2(runtime vs runtime-corejs3)ではなくからのインポート@babel/runtime-corejs3/helpers/objectSpread2- 配列マップのポリフィルが取り込まれなかった理由である可能性があります??)

質問

これらのうち、正しいアプローチはどれですか?

withがポリフィルをもたらすので、@babel/preset-envwithが最適だと思います。useBuiltIns

グローバル名前空間を汚染することの欠点は何ですか? これはライブラリのみの問題ですか?

と組み合わせて@babel/transform-runtime、オブジェクト スプレッドのポリフィルも取得します (ポリフィルの提案@babel-preset-envが必要ですが、プラグインもcorejs: { version: '3.6', proposals: true }使用しないとそこに取り込まれない理由がわかりません)。@babel/transform-runtime

Array#map ポリフィルは必要ですか?

4

1 に答える 1