вы знаете?你在 vite 项目中写的高版本 ECMAScript 语法,可能是项目的隐患
задний план
Проект разработан на основе vite.В процессе разработки было использованоObject.fromeEntries
При открытии в браузере более ранней версии произошла следующая ошибка
Проверьте vite.config.js и обнаружите, что там не используются странные плагины, сначала исключите проблему с файлом конфигурации.
Придерживаясь инженерной культуры стремления к максимуму, начните докапываться до сути проблемы.
проблема позиционирования
Прежде чем анализировать, почему, давайте взглянем на этот новый синтаксисObject.fromEntries
Это новый синтаксис для ES2019, который уже является стабильной версией.
Совместимость с браузером
Браузер IE не поддерживает... ну слезы времени
Но об ошибке сообщает не браузер IE, а браузер 2345
этодвухъядерный браузер, в режиме совместимости используется ядро IE, а в скоростном режиме используется ядро chrome. Убедитесь, что текущая версия является скоростным режимом
версия хрома в скоростном режиме 69, аObject.fromEntries
Он не поддерживался до chrome73, даже если это не ядро IE, более низкая версия chrome сообщит об ошибке
Но обычно, чтобы быть совместимым с браузерами более ранних версий, инструмент сборки преобразует новый синтаксис в синтаксис, распознаваемый браузерами более ранних версий.
Когда браузер запущен, он существует в кодеObject.fromEntries
, так что предварительно делается вывод, что vite построен не правильноObject.fromEntries
иметь дело с
При осмотре товара также можно обнаружить, что грамматика действительно сохранена
Так как это вопрос здания, затем прошел через официальный сайт Vite, вГлавы сборкинашел брови
Красное поле говорит, что 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 с точки зрения версии или типа, чтобы разработчики могли лучше представить их по мере необходимости.
@babel/preset-env
Кроме того, существуют плагины верхнего уровня, основанные на инкапсуляции core-js.@babel/preset-env
Управляйте размером кода полифилов, объявляя версию браузера в файле (.browserslist) и устанавливая минимальную совместимую версию синтаксиса, чтобы избежать создания слишком большого количества ненужных полифиллов.
polyfill.io
Будь то core-js или @babel/preset-env, код полифиллов генерируется во время сборки, другими словами, они хранятся в локальном продукте в виде js-файлов.
Все они имеют недостаток, хотя объем полифилов можно оптимизировать во время сборки с помощью конфигурации, но дальнейшая оптимизация не может быть выполнена после создания.
Например, когда я обращаюсь к браузеру ниже, чем chrome73, он загружает код полифиллов, сгенерированный во время сборки.
И при доступе к последней версии Chrome он также загружает тот же код. Но для хрома на данный момент, поскольку ядро уже поддерживает новый синтаксис, этот полифил не нужен. Загрузка в это время, несомненно, является пустой тратой ресурсов, а также может повлиять на экранное время (FP)
Есть ли способ динамически загружать полифиллы во время выполнения браузера? Ответ указан на официальном сайте vite.polyfill.io
Чтобы использовать polyfill.io, вам нужно сначала установить самую высокую версию синтаксиса, чтобы получить URL-адрес.
Когда браузер посещает URL-адрес, динамически возвращайте полифиллы, подходящие для текущего браузера.
- браузер с низкой версией
- высококлассный браузер
Можно обнаружить, что для одного и того же URL-адреса результаты, возвращаемые браузерами младшей и старшей версии, различаются.
Но polyfill.io тоже не идеален
- Необходимо запрашивать сторонний URL.В связи с тем, что полифиллы должны выполняться перед всеми бизнес-кодами, при колебаниях во внешней сети последующий код может быть заблокирован, что приводит к более длинному белому экрану (что может решить путем приватизации)
- User-agent отечественных браузеров может быть неточно идентифицирован (на примере двухъядерного браузера 2345, а некоторые частичные браузеры могут иметь скрытые опасности)
Какой метод полифиллов использовать, зависит от проекта, так называемой серебряной пули не существует.
- Если вы не чувствительны к объему продукта, вы можете рассмотреть возможность использования предварительно созданных полифиллов.
- Если целевой браузер может конвергировать и имеет возможность частного развертывания, рассмотрите возможность использования версии полифиллов во время выполнения.
Сказав так много полифилов, давайте взглянем на перевод грамматики.
грамматический перевод
Для некоторых новых грамматик одни только полифиллы невозможны, например
- optional-chaining ( a?.b )
- nullish-coalescing-operator ( a ?? 10 )
- logical-assignment-operators ( a ||= 10 )
Аналогичный новый синтаксис, из-за того, что он опирается на лексический анализ ядра браузера, браузеры более ранних версий не могут быть решены в виде исправлений.
Таким образом, этот тип грамматики может быть переведен только через грамматику, и он вернет код, который браузер более низкой версии может запускать во время построения.
// 源码
const a = 0
console.log(a ?? 10)
// 产物
var a = 0;
console.log(a !== null && a !== void 0 ? a : 10);
Текущие основные инструменты перевода:babel(да, помимо полифиллов поддерживает и трансляцию грамматики), за счет интеграции с инструментами сборки среда разработки может использовать новую грамматику из коробки, принцип реализации следующий
- При построении разбирается лексическим анализом какабстрактное синтаксическое дерево
- Затем преобразуйте абстрактное синтаксическое дерево в абстрактное синтаксическое дерево, совместимое с браузерами более ранних версий.
- Просто используйте новое абстрактное синтаксическое дерево для создания кода js более низкой версии.
Конечный продукт также не будет содержать нового синтаксиса, поэтому все браузеры будут работать безупречно.
разница
Итак, в каких грамматиках используется полифилл, а в каких — грамматический перевод? подытожу несколько моментов
- Реализованный API можно смоделировать в любой версии браузера с помощью полифилла.
- Для лексических аспектов, таких как новые ключевые слова (async/const/|>/??), используйте перевод синтаксиса.
- Используйте полифилл для всего, что можно реализовать с помощью полифилла, и переводите с помощью синтаксиса для того, что невозможно реализовать.
несколько других примеров
polyfills
- String.prototype.matchAll
- Number.isNaN
- Map/Set
грамматический перевод
- стрелочная функция
- const/let
- async/await
Поддержка Vite для полифиллов
Я потратил много времени, говоря о связи между полифиллами и переводом грамматики.Возвращаясь к самой проблеме, в официальном документе четко упоминается, что vite не будет добавлять полифиллы.
при использованииvue-cliавтоматически добавит полифиллы
Запутался по этому поводу, спросил у разработчиков vite
Он сказал, что vite для современных браузеров (это на самом деле не правильно, он тоже добавил позже, современные браузеры тоже нуждаются в полифиллах), а учитывая объем продукта, встроенных полифилов нет
Он также рекомендовал@vitejs/plugin-legacy Плагин, который может добавить поддержку полифиллов для vite
Или используйте полифиллы времени выполнения, упомянутые выше. Какой из них выбрать, зависит от анализа объема продукта и эталона первого экрана перед принятием решения.
В любом случае, проблема наконец была найдена, и соответствующее решение было найдено, и задача была выполнена.
Суммировать
vite 默认不会添加任何 polyfills,没有特殊处理时,务必避免写需要被 polyfill 的新语法,否则会导致低版本浏览器报错
- Браузер более низкой версии не является браузером IE, но также включает браузер Chrome более низкой версии.
- Для того, чтобы все пользователи корректно работали с новым синтаксисом в проекте, рекомендуется добавлять полифиллы отдельно
- можно использовать@vitejs/plugin-legacy илиpolyfill.ioДобавить полифиллы для проектов Vite
В этой статье рассказывается о проблемах, возникающих в проекте vite, методе основных полифилов, babel и методе решения проблемы, что очень полезно для меня.