Babel polyfill что это
Перейти к содержимому

Babel polyfill что это

  • автор:

Загружаем babel-polyfill только для старых браузеров на примере vue.js

Это сервис, который на основании юзер-агента определяет какие полифиллы нужно загружать.

Попросту в index.html добавляем:

script src pl-s">https://cdn.polyfill.io/v2/polyfill.min.js?features=es6">script>

Правда тогда отдельные полифиллы будут загружаться даже для свежих версий хрома/фф. Решение — используем атрибут nomodule. Современные браузеры не будут загружать скрипт с этим атрибутом:

script src pl-s">https://cdn.polyfill.io/v2/polyfill.min.js?features=es6" nomodule>script>

Однако у polyfill.io есть и минусы: плохие полифиллы, не гарантирующие полную совместимость. По крайней мере так пишет автор core-js.

2. Поэтому загружаем babel-polyfill

Тоже используем nomodule , чтобы грузить только на старых браузерах:

script src pl-s">https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.min.js" nomodule>script>

3. Альтернатива: как раньше импортируем babel-polyfill в коде

Но делаем как советуют в гайде по vue-cli.

module.exports =  presets: [ ['@vue/app',  "useBuiltIns": "entry" >] ], >;

В начало main.js добавляем (не забыв сделать npm install @babel/polyfill ):

import '@babel/polyfill';

В этом случае в бандл добавятся не все полифиллы, а только встречающиеся в коде и сооветствующие browserlist.

При этом сократить бандл для современных браузеров можно при помощи modern mode. Правда даже в этом случае часть полифиллов будет добавлена для современных браузеров. Возможно это особенность browserlist, а может и действительно они им нужны, не знаю.

Вопрос №48379 от пользователя Алексей Черняев в уроке «Полифиллы», курс «JS: DOM API»

Не понял, для чего используют core-js. Babel не является альтернативой?

Алексей Черняев, добрый день. Бабель — транспилятор. То есть, он только берет код и превращает его в тот, который вы от него просите. Полифиллы — непосредственно код, который добавляет новый функционал туда, где он не поддерживается. И бабель, начиная с 7 версии, не берет на себя задачу добавления полифилов. Он ими только пользуется, если они будут предоставлены. Поэтому надо использовать бабель и core-js в связке

Александр Фуфаев, кажется, я нашёл это замечание . То есть раньше Babel самостоятельно добавлял полифиллы через @babel/polyfill, а теперь нужен core-js?

Алексей Черняев, именно так. Более того babel/polyfill — просто оболочка вокруг core-js + runtime-generator

Предоставляйте современный код современным браузерам для более быстрой загрузки страниц.

Оптимизируйте свои подборки Сохраняйте и классифицируйте контент в соответствии со своими настройками.

Хусейн Джирде

Чтобы следовать этой кодовой лаборатории, откройте этот глюк на второй вкладке. Примечание. В этой лаборатории кода используются Chrome DevTools. Загрузите Chrome, если у вас его еще нет.

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

Скриншот приложения

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

Мера

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

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

  1. Чтобы просмотреть сайт, нажмите «Просмотреть приложение» . Затем нажмите Полноэкранный режим .
  2. Нажмите «Control+Shift+J» (или «Command+Option+J» на Mac), чтобы открыть DevTools.
  3. Откройте вкладку «Сеть» .
  4. Установите флажок Отключить кеш .
  5. Перезагрузите приложение.

Запрос исходного размера пакета

Для этого приложения используется более 80 КБ! Пришло время узнать, не используются ли части пакета:

  1. Нажмите Control+Shift+P (или Command+Shift+P на Mac), чтобы открыть меню команд . Командное меню
  2. Введите Show Coverage и нажмите Enter , чтобы отобразить вкладку «Покрытие» .
  3. На вкладке «Покрытие» нажмите «Обновить» , чтобы перезагрузить приложение во время сбора данных о покрытии. Перезагрузите приложение с покрытием кода
  4. Посмотрите, сколько кода было использовано по сравнению с тем, сколько было загружено для основного пакета: Покрытие кода пакета

Более половины пакета (44 КБ) даже не используется. Это связано с тем, что большая часть кода состоит из полифилов, обеспечивающих работу приложения в старых браузерах.

Используйте @babel/preset-env

Синтаксис языка JavaScript соответствует стандарту, известному как ECMAScript или ECMA-262 . Новые версии спецификации выпускаются каждый год и включают новые функции, прошедшие процедуру предложения. Каждый основной браузер всегда находится на разном этапе поддержки этих функций.

В приложении используются следующие возможности ES2015:

  • Стрелочные функции
  • Литералы шаблонов
  • Для… цикла
  • Деструктуризация задания

Также используется следующая функция ES2017:

Не стесняйтесь погрузиться в исходный код в src/index.js , чтобы увидеть, как все это используется.

Все эти функции поддерживаются в последней версии Chrome, но как насчет других браузеров, которые их не поддерживают? Babel , включенная в приложение, — это самая популярная библиотека, используемая для компиляции кода, содержащего новый синтаксис, в код, понятный старым браузерам и средам. Это делается двумя способами:

  • Полифиллы включены для эмуляции новых функций ES2015+, чтобы их API можно было использовать, даже если они не поддерживаются браузером. Вот пример полифила метода Array.includes .
  • Плагины используются для преобразования кода ES2015 (или более поздней версии) в более старый синтаксис ES5. Поскольку это изменения, связанные с синтаксисом (например, функции стрелок), их нельзя эмулировать с помощью полифилов.

Посмотрите package.json чтобы узнать, какие библиотеки Babel включены:

"dependencies": < "@babel/polyfill": "^7.0.0" >, "devDependencies": < //. "babel-loader": "^8.0.2", "@babel/core": "^7.1.0", "@babel/preset-env": "^7.1.0", //. >
  • @babel/core — основной компилятор Babel. При этом все конфигурации Babel определяются в .babelrc в корне проекта.
  • babel-loader включает Babel в процесс сборки веб-пакета.

Теперь посмотрите на webpack.config.js , чтобы увидеть, как обычно включается babel-loader :

module: < rules: [ //. < test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" > ] >,
  • @babel/polyfill предоставляет все необходимые полифилы для любых новых функций ECMAScript, чтобы они могли работать в средах, которые их не поддерживают. Он уже импортирован в самом верху src/index.js.
import "./style.css"; import "@babel/polyfill"; 
  • @babel/preset-env определяет, какие преобразования и полифилы необходимы для любых браузеров или сред, выбранных в качестве целевых.

Взгляните на файл конфигурации Babel, .babelrc , чтобы узнать, как он включен:

Это установка Babel и веб-пакета. Узнайте, как включить Babel в свое приложение, если вы используете другой сборщик модулей, чем веб-пакет.

Атрибут targets в .babelrc определяет, какие браузеры являются мишенью. @babel/preset-env интегрируется со списком браузеров, а это значит, что вы можете найти полный список совместимых запросов, которые можно использовать в этом поле, в документации по списку браузеров .

Значение «last 2 versions» транспилирует код в приложении для двух последних версий каждого браузера.

Отладка

Чтобы получить полное представление обо всех целях Babel браузера, а также обо всех включенных преобразованиях и полифилах, добавьте поле debug в .babelrc:

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

Целевые браузеры

Babel записывает в консоль ряд подробностей о процессе компиляции, включая все целевые среды, для которых был скомпилирован код.

Целевые браузеры

Обратите внимание, что в этот список включены браузеры, выпуск которых прекращен, например Internet Explorer. Это проблема, поскольку в неподдерживаемые браузеры не будут добавлены новые функции, и Babel продолжает переносить для них определенный синтаксис. Это неоправданно увеличивает размер вашего пакета, если пользователи не используют этот браузер для доступа к вашему сайту.

Babel также записывает список используемых плагинов преобразования:

Список используемых плагинов

Это довольно длинный список! Это все плагины, которые необходимо использовать Babel для преобразования любого синтаксиса ES2015+ в более старый синтаксис для всех целевых браузеров.

Однако Babel не показывает какие-либо конкретные используемые полифилы:

Полифилы не добавлены

Это связано с тем, что весь @babel/polyfill импортируется напрямую.

Загружать полифилы по отдельности

По умолчанию Babel включает все полифилы, необходимые для полной среды ES2015+, когда @babel/polyfill импортируется в файл. Чтобы импортировать определенные полифилы, необходимые для целевых браузеров, добавьте в конфигурацию запись useBuiltIns: ‘entry’ .

Перезагрузите приложение. Теперь вы можете увидеть все включенные в него полифилы:

Хотя теперь включены только необходимые полифилы для «last 2 versions» , это по-прежнему очень длинный список! Это связано с тем, что полифилы, необходимые целевым браузерам для каждой новой функции, по-прежнему включены. Измените значение атрибута на usage , чтобы включать только те функции, которые используются в коде.

При этом полифилы автоматически включаются там, где это необходимо. Это означает, что вы можете удалить импорт @babel/polyfill в src/index.js.

import "./style.css"; import "@babel/polyfill"; 

Теперь включены только необходимые для приложения полифилы.

Список полифилов, включенных автоматически

Размер пакета приложений значительно уменьшен.

Размер пакета уменьшен до 30,1 КБ.

Сужение списка поддерживаемых браузеров

Число включенных целевых браузеров по-прежнему довольно велико, и немногие пользователи используют устаревшие браузеры, такие как Internet Explorer. Обновите конфигурации до следующего:

< "presets": [ [ "@babel/preset-env", < "targets": "last 2 versions", "targets": [">0.25%", "not ie 11"], "debug": true, "useBuiltIns": "usage", > ] ] > 

Взгляните на детали полученного комплекта.

Размер пакета 30,0 КБ.

Поскольку приложение настолько маленькое, эти изменения на самом деле не имеют большой разницы. Однако рекомендуется использовать процентную долю рынка браузеров (например, «>0.25%» и исключать определенные браузеры, которые, как вы уверены, не используют ваши пользователи. Чтобы узнать больше об этом, прочтите статью Джеймса Кайла «Последние 2 версии», которую считают вредной .

Используйте

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

Модули JavaScript — относительно новая функция, поддерживаемая во всех основных браузерах . Модули можно создавать с использованием атрибута type=»module» для определения сценариев, которые импортируют и экспортируют из других модулей. Например:

// math.mjs export const add = (x, y) => x + y;   

Многие новые функции ECMAScript уже поддерживаются в средах, поддерживающих модули JavaScript (вместо Babel). Это означает, что конфигурацию Babel можно изменить для отправки в браузер двух разных версий вашего приложения:

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

Использование модулей ES с Babel

Чтобы иметь отдельные настройки @babel/preset-env для двух версий приложения, удалите файл .babelrc . Настройки Babel можно добавить в конфигурацию веб-пакета, указав два разных формата компиляции для каждой версии приложения.

Начните с добавления конфигурации устаревшего скрипта в webpack.config.js :

const legacyConfig = < entry, output: < path: path.resolve(__dirname, "public"), filename: "[name].bundle.js" >, module: < rules: [ < test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: < presets: [ ["@babel/preset-env", < useBuiltIns: "usage", targets: < esmodules: false >>] ] > >, cssRule ] >, plugins > 

Обратите внимание, что вместо использования targets значения для «@babel/preset-env» вместо этого используются esmodules со значением false . Это означает, что Babel включает в себя все необходимые преобразования и полифилы для каждого браузера, который еще не поддерживает модули ES.

Добавьте объекты entry , cssRule и corePlugins в начало файла webpack.config.js . Все они используются как модулем, так и устаревшими сценариями, передаваемыми в браузер.

const entry = < main: "./src" >; const cssRule = < test: /\.css$/, use: ExtractTextPlugin.extract(< fallback: "style-loader", use: "css-loader" >) >; const plugins = [ new ExtractTextPlugin(), new HtmlWebpackPlugin() ]; 

Теперь аналогичным образом создайте объект конфигурации для сценария модуля ниже, где определен legacyConfig :

const moduleConfig = < entry, output: < path: path.resolve(__dirname, "public"), filename: "[name].mjs" >, module: < rules: [ < test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: < presets: [ ["@babel/preset-env", < useBuiltIns: "usage", targets: < esmodules: true >>] ] > >, cssRule ] >, plugins > 

Основное отличие здесь заключается в том, что для имени выходного файла используется расширение .mjs . Здесь для значения esmodules установлено значение true, что означает, что код, выводимый в этот модуль, представляет собой меньший по размеру и менее компилируемый сценарий, который не подвергается каким-либо преобразованиям в этом примере, поскольку все используемые функции уже поддерживаются в браузерах, поддерживающих модули.

В самом конце файла экспортируйте обе конфигурации в один массив.

module.exports = [ legacyConfig, moduleConfig ]; 

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

Браузеры, поддерживающие модули, игнорируют скрипты с атрибутом nomodule . И наоборот, браузеры, которые не поддерживают модули, игнорируют элементы сценария с type=»module» . Это означает, что вы можете включить как модуль, так и скомпилированный резервный вариант. В идеале две версии приложения должны находиться в index.html следующим образом:

Браузеры, поддерживающие модули, извлекают и выполняют main.mjs и игнорируют main.bundle.js. Браузеры, не поддерживающие модули, делают наоборот.

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

Последнее, что здесь нужно сделать, — это добавить атрибуты module и nomodule к модулю и устаревшему скрипту соответственно. Импортируйте ScriptExtHtmlWebpackPlugin в самый верх webpack.config.js :

const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin"); 

Теперь обновите массив plugins в конфигурациях, чтобы включить этот плагин:

const plugins = [ new ExtractTextPlugin(), new HtmlWebpackPlugin(), new ScriptExtHtmlWebpackPlugin(< module: /\.mjs$/, custom: [ < test: /\.js$/, attribute: 'nomodule', value: '' >, ] >) ];

Эти настройки плагина добавляют атрибут type=»module» для всех элементов сценария .mjs , а также атрибут nomodule для всех модулей сценария .js .

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

Обслуживание модулей в HTML-документе

Последнее, что нужно сделать, — это вывести как устаревшие, так и современные элементы сценария в HTML-файл. К сожалению, плагин HTMLWebpackPlugin , создающий окончательный HTML-файл, в настоящее время не поддерживает вывод скриптов модуля и nomodule. Хотя для решения этой проблемы существуют обходные пути и отдельные плагины, такие как BabelMultiTargetPlugin и HTMLWebpackMultiBuildPlugin , для целей данного руководства используется более простой подход — добавление элемента сценария модуля вручную.

Добавьте следующее в src/index.js в конце файла:

Теперь загрузите приложение в браузере, поддерживающем модули, например в последней версии Chrome.

Модуль размером 5,2 КБ, полученный по сети для новых браузеров

Извлекается только модуль с гораздо меньшим размером пакета, поскольку он практически не транспилируется! Другой элемент сценария полностью игнорируется браузером.

Если вы загружаете приложение в более старом браузере, будет загружен только более крупный транспилированный скрипт со всеми необходимыми полифилами и преобразованиями. Вот скриншот всех запросов, сделанных в более старой версии Chrome (версия 38).

Скрипт размером 30 КБ получен для старых браузеров.

Заключение

Теперь вы понимаете, как использовать @babel/preset-env для предоставления только необходимых полифилов, необходимых для целевых браузеров. Вы также знаете, как модули JavaScript могут еще больше повысить производительность, предоставляя две разные транспилированные версии приложения. Имея хорошее представление о том, как оба эти метода могут значительно сократить размер вашего пакета, приступайте к оптимизации!

Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons «С указанием авторства 4.0», а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.

Последнее обновление: 2018-12-12 UTC.

Оптимизация кода под старые браузеры

В package.json нужно добавить после «license»: «ISC» :

"license": "ISC", "browserslist": [ ">1%" ], 

В файл webpack.config.js необходимо добавить в раздел module :

rules: [  test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use:  loader: 'babel-loader', options:  presets: [['@babel/preset-env',  debug: true, corejs: 3, useBuiltIns: "usage" >]] > > > ] 

test – регулярное выражение для поиска файлов которые необходимо перобразовать

corejs – сообщяем о необходимости библиотеки corejs. useBuiltIns: «usage» — Проверяем имеющийся код и загружаем только те библиотеки, которые необходимы (а не все что есть).

npm i --save-dev babel-loader npm i --save-dev core-js 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *