と組み合わせて使用する@babel/preset-env
のさまざまな構成に対して、さまざまな出力が得られます。ドキュメントを読みましたが、ベスト プラクティスがどうあるべきかを理解できませんでした。useBuiltIns
@babel/transform-runtime
たとえば、ブラウザのターゲット リストに Edge 18 が含まれている場合にポリフィルを追加し@babel/preset-env
ます。useBuiltIns
string.replace
しかし、@babel/transform-runtime
代わりに使用すると、そのポリフィルは追加されません。
だから、この質問から始めます:
Does `string.replace` need to be polyfilled for Edge 18?
完全にサポートされていることを示すcaniuse.comを確認しました-これは、ポリフィルが必要ないことを意味します。
ただし、Manuel Beaudru のブログ投稿core-js@3 によると、babel と将来の展望
caniuse
、mdn
およびcompat-table
は優れた教育リソースですが、実際には開発者ツールのデータ ソースとして使用することを意図したものではありません:compat-table
ES 関連のデータの適切なセットが含まれているだけで、@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.replace
targetと書かれていることです。これは私が行ったことがあるかもしれませんが、今のところは問題ありません。edge: 17
edge: 18
core-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-pure
。core-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-env
withが最適だと思います。useBuiltIns
グローバル名前空間を汚染することの欠点は何ですか? これはライブラリのみの問題ですか?
と組み合わせて@babel/transform-runtime
、オブジェクト スプレッドのポリフィルも取得します (ポリフィルの提案@babel-preset-env
が必要ですが、プラグインもcorejs: { version: '3.6', proposals: true }
使用しないとそこに取り込まれない理由がわかりません)。@babel/transform-runtime
Array#map ポリフィルは必要ですか?