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), който имплементира функционалност, която средата за изпълнение не поддържа нативно. Терминът е предложен от Remy Sharp през 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 и имплементацията в браузърите. Терминът беше въведен от Remy Sharp през 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 определя кои полифили са необходими въз основа на целевите браузъри. useBuiltIns: „usage” анализира кои API се използват в кода и свързва само необходимите полифили от core-js. useBuiltIns: „entry” свързва всички полифили за целевите браузъри чрез единен import на 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 автоматично добавя необходимите импорти въз основа на целевите браузъри от .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 замества нативната имплементация или добавя липсващата. Това е техника на прогресивно подобрение: съвременните браузъри получават само нативен код, старите — допълнителен полифил.

Интеграция на 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>
  // откриване на функции за fetch
  if (!self.fetch) {
    loadScript("/js/fetch-polyfill.js");
  }
</script>

Параметърът features в URL адреса на Polyfill.io указва кои полифили да се заредят. Възможни стойности: имена на методи (Array.prototype.includes), глобални обекти (Promise) или флагове (es6, es2016). Флагът „default” свързва основния набор за модерен JavaScript. За производствени проекти се препоръчва хостване на 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
// Откриване на функции за 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. Транспилацията работи във фазата на изграждане, полифилът се зарежда по време на изпълнение. И двата механизма са необходими за пълна поддръжка на модерен код в стари среди.

Може ли да се избегнат полифилите през 2026 г.?

Може, ако целевата аудитория използва само съвременни браузъри (Chrome 90+, Safari 15+, Firefox 90+). За проекти, поддържащи стари устройства или корпоративни потребители (Internet Explorer 11 все още се използва в държавния сектор), полифилите са задължителни. Анализирайте статистиката на браузърите на вашата аудитория чрез Google Analytics.

Какъв е размерът на полифилите на core-js?

core-js в пълна компилация тежи ~85 KB (gzip). При използване на useBuiltIns: „usage” в Babel се свързват само необходимите полифили, което намалява размера до 5–30 KB в зависимост от целевите браузъри. За съвременни браузъри (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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също