Я получаю разные выходные данные для разных конфигураций @babel/preset-env
с useBuiltIns
, используемым в сочетании с @babel/transform-runtime
. Я прочитал документацию, но не смог понять, какой должна быть лучшая практика.
Например, @babel/preset-env
с useBuiltIns
добавит полифилл для string.replace
, когда моя цель список браузеров включает Edge 18.
Но когда я использую @babel/transform-runtime
, этот полифилл не добавляется.
Итак, начнем с этого вопроса:
Does `string.replace` need to be polyfilled for Edge 18?
caniuse
, mdn
и compat-table
- хорошие образовательные ресурсы, но на самом деле не предназначены для использования в качестве источников данных для инструментов разработчика: только compat-table
содержит хороший набор данных, связанных с ES и он используется @ babel / preset-env, но имеет некоторые ограничения
И еще:
По этой причине я создал пакет core-js-compat
: it предоставляет данные о необходимости модулей core- js для различных целевых двигателей. При использовании core-js@3
, @babel/preset-env
будет использовать этот новый пакет вместо compat-table.
Итак, я передал целевые браузеры в core-js-compat
, и он выдает все требуемые поля. Как вы можете видеть на изображении ниже, довольно много строковых методов необходимо полифиллировать, в основном для поддержки Edge 18.
So far, so good. It looks like string.replace
does need to be polyfilled for Edge 18.
Babel config
First approach: @babel/preset-env
and useBuiltIns: 'usage'
When I use useBuiltIns: 'usage'
to bring in per-file polyfills from 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" }
Единственное отличие в том, что es.string.replace
предназначен для 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;
Опять пока все хорошо.
Второй подход: @babel/runtime
и @babel/transform-runtime
Согласно документации core- js:
@babel/runtime
с corejs: 3
опция упрощает работу с core-js-pure
. Он автоматически заменяет использование современных функций из стандартной библиотеки JS на импорт из версии core-js
без глобального загрязнения пространства имен
Звучит отлично - давайте попробуем!
Комментарии out 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) Set corejs
for @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
:
- так же, как второй подход (см. Выше)
Сравнение вывода для различных подходов
Использование только useBuiltIns
:
- Добавляет требуемые строковые полифилы, но загрязняет глобальное пространство имен.
Использование только @babel/runtime-transform
:
- Не добавляет строковых полифилов, но добавляет другие помощники / полифиллы ??, для карты массива и распространения объекта
Использование комбинации useBuiltIns
и @babel/transform-runtime
:
- Добавляет требуемые строковые полифилы, но загрязняет глобальное пространство имен.
- Также добавляет полифилы разброса объектов (но не полифил карты массива)
- Импорт из
@babel/runtime/helpers/objectSpread2
, а не @babel/runtime-corejs3/helpers/objectSpread2
(время выполнения против runtime-corejs3) - может быть причиной того, что полифил карты массива не был добавлен ??)
Вопрос
Какой из них - если таковой имеется - является правильным?
Я предполагаю, что @babel/preset-env
с useBuiltIns
- лучший вариант, потому что он вносит полифиллы.
Каковы недостатки загрязнения глобального пространства имен? Это проблема только для библиотек?
В сочетании с @babel/transform-runtime
мы также получаем полифилл для распространения объекта (хотя @babel-preset-env
имеет corejs: { version: '3.6', proposals: true }
, который должен заполнять предложения, поэтому я не уверен почему он не попадает туда без использования плагина @babel/transform-runtime
)
Нужен ли нам полифилл Array # map?