Что, почему vite не может использовать новый синтаксис?

Vue.js Babel Vite

image.png

вы знаете?你在 vite 项目中写的高版本 ECMAScript 语法,可能是项目的隐患

задний план

Проект разработан на основе vite.В процессе разработки было использованоObject.fromeEntries

При открытии в браузере более ранней версии произошла следующая ошибка

image-20211107153010394

Проверьте vite.config.js и обнаружите, что там не используются странные плагины, сначала исключите проблему с файлом конфигурации.

Придерживаясь инженерной культуры стремления к максимуму, начните докапываться до сути проблемы.

проблема позиционирования

Прежде чем анализировать, почему, давайте взглянем на этот новый синтаксисObject.fromEntries

image-20211105193542344

Это новый синтаксис для ES2019, который уже является стабильной версией.

Совместимость с браузеромimage-20211105193600789

Браузер IE не поддерживает... ну слезы времени

Но об ошибке сообщает не браузер IE, а браузер 2345

企业微信截图_16361126115502

этодвухъядерный браузер, в режиме совместимости используется ядро ​​IE, а в скоростном режиме используется ядро ​​chrome. Убедитесь, что текущая версия является скоростным режимом

версия хрома в скоростном режиме 69, аObject.fromEntriesОн не поддерживался до chrome73, даже если это не ядро ​​IE, более низкая версия chrome сообщит об ошибке

Но обычно, чтобы быть совместимым с браузерами более ранних версий, инструмент сборки преобразует новый синтаксис в синтаксис, распознаваемый браузерами более ранних версий.

Когда браузер запущен, он существует в кодеObject.fromEntries, так что предварительно делается вывод, что vite построен не правильноObject.fromEntriesиметь дело с

При осмотре товара также можно обнаружить, что грамматика действительно сохранена

image-20211106220800426

Так как это вопрос здания, затем прошел через официальный сайт Vite, вГлавы сборкинашел бровиimage-20211106232625048

Красное поле говорит, что vite будет выполнять только перевод синтаксиса и не будет включать полифиллы, так что же такое полифиллы и перевод синтаксиса?

polyfills

Полифилы реализуют поведение синтаксиса более высоких версий, имитируя эквивалентный код в браузерах более ранних версий.

Возьмите эту статьюObject.fromEntriesНапример, его код полифилла выглядит следующим образом

Object.fromEntries = Object.fromEntries || function fromEntries (iterable) {
  return [...iterable].reduce((obj, [key, val]) => {
    obj[key] = val
    return obj
  }, {})
}

Перед выполнением кода проекта сначала загрузите соответствующий код полифиллов, а затемObject.fromEntriesэто работает отлично

core-js

Основная библиотека полифиловcore-js, который классифицирует последний синтаксис ECMAScript с точки зрения версии или типа, чтобы разработчики могли лучше представить их по мере необходимости.

image-20211107104343018

image-20211107104308778

@babel/preset-env

Кроме того, существуют плагины верхнего уровня, основанные на инкапсуляции core-js.@babel/preset-env

image-20211107104850602

Управляйте размером кода полифилов, объявляя версию браузера в файле (.browserslist) и устанавливая минимальную совместимую версию синтаксиса, чтобы избежать создания слишком большого количества ненужных полифиллов.

polyfill.io

Будь то core-js или @babel/preset-env, код полифиллов генерируется во время сборки, другими словами, они хранятся в локальном продукте в виде js-файлов.

Все они имеют недостаток, хотя объем полифилов можно оптимизировать во время сборки с помощью конфигурации, но дальнейшая оптимизация не может быть выполнена после создания.

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

И при доступе к последней версии Chrome он также загружает тот же код. Но для хрома на данный момент, поскольку ядро ​​уже поддерживает новый синтаксис, этот полифил не нужен. Загрузка в это время, несомненно, является пустой тратой ресурсов, а также может повлиять на экранное время (FP)

Есть ли способ динамически загружать полифиллы во время выполнения браузера? Ответ указан на официальном сайте vite.polyfill.io

image-20211107110636122

Чтобы использовать polyfill.io, вам нужно сначала установить самую высокую версию синтаксиса, чтобы получить URL-адрес.

image-20211107111232132

Когда браузер посещает URL-адрес, динамически возвращайте полифиллы, подходящие для текущего браузера.

  • браузер с низкой версией

image-20211104172912390

  • высококлассный браузер

,

Можно обнаружить, что для одного и того же URL-адреса результаты, возвращаемые браузерами младшей и старшей версии, различаются.

Но polyfill.io тоже не идеален

  • Необходимо запрашивать сторонний URL.В связи с тем, что полифиллы должны выполняться перед всеми бизнес-кодами, при колебаниях во внешней сети последующий код может быть заблокирован, что приводит к более длинному белому экрану (что может решить путем приватизации)
  • User-agent отечественных браузеров может быть неточно идентифицирован (на примере двухъядерного браузера 2345, а некоторые частичные браузеры могут иметь скрытые опасности)

Какой метод полифиллов использовать, зависит от проекта, так называемой серебряной пули не существует.

  • Если вы не чувствительны к объему продукта, вы можете рассмотреть возможность использования предварительно созданных полифиллов.
  • Если целевой браузер может конвергировать и имеет возможность частного развертывания, рассмотрите возможность использования версии полифиллов во время выполнения.

Сказав так много полифилов, давайте взглянем на перевод грамматики.

грамматический перевод

Для некоторых новых грамматик одни только полифиллы невозможны, например

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

Таким образом, этот тип грамматики может быть переведен только через грамматику, и он вернет код, который браузер более низкой версии может запускать во время построения.

// 源码
const a = 0
console.log(a ?? 10)
​
// 产物
var a = 0;
console.log(a !== null && a !== void 0 ? a : 10);

Текущие основные инструменты перевода:babel(да, помимо полифиллов поддерживает и трансляцию грамматики), за счет интеграции с инструментами сборки среда разработки может использовать новую грамматику из коробки, принцип реализации следующий

  1. При построении разбирается лексическим анализом какабстрактное синтаксическое дерево

image-20211107150013075

  1. Затем преобразуйте абстрактное синтаксическое дерево в абстрактное синтаксическое дерево, совместимое с браузерами более ранних версий.
  1. Просто используйте новое абстрактное синтаксическое дерево для создания кода js более низкой версии.

Конечный продукт также не будет содержать нового синтаксиса, поэтому все браузеры будут работать безупречно.

разница

Итак, в каких грамматиках используется полифилл, а в каких — грамматический перевод? подытожу несколько моментов

  • Реализованный API можно смоделировать в любой версии браузера с помощью полифилла.
  • Для лексических аспектов, таких как новые ключевые слова (async/const/|>/??), используйте перевод синтаксиса.
  • Используйте полифилл для всего, что можно реализовать с помощью полифилла, и переводите с помощью синтаксиса для того, что невозможно реализовать.

несколько других примеров

polyfills

  • String.prototype.matchAll
  • Number.isNaN
  • Map/Set

грамматический перевод

  • стрелочная функция
  • const/let
  • async/await

Поддержка Vite для полифиллов

Я потратил много времени, говоря о связи между полифиллами и переводом грамматики.Возвращаясь к самой проблеме, в официальном документе четко упоминается, что vite не будет добавлять полифиллы.

при использованииvue-cliавтоматически добавит полифиллы

image-20211107152203739

Запутался по этому поводу, спросил у разработчиков vite

image-20211107154856032

image.png

Он сказал, что vite для современных браузеров (это на самом деле не правильно, он тоже добавил позже, современные браузеры тоже нуждаются в полифиллах), а учитывая объем продукта, встроенных полифилов нет

Он также рекомендовал@vitejs/plugin-legacy Плагин, который может добавить поддержку полифиллов для vite

Или используйте полифиллы времени выполнения, упомянутые выше. Какой из них выбрать, зависит от анализа объема продукта и эталона первого экрана перед принятием решения.

В любом случае, проблема наконец была найдена, и соответствующее решение было найдено, и задача была выполнена.

Суммировать

  • vite 默认不会添加任何 polyfills,没有特殊处理时,务必避免写需要被 polyfill 的新语法,否则会导致低版本浏览器报错
  • Браузер более низкой версии не является браузером IE, но также включает браузер Chrome более низкой версии.
  • Для того, чтобы все пользователи корректно работали с новым синтаксисом в проекте, рекомендуется добавлять полифиллы отдельно
  • можно использовать@vitejs/plugin-legacy илиpolyfill.ioДобавить полифиллы для проектов Vite

В этой статье рассказывается о проблемах, возникающих в проекте vite, методе основных полифилов, babel и методе решения проблемы, что очень полезно для меня.

использованная литература

Polyfills and transpilers

What is the difference between Polyfilling and Transpiling?