Polyfill (polifill) — cod care emulează funcționalitatea lipsă (API, metode, obiecte) în medii unde aceasta nu este implementată nativ. Polyfill permite utilizarea capacităților moderne ale JavaScript, CSS sau Web API în browsere vechi și runtime-uri. Potrivit MDN Web Docs, polifillurile sunt un instrument cheie al îmbunătățirii progresive și al asigurării compatibilității cross-browser.
Principalele
Polyfill — un fragment de cod (de obicei JavaScript) care implementează funcționalitatea pe care mediul de execuție nu o suportă nativ. Termenul a fost propus de Remy Sharp în 2009 ca un joc de cuvinte: Polyfill — analogia chitului (Polyfilla) care umple crăpăturile din perete. Polyfill umple golurile dintre standard și suportul într-un browser sau runtime specific.
Polyfill nu modifică codul existent — el extinde mediul de execuție. Dacă browserul nu suportă Array.prototype.includes, polifillul adaugă această metodă în prototipul Array înainte de executarea codului principal. Polifillurile pot emula noi obiecte globale (Promise, Map, Set, Symbol), metode statice (Array.from, Object.assign) și metode ale prototipurilor.
Feature detection — mecanism obligatoriu înainte de instalarea polifillului. În loc să verifici user-agent (ce browser), trebuie să verifici existența metodei: if (!Array.prototype.includes) { Array.prototype.includes = ... }. Aceasta garantează că polifillul nu va suprascrie implementarea nativă dacă aceasta există deja. Google Analytics și alte servicii colectează date despre suportul API pentru analiză.
Primele polifilluri au apărut în era Internet Explorer 6–8 (2005–2009), când dezvoltatorii au descoperit decalajul dintre standardele W3C și implementarea în browsere. Termenul a fost introdus de Remy Sharp în 2009 la conferința BarCamp London. Primul polifill în masă a fost html5shiv (2009) — o bibliotecă care adăuga suport pentru tagurile HTML5 (<section>, <article>, <nav>) în Internet Explorer.
Odată cu apariția ES6 (2015) și ciclul anual de actualizare ECMAScript, numărul polifillurilor necesare a crescut. În fiecare an standardul adaugă metode noi (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) care nu sunt suportate de browserele vechi. core-js, început ca es6-shim în 2014, a devenit soluția universală. În 2026, core-js conține peste 5000 de module de polifilluri pentru ES5–ES2025.
| Categorie | Se poate polifilla | Nu se poate polifilla |
|---|---|---|
| Metode ale prototipurilor | Array.includes, String.startsWith | — |
| Obiecte globale | Promise, Map, Set, Symbol | — |
| Metode statice | Object.assign, Array.from | — |
| Sintaxa limbajului | — | Arrow functions, async/await, class |
| Web API | fetch, IntersectionObserver | Service Worker (necesită suport nativ) |
Transpilarea transformă sintaxa nouă în cea veche (const → var, () => {} → function() {}). Polyfill adaugă metode și obiecte lipsă (Promise, Array.includes). Aceste două mecanisme se completează reciproc: transpilarea asigură compatibilitatea sintactică, polifillurile asigură completitudinea API. Babel + core-js — combinația standard pentru suport complet.
Babel @babel/preset-env cu opțiunea useBuiltIns determină ce polifilluri sunt necesare pe baza browserelor target. useBuiltIns: „usage” analizează ce API-uri sunt utilizate în cod și conectează doar polifillurile necesare din core-js. useBuiltIns: „entry” conectează toate polifillurile pentru browserele target printr-un singur import core-js/stable.
// Verificarea existenței și adăugarea polifillului
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,
});
}
// Utilizare — acum sigur în orice browser
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // truePolifillul pentru Array.prototype.includes verifică dacă metoda este definită în prototipul Array. Dacă nu — creează o proprietate prin Object.defineProperty cu flagurile writable: true, configurable: true. Implementarea urmează specificația ES2016: verificare null/undefined, conversie în obiect, lucru cu fromIndex negativ. După adăugarea polifillului, apelul arr.includes(3) funcționează în toate browserele, inclusiv Internet Explorer 11.
core-js — cea mai completă bibliotecă de polifilluri JavaScript, care suportă toate propunerile stage-4 TC39 (standardul ECMAScript). core-js conține polifilluri pentru Promise, Symbol, Map, Set, WeakMap, WeakSet, metode Array, metode String, metode Object, metode Number, metode Math, Reflect, globalThis și toate stage-4 proposals. Versiunea curentă core-js 3.38+ acoperă ES5–ES2025.
core-js se integrează cu Babel prin @babel/preset-env și opțiunea useBuiltIns. Fără această integrare, dezvoltatorul ar trebui să importe manual fiecare polifill: import „core-js/stable/array/includes”. @babel/preset-env adaugă automat importurile necesare pe baza browserelor target din .browserslistrc. Aceasta reduce dimensiunea bundle-ului — se conectează doar polifillurile necesare.
Fetch API — unul dintre cele mai frecvent polifillate Web API-uri. Implementarea nativă fetch este disponibilă în Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015), dar lipsește în Internet Explorer și WebView-uri vechi. Polifillul whatwg-fetch emulează fetch prin XMLHttpRequest. Alternativă — folosim isomorphic-fetch (polifill pentru Node.js și browser) sau biblioteca universală axios, care nu necesită polifilluri.
// Încărcarea polifillului fetch doar pentru browsere vechi
if (typeof self.fetch !== "function") {
import("whatwg-fetch").then(module => {
self.fetch = module.fetch;
console.log("fetch polyfill loaded");
});
}
// Utilizarea fetch (funcționează atât cu polifillul, cât și cu API-ul nativ)
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);
}
}Importul dinamic al polifillului fetch prin import() garantează că browserele moderne nu încarcă cod inutil. Polifillul se încarcă asincron și nu blochează firul principal. După încărcare, self.fetch înlocuiește implementarea nativă sau o adaugă pe cea lipsă. Aceasta este o tehnică de îmbunătățire progresivă: browserele moderne primesc doar cod nativ, cele vechi — polifill suplimentar.
// 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 — browsere țintă
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12useBuiltIns: „usage” analizează codul și adaugă doar polifillurile care sunt efectiv utilizate. corejs.version indică versiunea core-js în proiect. targets.browsers determină nivelul minim al browserelor — cu cât browserele sunt mai vechi, cu atât mai multe polifilluri vor fi conectate. .browserslistrc este folosit nu doar de Babel, ci și de Autoprefixer, PostCSS și Stylelint pentru o targetare coerentă.
Polyfill.io — un serviciu (și o bibliotecă cu același nume) care determină dinamic ce polifilluri sunt necesare browserului utilizatorului și returnează doar acestea. Polyfill.io utilizează antetul User-Agent pentru a determina versiunea browserului și furnizează setul minim de polifilluri. Aceasta reduce volumul datelor transmise în comparație cu un bundle universal de polifilluri.
Conectarea Polyfill.io se realizează printr-un tag <script> înaintea codului principal al aplicației. Serviciul analizează User-Agent și returnează un fișier JavaScript cu polifilluri doar pentru acest browser. Chrome nu va primi niciun polifill, IE 11 va primi setul complet. Aceasta este abordarea optimă pentru performanță: browserele moderne nu încarcă cod inutil.
<!-- Polyfill.io: încărcare dinamică -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>
<!-- Versiunea locală a Polyfill.io -->
<script src="/js/polyfill.js"></script>
<script>
// detecție caracteristici pentru fetch
if (!self.fetch) {
loadScript("/js/fetch-polyfill.js");
}
</script>Parametrul features din URL-ul Polyfill.io specifică ce polifilluri să fie încărcate. Valorile posibile: nume de metode (Array.prototype.includes), obiecte globale (Promise), sau flaguri (es6, es2016). Flagul „default” conectează setul de bază pentru JavaScript modern. Pentru proiectele de producție se recomandă găzduirea Polyfill.io pe propriul CDN sau utilizarea unei versiuni locale a bibliotecii pentru controlul disponibilității.
WebView în aplicațiile mobile (Android WebView, WKWebView pe iOS) — un mediu special pentru polifilluri. Versiunea WebView depinde de versiunea sistemului de operare și de actualizarea instalată a Chrome System WebView (Android) sau WKWebView de la iOS Safari. În versiunile vechi de Android (4.4, 5.0) WebView se bazează pe Chromium 30–37 — fără suport pentru fetch, Promise, IntersectionObserver.
React Native utilizează JavaScriptCore (iOS) sau Hermes (Android) — aceste motoare implementează ES6+ diferit. JavaScriptCore pe iOS suportă majoritatea funcționalităților ES6, dar poate să nu aibă unele propuneri stage-3. Hermes (folosit implicit în React Native 0.70+) suportă un set limitat al standardului ES — pentru acesta polifillurile sunt obligatorii.
// Detecție caracteristici pentru WebView
const polyfills = [];
// Promise
if (typeof Promise === "undefined") {
polyfills.push("Promise");
}
// Fetch API
if (typeof self.fetch === "undefined") {
polyfills.push("fetch");
}
// IntersectionObserver (necesar pentru încărcarea leneșă)
if (typeof IntersectionObserver === "undefined") {
polyfills.push("IntersectionObserver");
}
// Încărcarea dinamică a polifillurilor
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 pentru WebView verifică existența API-urilor critice (Promise, fetch, IntersectionObserver) și încarcă dinamic polifilluri doar pentru cele lipsă. Aceasta garantează că WebView-urile moderne (Chrome 100+ pe Android 12) nu încarcă cod inutil, iar WebView-urile vechi (Android 5.0) primesc suportul necesar.
Întrebări frecvente
React Native pe Hermes necesită polifilluri pentru unele metode ES: Array.flat, Array.flatMap, globalThis, TextEncoder. Se recomandă conectarea core-js sau react-native-polyfill-globals pentru versiunile de producție. JavaScriptCore pe iOS suportă mai multe funcționalități, dar poate necesita polifilluri pentru propunerile stage-3.
Polifillurile reduc performanța cu 1–5%, deoarece implementarea în JavaScript este mai lentă decât implementarea nativă C++ în motor. De exemplu, polifillul Promise în JS pur este mai lent decât Promise-ul nativ în V8. Cu toate acestea, pentru majoritatea aplicațiilor diferența este imperceptibilă. Pentru codul critic se recomandă verificarea existenței implementării native prin feature detection.
Transpilarea transformă sintaxa: const → var, funcțiile săgeată → function. Polifillul adaugă obiecte/metode noi: Promise, Array.includes, fetch. Transpilarea funcționează în faza de build, polifillul se încarcă în runtime. Ambele mecanisme sunt necesare pentru suportul complet al codului modern în medii vechi.
Se poate, dacă publicul țintă folosește doar browsere moderne (Chrome 90+, Safari 15+, Firefox 90+). Pentru proiectele care suportă dispozitive vechi sau utilizatori corporativi (Internet Explorer 11 este încă folosit în sectorul guvernamental) polifillurile sunt obligatorii. Analizați statisticile browserelor audienței dvs. prin Google Analytics.
core-js în construcția completă cântărește ~85 KB (gzip). La utilizarea useBuiltIns: „usage” în Babel se conectează doar polifillurile necesare, ceea ce reduce dimensiunea la 5–30 KB în funcție de browserele target. Pentru browserele moderne (Chrome 100+) s-ar putea să nu fie necesar niciun polifill.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și