12k
All articles

Используют ли кто-то ещё полифилы в 2026 году?

Polyfills в 2026? Проверьте core-js, Browserslist и Babel, уберите лишнее, оставьте Temporal и откажитесь от polyfill.io.

OpenReplay Team
OpenReplay Team
Используют ли кто-то ещё полифилы в 2026 году?

Да — но почти ни один из тех, что достался вам по наследству от сборщика. Подход «полифилы на всё подряд», оправданный в 2019 году — когда @babel/preset-env с useBuiltIns: 'entry' настраивался под широкий Browserslist-таргет, — сегодня отправляет мёртвый груз подавляющему большинству пользователей ради поддержки доли браузеров, которая статистически стремится к нулю. Полифил по-прежнему остаётся правильным инструментом для короткого, поимённого списка действительно неподдерживаемых возможностей в 2026 году — и обузой для всего остального.

Эта статья отвечает на один конкретный вопрос: оправдывают ли полифилы в вашем текущем пайплайне сборки те байты, которые занимают. Здесь названы API, ставшие мёртвым грузом, те, которым полифил всё ещё нужен, то, что изменил инцидент с polyfill.io в подходах к их загрузке, и точные команды для аудита того, что вы реально отправляете пользователям.

Ключевые выводы

  • Для React-, Vue-, Svelte- или Next.js-приложения, ориентированного на вечнозелёные браузеры в 2026 году, правильное количество полифилов для большинства команд близко к нулю — с именованными исключениями для Decorators, Temporal в период его кросс-браузерного перехода и ограничений корпоративных браузеров с фиксированной версией.
  • Array.flat, Object.entries, Promise.allSettled, structuredClone, optional chaining, nullish coalescing и fetch — всё это широко поддерживается в 2026 году; полифилить их значит отправлять байты, которые почти никому из реальных пользователей не нужны.
  • Паттерн удалённого полифил-сервиса (загрузка скрипта с polyfill.io) мёртв после инцидента с цепочкой поставок в 2024 году; Cloudflare и Fastly подняли зеркала, но сам паттерн больше не поддаётся защите.
  • Запустите npx browserslist, чтобы увидеть точный список браузеров, на которые нацелена ваша конфигурация, затем используйте source-map-explorer, чтобы выяснить, сколько веса от core-js вы отправляете.
  • Классификация Enhancement / Additive / Critical от web.dev — наиболее сильный фреймворк для принятия решения о том, оправдывает ли отсутствие поддержки функции использование полифила вообще.

Базовый уровень нативной поддержки в 2026 году: что больше не нужно полифилить

Большинство возможностей JavaScript, которые конфигурации сборки всё ещё регулярно полифилят, теперь поддерживаются во всех вечнозелёных браузерах — а значит, полифилить их значит отправлять байты, которые почти никому из реальных пользователей не нужны. Возможности, ставшие основой полифил-туториалов на протяжении десяти лет — Math.trunc, Array.prototype.flat, optional chaining — сегодня широко поддерживаются и являются именно тем мёртвым грузом, который должен выявить аудит 2026 года.

Классический учебный пример — полифил Math.trunc с javascript.info — наглядная иллюстрация. Math.trunc имеет универсальную поддержку браузеров с 2015 года: согласно данным совместимости MDN, он появился в Chrome 38, Firefox 25 и Safari 8. Писать или бандлить полифил для Math.trunc в 2026 году — значит добавлять защитную проверку для браузера, которым никто не пользуется.

То же самое справедливо для всего спектра API, на который по-прежнему нацелены устаревшие конфигурации. Приведённые ниже проценты поддержки взяты из глобальных данных caniuse.com (StatCounter, май 2026 года); «глобальная поддержка» означает взвешенную долю браузеров по всем отслеживаемым версиям.

ВозможностьГлобальная поддержка (caniuse, 2026)Стоит ли полифилить?
Array.prototype.flat94,11%Нет
Object.entries95,06%Нет
Promise.allSettled94,04%Нет
structuredClone93,84%Нет
Optional chaining (?.)93,99%Нет (синтаксис — транспилируйте, не полифилите)
Nullish coalescing (??)93,99%Нет (синтаксис — транспилируйте, не полифилите)
fetch96,3%Нет
Temporal65,16%Да — переходный период
Decorators0% нативноДа

Array.flat, Object.entries, Promise.allSettled, structuredClone, optional chaining, nullish coalescing и fetch — все они имеют около 94–96% глобальной поддержки. Если ваша конфигурация Babel по-прежнему полифилит их, вы отправляете байты, которые не нужны почти ни одному пользователю.

Синтаксис vs. функции: Optional chaining и nullish coalescing — это синтаксис, а не отсутствующие функции, поэтому они обрабатываются транспилером, а не полифилом. Как формулирует javascript.info: используйте транспилер для современного синтаксиса и операторов, а полифилы — для отсутствующих функций. Это различие важно при аудите: «полифил» для ?? в вашей конфигурации — признак того, что конфигурация смешивает оба понятия.

Какие полифилы всё ещё оправдывают своё место в 2026 году?

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

Decorators. Предложение TC39 по декораторам находится на Stage 3 без нативной реализации ни в одном браузере. Если вы используете декораторы — напрямую или через фреймворк, например Angular, или библиотеку, которая от них зависит, — вы полагаетесь на транспилер плюс, в некоторых случаях, runtime-хелперы. Варианта «подождать нативной поддержки» пока нет: эта возможность не реализована в браузерах.

Temporal в период кросс-браузерного перехода. Temporal — завершённое предложение TC39, фигурирующее в списке завершённых предложений TC39, — и оно уже начало появляться нативно. Согласно данным совместимости MDN для Temporal, оно доступно в Firefox 139+, Chrome 144+, Edge 144+ и Node.js 26+, тогда как Safari пока не поддерживает его. Такое неравномерное распространение делает полифил для Temporal переходной необходимостью, а не постоянной. В репозитории proposal-temporal TC39 перечисляет @js-temporal/polyfill как альфа-версию наряду с альтернативами — это не единственный канонический выбор.

Корпоративные и среды с фиксированным браузером. Регулируемые финансовые системы, государственные интранеты, а также киоски и POS-устройства иногда фиксируют версию браузера на годы. Если ваша реальная аудитория включает браузеры, которые не могут обновляться, ваш Browserslist-таргет шире вечнозелёного по умолчанию, и некоторые полифилы являются критически важными. Ключевое слово здесь — реальная: этот случай декларируется гораздо чаще, чем измеряется. Проверьте его по аналитике, прежде чем сохранять полифилы ради него.

CSS-возможности с ограниченной доступностью, реализованные через JS-полифилы. Некоторые CSS-возможности, например container queries в старых версиях Safari, полифилились с помощью JavaScript в период их внедрения. Как отмечает web.dev, полифил для container queries использует ResizeObserver и MutationObserver для имитации нативного поведения — а его README помечает его как более не поддерживаемый. Эти полифилы несут в себе поведенческие оговорки, рассмотренные ниже.

Мягкий консенсус в широком обсуждении — «используйте точечные полифилы, принимайте решения на основе данных» — не ошибочен, но недооценивает масштаб произошедших изменений: для большинства приложений в 2026 году утверждение «полифилы по-прежнему играют важную роль» больше не соответствует действительности. Эта роль теперь узкая и конкретная.

Инцидент с polyfill.io убил паттерн удалённого полифил-сервиса

Паттерн удалённого полифил-сервиса — загрузка <script> со стороннего CDN, возвращающего полифилы, адаптированные под браузер, — больше не является защищаемой архитектурой после атаки на цепочку поставок polyfill.io в 2024 году. Инцидент вынудил команды проверить, что именно они загружают от третьих сторон, и большинство обнаружило, что большая часть этого им не нужна.

Хронология событий:

  • Начало 2024 года — смена владельца. Домен polyfill.io сменил владельца. Публикация в сообществе Fastly документирует это изменение и реакцию Fastly для затронутых пользователей.
  • 25 июня 2024 года — сообщение о вредоносном ПО. Компания по безопасности Sansec сообщила, что сервис polyfill.io внедрял вредоносный код в скрипты, отдаваемые конечным пользователям.
  • Июнь 2024 года — зеркала и меры по устранению. Cloudflare объявил об автоматической замене ссылок на polyfill.io собственным зеркалом, а Fastly предложил замещающий эндпоинт.

Зеркала поддерживают работу существующих сайтов, но не реабилитируют сам паттерн. Типичный производственный сбой, который это обнажило: у команд был тег <script> с cdn.polyfill.io, загружавший пакеты полифилов, которые перестали быть нужны годами ранее, и выполнявший сторонний JavaScript при каждой загрузке страницы ради поддержки браузеров, которые к тому времени обновились. Не рассматривайте зеркала Cloudflare или Fastly как «безопасную» замену один к одному — воспринимайте инцидент как повод полностью удалить тег скрипта и перенести действительно нужные полифилы в собственный бандл, где вы их контролируете и проверяете.

Как провести аудит того, что реально отправляет ваш сборщик

Аудит полифил-нагрузки — это четырёхшаговая последовательность: прочитайте реальный Browserslist-таргет, проверьте бандл на вес core-js, исправьте конфигурацию Babel и проверьте результат по реальным пользовательским данным. Здесь не нужно ничего угадывать — каждый шаг представляет собой команду или изменение конфигурации, которое можно выполнить прямо сейчас.

Шаг 1: Узнайте свой реальный список таргетов

Запросы Browserslist определяют, какие браузеры поддерживает ваша конфигурация, и единственный надёжный способ узнать, что именно разрешает ваш запрос, — спросить напрямую:

npx browserslist

Эта команда выводит конкретный список версий браузеров, на которые нацелена ваша текущая конфигурация. Дефолтные настройки Browserslist (> 0.5%, last 2 versions, Firefox ESR, not dead) уже исключают IE11 через not dead. Реальный риск — унаследованный кастомный запрос: случайный > 0.2% или явно заданная нижняя граница версий многолетней давности, которая тихо добавляет устаревшие таргеты. Запустите команду; если в выводе есть браузеры, которыми никто из реальных пользователей не пользуется, — это и есть ваш мёртвый груз.

Шаг 2: Найдите вес core-js в вашем бандле

core-js — это библиотека полифилов, из которой @babel/preset-env берёт код для инъекции, и она может составлять значительную долю бандла, которому она не нужна. Проверьте продакшн-сборку:

npx source-map-explorer dist/assets/*.js

source-map-explorer строит карту дерева содержимого каждого бандла на основе его source map. Ищите модули core-jses.array.flat, es.object.entries, es.promise.all-settled. Каждый из них соответствует возможности из таблицы мёртвого груза выше. (Для webpack-проектов webpack-bundle-analyzer даёт аналогичное представление.)

Шаг 3: Исправьте конфигурацию Babel

Каноническая конфигурация, унаследованная большинством команд, неполна. Типичный паттерн выглядит так:

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

В этой конфигурации две проблемы. Во-первых, нет поля targets, поэтому конфигурация откатывается к вашему Browserslist-файлу — который может содержать тот самый устаревший кастомный запрос из шага 1. Во-вторых, corejs: 3 не зафиксирован на минорной версии; согласно документации core-js, версия должна включать минорный номер, чтобы preset-env инжектировал полифилы, соответствующие установленному релизу. Актуальная для 2026 года версия:

{
  "presets": [
    ["@babel/preset-env", {
      "targets": "> 1%, last 2 versions, not dead",
      "useBuiltIns": "usage",
      "corejs": "3.40"
    }]
  ]
}

Зафиксируйте corejs на минорной версии, которая у вас реально установлена, а не копируйте любое число — preset-env использует его для определения того, какие полифилы существуют для инъекции.

Значение useBuiltIns — наиболее значимая настройка. Согласно документации @babel/preset-env:

  • 'entry' заменяет единственный import 'core-js' полным набором полифилов, требуемых вашими targets — широкий подход и источник большей части унаследованного раздувания бандла.
  • 'usage' добавляет полифилы только для тех возможностей, которые ваш код реально использует, на уровне каждого файла. Это почти всегда то, что вам нужно: инъекция полифилов ограничивается реальным использованием, а не всей матрицей таргетов.

Шаг 4: Проверьте результат по реальным пользовательским данным

Конфигурация — это гипотеза о ваших пользователях; данные RUM (Real User Monitoring) подтверждают или опровергают её. web.dev рекомендует измерять реальную поддержку возможностей перед принятием решения о полифиле и указывает на RUM Insights как на широкий источник данных. Паттерн там таков: возможности из набора Baseline Widely Available поддерживаются 98% и более пользователей. Если ваша аналитика показывает, что поддержка какой-то возможности близка к этому порогу, полифил для неё обслуживает долю, которая статистически стремится к нулю.

Когда стоит использовать полифил? Фреймворк Enhancement, Additive, Critical

Когда возможность действительно не поддерживается в реальной пользовательской базе, классификация Enhancement / Additive / Critical от web.dev — наиболее полезная эвристика для решения вопроса о полифиле: если отсутствие возможности невидимо для пользователей — не полифилите; если деградация происходит плавно — склоняйтесь к отказу от полифила; только если отсутствие ломает пользовательский опыт, полифил оправдывает свою стоимость с точки зрения производительности.

Три уровня, как их определяет web.dev:

  1. Enhancement (Улучшение) — возможность улучшает опыт, но её отсутствие не приводит к визуальным изменениям или потере функциональности. Примером служат подсказки производительности вроде fetchpriority. Пользователи на браузерах без поддержки ничего не заметят. Не полифилите.
  2. Additive (Дополнительное) — возможность может влиять на внешний вид или поведение страницы, но не так, чтобы создавать серьёзные проблемы; пользователь может заметить разницу, только сравнивая браузеры. Если полифил существует, склоняйтесь к тому, чтобы не использовать его, особенно если вы уже полифилите что-то ещё. Примеры — цветовые функции и subgrid.
  3. Critical (Критическое) — отсутствие приводит к сломанному опыту: ошибкам в рантайме, сломанным макетам, неработающей функциональности. Здесь полифил (или совершенно другой подход) оправдан.

Базовое правило web.dev хорошо сочетается с таблицей поддержки выше: если возможность широко доступна (Widely Available), не тянитесь за полифилом — если только у вас нет данных о ваших пользователях, которые явно говорят об обратном.

Почему баги полифилов скрываются — и как их выявляет запись сессий

Баги полифилов относятся к классу, который стандартные тест-сьюты полностью упускают: они проявляются только в той доле браузеров, которая и вызвала применение полифила, — а это никогда не тот вечнозелёный браузер, в котором работает ваш CI. Запись сессий (session replay) — один из немногих методов наблюдаемости, который захватывает реальное состояние DOM у таких пользователей, поскольку записывает реальную последовательность взаимодействий и мутаций из браузера, выполнявшего путь с полифилом.

Запись сессий выявляет три конкретных паттерна расхождения между путями с полифилом и нативным кодом:

  • Тайминг сдвига макета в полифиле container queries. Как отмечает web.dev, полифил container queries управляет макетом из колбэков ResizeObserver, которые срабатывают непосредственно перед тем, как браузер рисует новый кадр, — увеличивая задержку отрисовки и влияя на Interaction to Next Paint. Задержанный тайминг перерисовки может приводить к сдвигам макета, которые наблюдаемы только в браузерах, где полифил был нужен.
  • Расхождение часовых поясов в Temporal. В период кросс-браузерного перехода Temporal командам может потребоваться тестировать как нативную, так и полифилированную реализации Temporal для обеспечения согласованного поведения в разных браузерах. Ваш тест-сьют может выполняться только против одного пути реализации, тогда как реальные пользователи сталкиваются с другим; записи сессий из браузеров, где нативная и полифилированная реализации сосуществуют, могут помочь выявить эти различия.
  • Пробелы в управлении фокусом. Полифилы, ориентированные на доступность, могут вносить тонкие проблемы с навигацией по клавиатуре и управлением фокусом в браузерах без нативной поддержки — тот тип сбоев, который web.dev выделяет в более общем контексте. Запись с захватом событий клавиатуры показывает, как пользователь переходит по элементам модального оверлея с помощью Tab, — а это не выявит автоматизированный тест, прошедший против полифила.

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

Конкретные действия на эту неделю

Сокращение полифил-нагрузки — это последовательность небольших, обратимых правок, каждая из которых проверяется по бандлу и данным о пользователях. Цель — отправлять нативный код там, где это возможно, условно загружать полифилы для реального «длинного хвоста» и убирать всё остальное.

  1. Запустите npx browserslist и удалите любой унаследованный кастомный запрос, нацеленный на браузеры, которыми никто из реальных пользователей не пользуется. Переход к более узкому, актуальному таргету — единственное изменение с наибольшим эффектом.
  2. Установите useBuiltIns: 'usage' и явное поле targets в конфигурации @babel/preset-env, зафиксируйте corejs на установленной у вас минорной версии.
  3. Сравните бандл до и после с помощью source-map-explorer, чтобы убедиться, что вес core-js действительно снизился, затем запустите тесты, чтобы убедиться, что ничего нужного не исчезло.
  4. Полностью удалите тег <script> с cdn.polyfill.io; перенесите действительно нужные полифилы в собственный бандл.
  5. Условно загружайте реальные исключения. Для Temporal в переходный период загружайте полифил только для браузеров, которым он нужен, а не отправляйте его всем. Для Decorators полагайтесь на транспиляцию и runtime-хелперы там, где это требуется. Рекомендация web.dev о том, что полифилы для возможностей с ограниченной доступностью должны загружаться условно, применима напрямую.
  6. Проверьте результат по данным RUM до и после, чтобы аудит опирался на данные о ваших пользователях, а не на глобальные средние значения.

Заключение

Честный ответ 2026 года на вопрос, используют ли кто-то ещё полифилы, — да, но защищаемый список короткий и конкретный: Decorators, Temporal в период кросс-браузерного перехода и среды с фиксированным браузером, которые вы реально измерили. Всё остальное, унаследованное вашей конфигурацией, — это байты, потраченные на долю браузеров, которая статистически стремится к нулю, а инцидент с polyfill.io напоминает, что небрежная их загрузка несёт реальный риск. Начните с npx browserslist сегодня; разрыв между тем, что выведет эта команда, и браузерами, которыми реально пользуются ваши пользователи, — это ваш полифил-бюджет, и для большинства команд он намного меньше, чем предполагает конфигурация.

Часто задаваемые вопросы

В чём разница между полифилом и транспилером?

Транспилер переписывает современный синтаксис в более старый эквивалент на этапе сборки, тогда как полифил добавляет реализацию отсутствующей функции или API во время выполнения. Синтаксические возможности, такие как optional chaining и nullish coalescing, обрабатываются транспилером, поскольку являются языковыми операторами, а не вызываемыми функциями. API вроде Promise.allSettled или structuredClone обрабатываются полифилами, поскольку представляют собой отсутствующие методы, которые может предоставить код времени выполнения. «Полифил» для nullish coalescing в вашей конфигурации сигнализирует о том, что эти два понятия смешаны.

В чём разница между useBuiltIns 'usage' и 'entry' в babel-preset-env?

При useBuiltIns равном 'entry' Babel заменяет единственный импорт core-js полным набором полифилов, требуемых вашими targets, — это источник большей части унаследованного раздувания бандла. При 'usage' Babel инжектирует полифилы только для тех возможностей, которые ваш код реально использует, на уровне каждого файла. Значение 'usage' почти всегда предпочтительнее, поскольку отправляет полифилы для реального использования, а не для всей матрицы targets. Оба варианта требуют фиксации corejs на установленной у вас минорной версии.

Безопасно ли продолжать использовать polyfill.io через зеркало Cloudflare или Fastly?

Зеркала Cloudflare и Fastly поддерживают работу существующих сайтов, но не реабилитируют паттерн удалённого полифил-сервиса. После того как домен polyfill.io сменил владельца в начале 2024 года, а Sansec 25 июня 2024 года сообщил о внедрении вредоносного кода сервисом, загрузка адаптированных под браузер полифилов со стороннего CDN стала неприемлемой для команд, серьёзно относящихся к безопасности. Полностью удалите тег скрипта с cdn.polyfill.io и перенесите действительно нужные полифилы в собственный бандл, где вы их контролируете и проверяете.

Нужен ли мне core-js, если моё приложение нацелено только на вечнозелёные браузеры?

Для большинства приложений, ориентированных на вечнозелёные браузеры, в 2026 году core-js отправляет близкое к нулю количество полезных полифилов, поскольку такие возможности, как Array.flat, Object.entries, Promise.allSettled, structuredClone и fetch, уже широко поддерживаются. Именованные исключения — Decorators, не имеющий нативной реализации ни в одном браузере, и Temporal в период неравномерного кросс-браузерного распространения. Запустите source-map-explorer против продакшн-сборки, чтобы увидеть, какие модули core-js присутствуют, затем ужесточьте Browserslist-таргет и переключите useBuiltIns на 'usage', чтобы избавиться от мёртвого груза.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.