Одна статья, чтобы разобраться с интерфейсным полифиллом

Babel

Polyfill в переводе с английского означает «прокладка», что означает что-то на дне кармана. В компьютерных науках относится к выполнению «под капотом» на стороне клиента, которое не было реализовано. Патчи во фронтенде - обычное дело, в сочетании с ежедневным опытом работы автора, суммировал 3 вида методов патчинга. включает в себя@babel/preset-env,@babel/polyfill,@babel/transform-runtime,@babel/runtimeтак же какcore-js. Правом следует пользоваться как ориентиром, и если будут какие-то ошибки, я не буду просить вас просветить меня.

В целом, существует три основных метода исправления ошибок:

  1. патч вручную
  2. Автоматическое исправление в зависимости от покрытия
  3. Динамическое исправление на основе характеристик браузера

Эти три метода могут учиться друг у друга и комбинироваться для создания исправлений, необходимых бизнесу. Вводится отдельно:

патч вручную

В каменном веке мы вручную импортировали нужные патчи, взяв за пример ES6 object#assign, даже в IE 11 он все равно сообщает об ошибке

Object assign报错

Поэтому нам нужно применить соответствующий патч. Вы можете использовать сторонний зрелый пакет или использовать шаблон, предоставленный MDN для исправления:

Object.assign = require('object-assign')
// or

// Refer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
if (typeof Object.assign != 'function') {
  // Must be writable: true, enumerable: false, configurable: true
  Object.defineProperty(Object, 'assign', {
    value: function assign(target, varArgs) {
      // .length of function is 2
      'use strict'
      if (target == null) {
        // TypeError if undefined or null
        throw new TypeError('Cannot convert undefined or null to object')
      }

      var to = Object(target)

      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index]

        if (nextSource != null) {
          // Skip over if undefined or null
          for (var nextKey in nextSource) {
            // Avoid bugs when hasOwnProperty is shadowed
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey]
            }
          }
        }
      }
      return to
    },
    writable: true,
    configurable: true,
  })
}

Проблема решена, но плюсы и минусы тоже вполне очевидны: плюс в том, что введение сведено к минимуму, не будет дополнительных накладных расходов на избыточный код, а работоспособность приложения гарантирована. Недостатком является то, что ручной импорт не прост в управлении и обслуживании, а стоимость обслуживания различных полифиллов и изменяющихся веб-приложений относительно высока.

Автоматическое исправление в зависимости от покрытия

С помощью черной магии Webpack мы можем пропатчить более современным способом. Связанные зависимости:@babel/preset-env,@babel/plugin-transform-runtime,core-js,@babel/polyfill. Давайте представим их один за другим:

  1. @babel/preset-env- Компилировать по требованию и исправлять по требованию

    @babel/preset-env is a smart preset that allows you to use the latest JavaScript without needing to micromanage which syntax transforms (and optionally, browser polyfills) are needed by your target environment(s). This both makes your life easier and JavaScript bundles smaller!

    переведи это на@babel/preset-envОн будет скомпилирован и исправлен в соответствии с целевой средой. В частности, по параметруtargetsчтобы определить целевую среду, он по умолчанию компилируется в ES2015 и может быть настроен в соответствии с потребностями проекта:

      ...
      presets: [
        [
          '@babel/preset-env',
          {
            // 支持chrome 58+ 及 IE 11+
            targets: {
              chrome: '58',
              ie: '11',
            }
          },
        ],
      ]
      ...
    

    Параметры конкретных целей см.browserlist.

  2. core-jsСтандартная библиотека JavaScript

    core-jsЭто одна из реализаций стандартной библиотеки времени выполнения JavaScript, которая предоставляет реализации JavaScript от ES3 до ES7+ и все еще находится на стадии предложения.

  3. @babel/plugin-transform-runtime- плагин babel, который повторно использует вспомогательные методы Babel

    A plugin that enables the re-use of Babel's injected helper code to save on codesize.

    @babel/plugin-transform-runtimeЭто повторное использование (объединение) вспомогательных методов, сгенерированных в процессе компиляции Babel, для уменьшения размера пакета. Кроме того, он также имеет эффект предоставления исправлений «песочницы» для упакованного упаковщика, чтобы избежать глобального загрязнения исправлениями.

  4. @babel/polyfill- Библиотека реализации для патчей core-js и regenerator-runtime.

    Babel includes a polyfill that includes a custom regenerator runtime and core-js.

    This will emulate a full ES2015+ environment (no < Stage 4 proposals) and is intended to be used in an application rather than a library/tool. (this polyfill is automatically loaded when using babel-node)

    @babel/polyfillпо индивидуальному заказуpolyfillа такжеregenerator, который предоставляет среду ES2015+polyfillбиблиотека. Поскольку она реализована двумя другими библиотеками, ее можно напрямую импортировать в две другие библиотеки, поэтому она была **заброшенный**.

    // 实现 @babel/polyfill 等同效果
    import 'core-js/stable'
    import 'regenerator-runtime/runtime'
    

инструкции

В соответствии с различными целями строительства автор считает, что должно быть два метода исправления:Исправление примененоа такжеБиблиотека патчей:

Применен патч - используйте@babel/preset-env + useBuiltIns

теперь, когдаcore-jsВключена вся стандартная библиотека JavaScript, так есть ли способ автоматически получать исправления на основе цели совместимости приложения? используется здесь@babel/preset-envизuseBuiltInsпараметры.useBuiltInsсказал@babel/preset-envКак обрабатывать на основе совместимых целей вашего приложенияpolyfill.

Во-первых, ввести в записи приложенияcore-js:

import 'core-js'

Затем настройтеuseBuiltInsПараметрыentry, и укажите версию core-js:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": 3
      }
    ],
    "@babel/preset-react"
  ]
}

Примеры кода см.babel-preset-env-1: Результат после упаковки:

polyfill-output-1

По умолчанию он преобразует весь код ECMAScript 2015+. Если этого не требует бизнес, следует указать среду браузера, которую должно поддерживать приложение, чтобы избежать ненужных исправлений и уменьшить объем упакованного вывода. Поддерживающая среда может бытьtargetsпараметры для указания, его синтаксис может относиться кbrowserslistчтобы подтвердить. Метод использования также очень прост, если предположить, что приложение должно поддерживать только Chrome 58:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": 3,
        "targets": {
          "chrome": 58
        }
      }
    ],
    "@babel/preset-react"
  ]
}

Видно, что упакованный объем значительно меньше:

polyfill-output-2

Если в приложении представлено несколько сторонних библиотек, и у них есть общие вспомогательные методы, их следует ввести@babel/plugin-transform-runtimeдля уменьшения размера упаковки. Метод использования не будет повторяться, вы можете обратиться кДокументация.

также,@babel/preset-envЗначение useBuiltIns также имеет экспериментальное значение.usage, его функция состоит в том, чтобы вводить соответствующие исправления в соответствии с исправлениями, требуемыми для разных файлов, что может в определенной степени уменьшить количество ненужных исправлений. Ссылаться наusebuiltins-usage-experimental.

Выше приведен метод исправления приложения в соответствии с коэффициентом покрытия, кратко изложенный:

  1. Представлено в записи приложенияcore-js

    import 'core-js'
    
  2. использовать@babel/preset-env, указавuseBuiltIns,core-jsи определяется приложениемtargets

    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "useBuiltIns": "entry",
            "corejs": 3,
            "targets": {
              "chrome": 58
            }
          }
        ],
        "@babel/preset-react"
      ]
    }
    
  3. Если в проекте представлено несколько сторонних библиотек, содержащих общедоступные вспомогательные методы, импортируйте@babel/plugin-transform-runtimeМетоды повторного использования для уменьшения размера упаковки.

Патчи для библиотеки — предоставляйте только проприетарные патчи, от которых зависит библиотека.

Поскольку библиотека импортируется приложением, она сама по себе не должна предоставлять такие вещи, какPromise,MapТакие часто используемые исправления должны предоставляться самим приложением, а сама библиотека должна импортировать только свою собственную библиотеку.

Например, если я хочу создать компонент выбора даты, поддерживающий несколько языков, я должен ввести полифиллы, реализованные на нескольких языках, напримерIntl.

Динамическое исправление на основе характеристик браузера

У обоих вышеперечисленных способов есть недостаток — избыточность патчей. кObject#assignДругими словами, для браузеров, поддерживающих эту функцию, нет необходимости вводить это исправление, которое неизбежно приведет к определенной избыточности исправлений, поэтому существует динамическая схема исправления, основанная на характеристиках браузера.

Polyfill.io Именно сервис реализует это решение и будет возвращать разные патчи в зависимости от UA браузера. Если хочешьPromiseПатч, представленный на странице:

<script src="https://polyfill.io/v3/polyfill.js?features=Promise"></script>

Например, в более поздней версии браузера (Chrome 75) открытие ссылки возвращает пустую страницу:

/* Polyfill service v3.34.0
 * For detailed credits and licence information see https://github.com/financial-times/polyfill-service.
 *
 * Features requested: Promise
 *  */

/* No polyfills found for current settings */

Если вы измените UA браузера на IE 11, он вернет соответствующийpolyfill:

Вы также можете добавить параметры запроса для настройки Polyfill. Подробную информацию см. на официальном сайте.Документация.

Кроме того, если есть требования к стабильности и безопасности Polyfill.io, вы можетеpolyfill serviceСоздайте свой собственный сервис и разверните его в CDN.

будущее

Исходя из текущего плана, автор считает, чтоИсправления функций по запросу + онлайн патчЭто идеальное решение для будущего. Функции по требованию могут относиться кuseBuiltInsизusageРеализация параметра - вносить нужные патчи только в текущий файл и только один раз. Использование онлайн-патчаpolyfill service, их комбинация гарантирует, что исправление вводится минимально, и разные исправления будут применяться в зависимости от разных устройств.

над.