Polyfill: що це, принцип роботи та бібліотеки для емуляції API

Автор: IT Sectr Опубліковано: 2026-05-19 Час читання: 9 хв

Polyfill (поліфілл) — код, який емулює відсутню функціональність (API, методи, об'єкти) у середовищах, де вона не реалізована нативно. Polyfill дозволяє використовувати сучасні можливості JavaScript, CSS або Web API в старих браузерах і рантаймах. За даними MDN Web Docs, поліфілли є ключовим інструментом прогресивного покращення та забезпечення крос-браузерної сумісності.

Головне

  • Polyfill — програмна емуляція відсутнього API в середовищі виконання, де цей API не реалізовано
  • core-js — стандартна бібліотека поліфіллів для сучасного JavaScript з підтримкою всіх stage-4 пропозицій
  • Polyfill.io — сервіс, який динамічно підставляє поліфілли тільки для браузера користувача
  • Транспіляція vs polyfill: транспіляція перетворює синтаксис (arrow function → function), polyfill додає нові методи (Array.includes, Promise)
  • Feature detection — перевірка наявності нативної реалізації перед завантаженням поліфілла для уникнення конфліктів

Що таке Polyfill?

Polyfill — фрагмент коду (зазвичай JavaScript), який реалізує функціональність, яку середовище виконання не підтримує нативно. Термін запропонував Ремі Шарп у 2009 році як гру слів: Polyfill — аналог шпаклівки (Polyfilla), яка заповнює тріщини в стіні. Polyfill заповнює прогалини між стандартом та підтримкою в конкретному браузері або рантаймі.

Polyfill не змінює існуючий код — він розширює середовище виконання. Якщо браузер не підтримує Array.prototype.includes, поліфілл додає цей метод у прототип Array до виконання основного коду. Поліфілли можуть емулювати нові глобальні об'єкти (Promise, Map, Set, Symbol), статичні методи (Array.from, Object.assign) та методи прототипів.

Feature detection — обов'язковий механізм перед встановленням поліфілла. Замість перевірки user-agent (який браузер), слід перевіряти наявність методу: if (!Array.prototype.includes) { Array.prototype.includes = ... }. Це гарантує, що поліфілл не перезапише нативну реалізацію, якщо вона вже існує. Google Analytics та інші сервіси збирають дані про підтримку API для аналізу.

Коли з'явилися поліфілли

Перші поліфілли з'явилися в епоху Internet Explorer 6–8 (2005–2009), коли розробники виявили розрив між стандартами W3C та реалізацією в браузерах. Термін ввів Ремі Шарп у 2009 році на конференції BarCamp London. Першим масовим поліфіллом став html5shiv (2009) — бібліотека, яка додає підтримку HTML5-тегів (<section>, <article>, <nav>) в Internet Explorer.

З появою ES6 (2015) та річного циклу оновлень ECMAScript кількість необхідних поліфіллів зросла. Щороку стандарт додає нові методи (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled), які не підтримуються старими браузерами. core-js, розпочатий як es6-shim у 2014, став універсальним рішенням. На 2026 рік core-js містить понад 5000 модулів поліфіллів для ES5–ES2025.

Що можна і не можна поліфіллити

КатегоріяМожна поліфіллитиНе можна поліфіллити
Методи прототипівArray.includes, String.startsWith
Глобальні об'єктиPromise, Map, Set, Symbol
Статичні методиObject.assign, Array.from
Синтаксис мовиArrow functions, async/await, class
Web APIfetch, IntersectionObserverService Worker (вимагає нативної підтримки)

Polyfill vs транспіляція: відмінності та взаємодія

Транспіляція перетворює новий синтаксис на старий (const → var, () => {} → function() {}). Polyfill додає відсутні методи та об'єкти (Promise, Array.includes). Ці два механізми доповнюють один одного: транспіляція робить код синтаксично сумісним, поліфілли забезпечують повноту API. Babel + core-js — стандартна комбінація для повної підтримки.

Babel @babel/preset-env з опцією useBuiltIns визначає, які поліфілли потрібні на основі target-браузерів. useBuiltIns: "usage" аналізує, які API використовуються в коді, та підключає тільки потрібні поліфілли з core-js. useBuiltIns: "entry" підключає всі поліфілли для target-браузерів через єдиний імпорт core-js/stable.

Приклад: поліфілл для Array.prototype.includes

js
// Перевірка наявності та додавання поліфілла
if (typeof Array.prototype.includes !== "function") {
  Object.defineProperty(Array.prototype, "includes", {
    value: function(searchElement, fromIndex) {
      if (this == null) {
        throw new TypeError("Array.prototype.includes called on null or undefined");
      }
      var arr = Object(this);
      var len = arr.length >>> 0;
      if (len === 0) { return false; }
      var start = fromIndex | 0;
      var k = Math.max(start >= 0 ? start : len + start, 0);

      while (k < len) {
        if (arr[k] === searchElement) { return true; }
        k++;
      }
      return false;
    },
    writable: true,
    configurable: true,
  });
}

// Використання — тепер безпечно в будь-якому браузері
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true

Поліфілл для Array.prototype.includes перевіряє, чи визначено метод у прототипі Array. Якщо ні — створює властивість через Object.defineProperty з прапорами writable: true, configurable: true. Реалізація слідує специфікації ES2016: перевірка null/undefined, перетворення в об'єкт, робота з від'ємним fromIndex. Після додавання поліфілла виклик arr.includes(3) працює у всіх браузерах, включаючи Internet Explorer 11.

core-js: стандартна бібліотека поліфіллів

core-js — найповніша бібліотека поліфіллів JavaScript, яка підтримує всі stage-4 пропозиції TC39 (ECMAScript стандарт). core-js містить поліфілли для Promise, Symbol, Map, Set, WeakMap, WeakSet, методи Array, методи String, методи Object, методи Number, методи Math, Reflect, globalThis та всіх stage-4 proposals. Актуальна версія core-js 3.38+ покриває ES5–ES2025.

core-js інтегрується з Babel через @babel/preset-env та опцію useBuiltIns. Без цієї інтеграції розробнику довелося б вручну імпортувати кожен поліфілл: import "core-js/stable/array/includes". @babel/preset-env автоматично додає необхідні імпорти на основі target-браузерів з .browserslistrc. Це зменшує розмір бандла — підключаються тільки потрібні поліфілли.

Приклад: поліфілл для fetch

Fetch API — один із найчастіше поліфіллимих Web API. Нативна реалізація fetch доступна в Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015), але відсутня в Internet Explorer та старих WebView. Поліфілл whatwg-fetch емулює fetch через XMLHttpRequest. Альтернатива — використовуємо isomorphic-fetch (поліфілл для Node.js та браузера) або універсальну бібліотеку axios, яка не потребує поліфіллів.

js
// Завантаження поліфілла fetch тільки для старих браузерів
if (typeof self.fetch !== "function") {
  import("whatwg-fetch").then(module => {
    self.fetch = module.fetch;
    console.log("fetch polyfill loaded");
  });
}

// Використання fetch (працює і з поліфіллом, і з нативним API)
async function loadData() {
  try {
    const response = await fetch("https://api.example.com/data");
    const json = await response.json();
    return json;
  } catch (error) {
    console.error("Failed to load:", error);
  }
}

Динамічний import поліфілла fetch через import() гарантує, що сучасні браузери не завантажать зайвий код. Поліфілл завантажується асинхронно і не блокує основний потік. Після завантаження self.fetch замінює нативну реалізацію або додає відсутню. Це техніка прогресивного enhancement: сучасні браузери отримують тільки нативний код, старі — додатковий поліфілл.

Інтеграція core-js з Babel

js
// babel.config.js — core-js + preset-env
module.exports = {
  presets: [
    ["@babel/preset-env", {
      useBuiltIns: "usage",
      corejs: {
        version: "3.38",
        proposals: true,
      },
      targets: {
        browsers: ["> 0.5%", "not dead", "not op_mini all"],
      },
    }],
  ],
};
none
# .browserslistrc — цільові браузери
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12

useBuiltIns: "usage" аналізує код та додає тільки ті поліфілли, які реально використовуються. corejs.version вказує версію core-js в проєкті. targets.browsers визначає мінімальний рівень браузерів — чим древніші браузери, тим більше поліфіллів буде підключено. .browserslistrc використовується не тільки Babel, але й Autoprefixer, PostCSS та Stylelint для узгодженого таргетингу.

Polyfill.io та динамічне завантаження поліфіллів

Polyfill.io — сервіс (та однойменна бібліотека), який динамічно визначає, які поліфілли потрібні браузеру користувача, та повертає тільки їх. Polyfill.io використовує заголовок User-Agent для визначення версії браузера та підставляє мінімальний набір поліфіллів. Це зменшує розмір переданих даних порівняно з універсальним бандлом поліфіллів.

Підключення Polyfill.io виконується через <script>-тег перед основним кодом додатку. Сервіс аналізує User-Agent та повертає JavaScript-файл з поліфіллами тільки для цього браузера. Chrome не отримає жодного поліфілла, IE 11 отримає повний набір. Це оптимальний підхід для продуктивності: сучасні браузери не завантажують зайвий код.

Підключення Polyfill.io

html
<!-- Polyfill.io: динамічне завантаження -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>

<!-- Локальна версія Polyfill.io -->
<script src="/js/polyfill.js"></script>
<script>
  // feature detection for fetch
  if (!self.fetch) {
    loadScript("/js/fetch-polyfill.js");
  }
</script>

Параметр features в URL Polyfill.io вказує, які поліфілли завантажувати. Можливі значення: назви методів (Array.prototype.includes), глобальних об'єктів (Promise) або прапори (es6, es2016). Прапор "default" підключає базовий набір для сучасного JavaScript. Для production-проєктів рекомендується розміщувати Polyfill.io на власному CDN або використовувати локальну версію бібліотеки для контролю над доступністю.

Поліфілли в мобільних додатках та WebView

WebView в мобільних додатках (Android WebView, WKWebView на iOS) — особливе середовище для поліфіллів. Версія WebView залежить від версії ОС та встановленого оновлення Chrome System WebView (Android) або WKWebView від iOS Safari. У старих версіях Android (4.4, 5.0) WebView заснований на Chromium 30–37 — без підтримки fetch, Promise, IntersectionObserver.

React Native використовує JavaScriptCore (iOS) або Hermes (Android) — ці рушії реалізують ES6+ по-різному. JavaScriptCore на iOS підтримує більшість ES6-фіч, але може не мати деяких stage-3 пропозицій. Hermes (використовуваний за замовчуванням в React Native 0.70+) підтримує обмежений набір ES-стандарту — для нього поліфілли обов'язкові.

Перевірка підтримки в WebView

js
// feature detection для WebView
const polyfills = [];

// Promise
if (typeof Promise === "undefined") {
  polyfills.push("Promise");
}

// Fetch API
if (typeof self.fetch === "undefined") {
  polyfills.push("fetch");
}

// IntersectionObserver (потрібен для лінивого завантаження)
if (typeof IntersectionObserver === "undefined") {
  polyfills.push("IntersectionObserver");
}

// Динамічне завантаження поліфіллів
if (polyfills.length > 0) {
  const script = document.createElement("script");
  script.src = "https://cdn.polyfill.io/v3/polyfill.min.js"
    + "?features=" + polyfills.join(",");
  document.head.appendChild(script);
}

Feature detection для WebView перевіряє наявність критичних API (Promise, fetch, IntersectionObserver) та динамічно завантажує поліфілли тільки для відсутніх. Це гарантує, що сучасні WebView (Chrome 100+ на Android 12) не завантажують зайвий код, а старі WebView (Android 5.0) отримують необхідну підтримку.

Часті запитання

Чи потрібні поліфілли для React Native?

React Native на Hermes вимагає поліфілли для деяких ES-методів: Array.flat, Array.flatMap, globalThis, TextEncoder. Рекомендується підключати core-js або react-native-polyfill-globals для продакшен-збірок. JavaScriptCore на iOS підтримує більше фіч, але також може вимагати поліфілли для stage-3 пропозицій.

Чи впливають поліфілли на продуктивність?

Поліфілли знижують продуктивність на 1–5%, оскільки JavaScript-реалізація повільніша за нативну C++ реалізацію в рушії. Наприклад, поліфілл Promise на чистому JS повільніший за нативний Promise у V8. Однак для більшості додатків різниця непомітна. Для критичного коду рекомендується перевіряти наявність нативної реалізації через feature detection.

Чим відрізняється поліфілл від транспіляції?

Транспіляція перетворює синтаксис: const → var, стрілкові функції → function. Поліфілл додає нові об'єкти/методи: Promise, Array.includes, fetch. Транспіляція працює на етапі збірки, поліфілл завантажується в runtime. Обидва механізми необхідні для повної підтримки сучасного коду в старих середовищах.

Чи можна не використовувати поліфілли в 2026 році?

Можна, якщо target-аудиторія використовує тільки сучасні браузери (Chrome 90+, Safari 15+, Firefox 90+). Для проєктів з підтримкою старих пристроїв або корпоративних користувачів (Internet Explorer 11 досі використовується в держсекторі) поліфілли обов'язкові. Аналізуйте статистику браузерів вашої аудиторії через Google Analytics.

Який розмір поліфіллів core-js?

core-js в повній збірці важить ~85 КБ (gzip). При використанні useBuiltIns: "usage" в Babel підключаються тільки потрібні поліфілли, що зменшує розмір до 5–30 КБ залежно від target-браузерів. Для сучасних браузерів (Chrome 100+) може не знадобитися жодного поліфілла.

Підсумки

  • Polyfill — емуляція відсутнього API в середовищі виконання, що забезпечує сумісність сучасного коду зі старими середовищами
  • core-js — стандартна бібліотека поліфіллів для ES5–ES2025, інтегрована з Babel через @babel/preset-env
  • Polyfill.io — сервіс динамічного завантаження поліфіллів на основі User-Agent браузера
  • Транспіляція + поліфілли — комплексне рішення: Babel перетворює синтаксис, core-js додає відсутні API
  • Feature detection — перевірка наявності нативної реалізації перед завантаженням поліфілла для продуктивності
  • WebView та Hermes вимагають обов'язкових поліфіллів для fetch, Promise та IntersectionObserver у старих версіях

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також