Polyfill (полифил) — код који емулира недостајућу функционалност (API, методе, објекте) у окружењима где она није имплементирана нативним путем. Polyfill омогућава коришћење савремених могућности JavaScript, CSS или Web API у старим прегледачима и извршним окружењима. Према MDN Web Docs, полифили су кључни алат прогресивног побољшања и обезбеђења унакрсне компатибилности прегледача.
Главно
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 API | fetch, IntersectionObserver | Service Worker (захтева нативну подршку) |
Транспилација претвара нову синтаксу у стару (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.
// Провера постојања и додавање полифила
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 — најпотпунија библиотека полифила 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 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, која не захтева полифиле.
// Учитавање полифила 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 замењује нативну имплементацију или додаје недостајућу. Ово је техника прогресивног побољшања: савремени прегледачи добијају само нативни код, стари — додатни полифил.
// 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"],
},
}],
],
};# .browserslistrc — циљни прегледачи
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12useBuiltIns: „usage” анализира код и додаје само оне полифиле који су стварно коришћени. corejs.version указује верзију core-js у пројекту. targets.browsers одређује минимални ниво прегледача — што су прегледачи старији, то ће више полифила бити повезано. .browserslistrc користе не само Babel, већ и Autoprefixer, PostCSS и Stylelint за доследно циљање.
Polyfill.io — сервис (и библиотека истог имена) који динамички одређује који полифили су потребни прегледачу корисника и враћа само њих. Polyfill.io користи заглавље User-Agent за одређивање верзије прегледача и испоручује минимални скуп полифила. Ово смањује количину пренетих података у поређењу са универзалним пакетом полифила.
Повезивање Polyfill.io врши се кроз <script> ознаку пре главног кода апликације. Сервис анализира User-Agent и враћа JavaScript датотеку са полифилима само за овај прегледач. Chrome неће добити ниједан полифил, IE 11 ће добити комплетан скуп. Ово је оптималан приступ за перформансе: савремени прегледачи не учитавају непотребан код.
<!-- 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>
// detekcija karakteristika за 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 у мобилним апликацијама (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
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 на 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. Оба механизма су неопходна за потпуну подршку савременог кода у старим окружењима.
Може, ако циљна публика користи само савремене прегледаче (Chrome 90+, Safari 15+, Firefox 90+). За пројекте који подржавају старе уређаје или корпоративне кориснике (Internet Explorer 11 се још увек користи у државном сектору) полифили су обавезни. Анализирајте статистику прегледача ваше публике кроз Google Analytics.
core-js у потпуној изградњи тежи ~85 KB (gzip). При коришћењу useBuiltIns: „usage” у Babel повезују се само потребни полифили, што смањује величину на 5–30 KB у зависности од циљних прегледача. За савремене прегледаче (Chrome 100+) можда неће бити потребан ниједан полифил.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође