Как лучше всего использовать `@ babel / preset-env` +` useBuiltIns` + `@ babel / runtime` +` browserslistrc` - PullRequest
2 голосов
/ 03 августа 2020

Я получаю разные выходные данные для разных конфигураций @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.com , который показывает, что он полностью поддерживается - что означает, что полифиллы не требуется.

  • Однако, согласно сообщению в блоге Мануэля Бодру, core-js@3, babel и взгляд в будущее

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.

enter image description here

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.*. Они больше не нужны? Их уже привели «помощники»? Не похоже, что разброс объектов и карта массива будут иметь какое-либо отношение к методам экземпляра строки полифиллинга, так что я думаю, что нет.

Наконец

Моя последняя попытка состояла в том, чтобы объединить оба подхода - и следовать рекомендациям :

enter image description here

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?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...