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

browserslist

Вы заметите поле browserslist в файле package.json (или файл .browserslistrc), где определяется диапазон браузеров под которые разрабатывается проект. Эти значения будут использоваться в @babel/preset-env и autoprefixer для автоматического определения возможностей JavaScript, которые требуется транспилировать, а также необходимые префиксные правила CSS.

Как указывается диапазон браузеров можно узнать здесь.

Полифилы

По умолчанию, проект Vue CLI использует @vue/babel-preset-app, в котором используется @babel/preset-env и конфигурация browserslist для определения необходимых полифилов.

useBuiltIns: 'usage'

По умолчанию в @babel/preset-env будет передаваться useBuiltIns: 'usage' для автоматического определения необходимых полифилов, основываясь на том, какие возможности языка были использованы в исходном коде проекта. Это гарантирует, что в финальную сборку попадёт только минимально необходимое количество полифилов. Однако, это также означает, что если одна из ваших зависимостей имеет специфичные требования к полифилам, то по умолчанию Babel не сможет это определить.

Если одной из ваших зависимостей требуются полифилы, у вас есть несколько вариантов:

  1. Если зависимость написана в версии ES, которую не поддерживают целевые окружения: Добавьте эту зависимость в опцию transpileDependencies в файле vue.config.js. Это позволит использовать как синтаксические преобразования, так и определение полифилов для используемых возможностей для этой зависимости.

  2. Если зависимость предоставляет ES5 код и явно перечисляет необходимые полифилы: вы можете предварительно включить необходимые полифилы с помощью опции polyfills для @vue/babel-preset-app. Обратите внимание, что es6.promise добавлен по умолчанию, так как он часто необходим для библиотек, основанных на Promise.

    // babel.config.js
    module.exports = {
      presets: [
        ['@vue/app', {
          polyfills: [
            'es6.promise',
            'es6.symbol'
          ]
        }]
      ]
    }
    

    Совет

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

  3. Если зависимость предоставляет ES5 код, но использует возможности ES6+ без явного перечисления необходимых полифилов (например, Vuetify): Используйте useBuiltIns: 'entry' и затем добавьте import '@babel/polyfill' в файл точки входа. Это будет импортировать ВСЕ полифилы, на основе целей, перечисленных в browserslist, так что вам больше не нужно будет беспокоиться о полифилах для зависимостей, но это скорее всего увеличит размер финальной сборки некоторыми неиспользуемыми полифилами.

Подробнее можно изучить в документации @babel-preset/env.

Полифилы при сборки библиотеки или веб-компонентов

При использовании Vue CLI для сборки библиотеки или веб-компонентов, рекомендуется указывать useBuiltIns: false для @vue/babel-preset-app чтобы отключить автоматическое добавление полифилов. Это гарантирует, что вы не добавляете ненужные полифилы в свой код, потому что полифилами должно будет заниматься приложение, где они будут использоваться.

Современный режим

Благодаря Babel мы можем использовать все новейшие возможности языка ES2015+, но это также означает, что нам необходимо предоставлять транспилированную сборку с полифилами для поддержки старых браузеров. Эти транспилированные сборки зачастую больше в размере, чем оригинальный исходный код в ES2015+, а их парсинг и выполнение происходит медленнее. Учитывая, что сегодня у большинства современных браузеров есть прекрасная поддержка ES2015, становится пустой тратой необходимость предоставлять более тяжёлый и менее эффективный код для них лишь потому что должны поддерживать старые версии браузеров.

Vue CLI предоставляет «Современный режим», чтобы помочь в решении этой проблемы. При сборке для production с помощью следующей команды:

vue-cli-service build --modern

Vue CLI будет собирать две версии вашего приложения: первая сборка для современных браузеров, которые поддерживают ES-модули, а вторая сборка для старых браузеров, которые не имеют такой поддержки.

Приятная часть заключается в том, что ничего специально делать при публикации не требуется. Сгенерированный HTML-файл автоматически использует технику, описанную в классном посте Филлипа Уолтона:

  • Современная сборка загружается с помощью <script type="module"> в браузерах, которые поддерживают модули; они также предзагружаются через <link rel="modulepreload">.

  • Сборка для старых браузеров загружается с помощью тега <script nomodule>, который игнорируется браузерами, поддерживающими ES-модули.

  • Исправление ошибки для <script nomodule> в Safari 10 также внедряется автоматически.

Для приложения Hello World, современная сборка на 16% меньше. В production использование современной сборки приводит к значительному ускорению парсинга и исполнения кода, что повышает производительность загрузки приложения.

Совет

<script type="module"> загружаются всегда с помощью CORS. Это значит, что ваш сервер должен возвращать корректные заголовки CORS, такие как Access-Control-Allow-Origin: *. Если вы хотите загружать скрипты с помощью credentials, установите опцию crossorigin в значение use-credentials.

Кроме того, современный режим использует инлайновый скрипт для избежания загрузки обеих сборок в Safari 10, поэтому, если вы используете строгие политики CSP, необходимо явно разрешить инлайновый скрипт с помощью:

Content-Security-Policy: script-src 'self' 'sha256-4RS22DYeB7U14dra4KcQYxmwt5HkOInieXK1NUMBmQI='

Определение текущего режима в конфигурации

Иногда может потребоваться изменить конфигурацию webpack только сборки для старых браузеров или только сборки для современных браузеров.

Vue CLI использует две переменных окружения для определения этого:

  • VUE_CLI_MODERN_MODE: флаг, что сборка была запущена с флагом --modern
  • VUE_CLI_MODERN_BUILD: значением true будет если текущая конфигурация для современной сборки. В противном случае это сборка для старых браузеров.

Важно: Переменные доступны только при вызове/после вызова функций chainWebpack() и configureWebpack(), (т.е. не напрямую в области видимости модуля vue.config.js). Это также означает, что они доступны в файле конфигурации postcss.