Что такое полифил — и как один такой скрипт заразил 100 000 сайтов

Смотри, какая история. Летом 2024 года на сотне тысяч сайтов одна строчка в <head> вдруг начала перекидывать мобильных посетителей на мошеннические страницы. Хозяева сайтов ничего не меняли.
Строчка подключала скрипт с polyfill.io — популярного сервиса полифилов. В феврале домен купила новая компания, а в июне в скрипт добавили вредоносный код. Сайты сами раздавали его своим пользователям.
Разберёмся, что такое полифил, почему его подключали все — и как не наступить на те же грабли.
Что такое полифил
Полифил — это кусок кода, который дописывает браузеру функцию, которой у него ещё нет. Свой вариант той же самой функции, с тем же именем и поведением.
Пример. В новых браузерах у массива есть .at(-1) — последний элемент. В старом его нет, код падает с arr.at is not a function. Полифил проверяет и, если надо, добавляет:
if (!Array.prototype.at) {
Array.prototype.at = function (i) {
const n = Math.trunc(i) || 0
return this[n < 0 ? this.length + n : n]
}
}
Главное тут — первая строка. Хороший полифил сначала спрашивает: «а у тебя уже есть?» Есть — ничего не трогает. Нет — достраивает. Как доска, вставленная точно в просвет моста.
Полифил и транспиляция — не одно и то же
Тут новички путаются чаще всего. Полифил умеет добавить только функцию. А новый синтаксис добавить нельзя.
structuredClone(),Array.prototype.at,Object.groupBy— это функции. Их можно дописать полифилом.?.,??,classс#private-полями — это синтаксис. Старый браузер даже не прочитает такой файл, он споткнётся на разборе. Тут полифил бессилен.
Синтаксис чинит другой инструмент — транспилятор. Это сборщик вроде Vite, esbuild или Babel. Он переписывает новый синтаксис в старый ещё до того, как код попадёт в браузер. В Vite за это отвечает настройка build.target.
Отсюда простое правило. Ошибка ... is not a function в старом браузере — нужен полифил. Ошибка Unexpected token — нужен транспилятор.
Почему полифилы опасны
Полифил меняет общие объекты вроде Array.prototype. Это сила, но и риск.
Риск первый — чужой код в твоём сайте. Полифил с внешнего сервера работает с полными правами на твоей странице. История polyfill.io ровно об этом: ты доверяешь не коду, а домену. Сменился хозяин — сменился код. После той атаки Cloudflare и Fastly подняли свои безопасные копии, а регистратор отключил домен. Но сайты, которые не убрали строчку, оставались под ударом.
Риск второй — самодельные «полифилы» ломают будущее. В 2018 году в JavaScript хотели добавить Array.prototype.flatten. Оказалось, старая библиотека MooTools уже добавляла свой flatten с другим поведением — и тысячи сайтов сломались бы. Стандарт переименовали в flat. Ровно так же раньше contains стал includes.
Отсюда два правила:
- Ставь полифилы как зависимость через npm, а не тегом с чужого CDN. Пакет фиксируется в lockfile и не поменяется без тебя.
- Не дописывай свои методы во встроенные объекты. Нужна функция — сделай обычную функцию
last(arr).
Нужен ли он тебе в 2026-м
Чаще всего — нет. Современные браузеры обновляются сами, и большинство функций уже есть везде. Проверить можно на caniuse.com или по отметке Baseline на MDN: «Baseline widely available» значит, что функция работает во всех основных браузерах больше двух лет.
Полифил нужен, если:
- твоя аудитория сидит на старых телефонах или корпоративных браузерах;
- ты используешь совсем свежее API. Например,
Temporalдля дат — его поддерживают не все браузеры, и для него есть официальный полифил. Мы разбирали это в статье про разницу между датами.
Как попросить ИИ
Сделай, чтобы работало в старых браузерахСайт должен работать в Safari 15 и Chrome 100.
Найди в коде функции и API, которых там нет, и для каждого скажи: нужен полифил или транспиляция.
Полифилы подключай только пакетами из npm, без скриптов с внешних CDN.
Для синтаксиса настрой build.target в Vite.Хороший ответ разделит список на две колонки — «функции» и «синтаксис». Если ИИ предлагает тег <script src="https://...polyfill..."> — откажись.
Полифил замедляет сайт?
Немного: это лишний код, который скачивает каждый посетитель. Поэтому подключай полифилы точечно, только под нужные функции, а не «всё сразу на всякий случай».
Чем полифил отличается от понифила?
Понифил (ponyfill) — та же функция, но без изменения встроенных объектов. Ты импортируешь её и вызываешь как обычную: import at from "...". Безопаснее, но код надо писать через неё явно.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





