Polyfill (polyfill) — kod som emulerar saknad funktionalitet (API, metoder, objekt) i miljöer där den inte är implementerad inbyggt. Polyfill gör det möjligt att använda moderna JavaScript-, CSS- eller Web API-funktioner i gamla webbläsare och körningsmiljöer. Enligt MDN Web Docs är polyfills ett nyckelverktyg för progressiv förbättring och säkerställande av cross-browser-kompatibilitet.
Huvudpunkter
Polyfill — en kodbit (vanligtvis JavaScript) som implementerar funktionalitet som körningsmiljön inte stöder inbyggt. Termen föreslogs av Remy Sharp 2009 som en ordlek: Polyfill — en analogi till spackel (Polyfilla) som fyller sprickor i väggen. Polyfill fyller luckorna mellan standarden och stödet i en specifik webbläsare eller körningsmiljö.
Polyfill ändrar inte befintlig kod — den utökar körningsmiljön. Om webbläsaren inte stöder Array.prototype.includes lägger polyfillen till denna metod i prototypen Array innan huvudkoden körs. Polyfills kan emulera nya globala objekt (Promise, Map, Set, Symbol), statiska metoder (Array.from, Object.assign) och prototypmetoder.
Feature detection — obligatorisk mekanism innan installation av polyfill. Istället för att kontrollera user-agent (vilken webbläsare) bör man kontrollera metodens förekomst: if (!Array.prototype.includes) { Array.prototype.includes = ... }. Detta garanterar att polyfillen inte skriver över den inbyggda implementeringen om den redan finns. Google Analytics och andra tjänster samlar in data om API-stöd för analys.
De första polyfillsen uppstod under Internet Explorer 6–8-eran (2005–2009), när utvecklare upptäckte klyftan mellan W3C-standarder och implementering i webbläsare. Termen introducerades av Remy Sharp 2009 på konferensen BarCamp London. Den första massiva polyfillen var html5shiv (2009) — ett bibliotek som lade till stöd för HTML5-taggar (<section>, <article>, <nav>) i Internet Explorer.
Med tillkomsten av ES6 (2015) och ECMAScripts årliga uppdateringscykel ökade antalet nödvändiga polyfills. Varje år lägger standarden till nya metoder (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) som inte stöds av gamla webbläsare. core-js, som startade som es6-shim 2014, blev den universella lösningen. År 2026 innehåller core-js över 5000 polyfillmoduler för ES5–ES2025.
| Kategori | Kan polyfillas | Kan inte polyfillas |
|---|---|---|
| Prototypmetoder | Array.includes, String.startsWith | — |
| Globala objekt | Promise, Map, Set, Symbol | — |
| Statiska metoder | Object.assign, Array.from | — |
| Språksyntax | — | Arrow functions, async/await, class |
| Web API | fetch, IntersectionObserver | Service Worker (kräver inbyggt stöd) |
Transpilering konverterar ny syntax till gammal (const → var, () => {} → function() {}). Polyfill lägger till saknade metoder och objekt (Promise, Array.includes). Dessa två mekanismer kompletterar varandra: transpilering säkerställer syntaktisk kompatibilitet, polyfills säkerställer fullständighet av API. Babel + core-js — standardkombinationen för fullt stöd.
Babel @babel/preset-env med alternativet useBuiltIns bestämmer vilka polyfills som behövs baserat på målwebbläsare. useBuiltIns: “usage” analyserar vilka API:er som används i koden och ansluter endast nödvändiga polyfills från core-js. useBuiltIns: “entry” ansluter alla polyfills för målwebbläsare via en enda import av core-js/stable.
// Kontrollera förekomst och lägg till polyfill
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,
});
}
// Användning — nu säker i vilken webbläsare som helst
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // truePolyfillen för Array.prototype.includes kontrollerar om metoden är definierad i prototypen Array. Om inte — skapar en egenskap via Object.defineProperty med flaggorna writable: true, configurable: true. Implementeringen följer ES2016-specifikationen: null/undefined-kontroll, konvertering till objekt, arbete med negativ fromIndex. Efter att polyfillen lagts till fungerar anropet arr.includes(3) i alla webbläsare, inklusive Internet Explorer 11.
core-js — det mest kompletta polyfillbiblioteket för JavaScript, som stöder alla stage-4-förslag från TC39 (ECMAScript-standarden). core-js innehåller polyfills för Promise, Symbol, Map, Set, WeakMap, WeakSet, Array-metoder, String-metoder, Object-metoder, Number-metoder, Math-metoder, Reflect, globalThis och alla stage-4 proposals. Den aktuella versionen core-js 3.38+ täcker ES5–ES2025.
core-js integreras med Babel via @babel/preset-env och alternativet useBuiltIns. Utan denna integration skulle utvecklaren manuellt behöva importera varje polyfill: import “core-js/stable/array/includes”. @babel/preset-env lägger automatiskt till nödvändiga importer baserat på målwebbläsare från .browserslistrc. Detta minskar bundle-storleken — endast nödvändiga polyfills ansluts.
Fetch API — ett av de mest polyfillade Web API:erna. Inbyggd implementering av fetch finns i Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015), men saknas i Internet Explorer och gamla WebViews. Polyfillen whatwg-fetch emulerar fetch via XMLHttpRequest. Alternativ — använd isomorphic-fetch (polyfill för Node.js och webbläsare) eller det universella biblioteket axios som inte kräver polyfills.
// Ladda fetch-polyfill endast för gamla webbläsare
if (typeof self.fetch !== "function") {
import("whatwg-fetch").then(module => {
self.fetch = module.fetch;
console.log("fetch polyfill loaded");
});
}
// Använda fetch (fungerar både med polyfill och inbyggt 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);
}
}Dynamisk import av fetch-polyfill via import() garanterar att moderna webbläsare inte laddar överflödig kod. Polyfillen laddas asynkront och blockerar inte huvudtråden. Efter laddning ersätter self.fetch den inbyggda implementeringen eller lägger till den saknade. Detta är en teknik för progressiv förbättring: moderna webbläsare får endast inbyggd kod, gamla — extra polyfill.
// 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 — målwebbläsare
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12useBuiltIns: “usage” analyserar koden och lägger endast till de polyfills som faktiskt används. corejs.version anger versionen av core-js i projektet. targets.browsers bestämmer miniminivån för webbläsare — ju äldre webbläsare, desto fler polyfills ansluts. .browserslistrc används inte bara av Babel utan även av Autoprefixer, PostCSS och Stylelint för konsekvent målning.
Polyfill.io — en tjänst (och bibliotek med samma namn) som dynamiskt bestämmer vilka polyfills användarens webbläsare behöver och returnerar endast dessa. Polyfill.io använder User-Agent-huvudet för att bestämma webbläsarversionen och levererar den minimala uppsättningen polyfills. Detta minskar mängden överförda data jämfört med en universell polyfill-bundle.
Anslutning av Polyfill.io görs via en <script>-tagg före applikationens huvudkod. Tjänsten analyserar User-Agent och returnerar en JavaScript-fil med polyfills endast för denna webbläsare. Chrome får ingen polyfill, IE 11 får den fullständiga uppsättningen. Detta är det optimala tillvägagångssättet för prestanda: moderna webbläsare laddar inte överflödig kod.
<!-- Polyfill.io: dynamisk laddning -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>
<!-- Lokal version av Polyfill.io -->
<script src="/js/polyfill.js"></script>
<script>
// funktionsdetektion för fetch
if (!self.fetch) {
loadScript("/js/fetch-polyfill.js");
}
</script>Parametern features i URL:en för Polyfill.io anger vilka polyfills som ska laddas. Möjliga värden: metodnamn (Array.prototype.includes), globala objekt (Promise) eller flaggor (es6, es2016). Flaggan “default” ansluter basuppsättningen för modern JavaScript. För produktionsprojekt rekommenderas att vara värd för Polyfill.io på eget CDN eller använda en lokal version av biblioteket för kontroll över tillgängligheten.
WebView i mobilapplikationer (Android WebView, WKWebView på iOS) — en speciell miljö för polyfills. WebView-versionen beror på operativsystemets version och installerad uppdatering av Chrome System WebView (Android) eller WKWebView från iOS Safari. I gamla Android-versioner (4.4, 5.0) är WebView baserad på Chromium 30–37 — utan stöd för fetch, Promise, IntersectionObserver.
React Native använder JavaScriptCore (iOS) eller Hermes (Android) — dessa motorer implementerar ES6+ på olika sätt. JavaScriptCore på iOS stöder de flesta ES6-funktioner men kan sakna vissa stage-3-förslag. Hermes (används som standard i React Native 0.70+) stöder en begränsad uppsättning av ES-standarden — för den är polyfills obligatoriska.
// Funktionsdetektion för WebView
const polyfills = [];
// Promise
if (typeof Promise === "undefined") {
polyfills.push("Promise");
}
// Fetch API
if (typeof self.fetch === "undefined") {
polyfills.push("fetch");
}
// IntersectionObserver (behövs för lat laddning)
if (typeof IntersectionObserver === "undefined") {
polyfills.push("IntersectionObserver");
}
// Dynamisk laddning av polyfills
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 för WebView kontrollerar förekomsten av kritiska API:er (Promise, fetch, IntersectionObserver) och laddar dynamiskt polyfills endast för de som saknas. Detta garanterar att moderna WebViews (Chrome 100+ på Android 12) inte laddar överflödig kod och gamla WebViews (Android 5.0) får nödvändigt stöd.
Vanliga frågor
React Native på Hermes kräver polyfills för vissa ES-metoder: Array.flat, Array.flatMap, globalThis, TextEncoder. Det rekommenderas att ansluta core-js eller react-native-polyfill-globals för produktionsbyggen. JavaScriptCore på iOS stöder fler funktioner men kan också kräva polyfills för stage-3-förslag.
Polyfills minskar prestandan med 1–5%, eftersom JavaScript-implementeringen är långsammare än den inbyggda C++-implementeringen i motorn. Till exempel är polyfill Promise i ren JS långsammare än inbyggt Promise i V8. För de flesta applikationer är skillnaden dock omärkbar. För kritisk kod rekommenderas att kontrollera förekomsten av inbyggd implementering via feature detection.
Transpilering konverterar syntax: const → var, pilfunktioner → function. Polyfill lägger till nya objekt/metoder: Promise, Array.includes, fetch. Transpilering fungerar i byggfasen, polyfill laddas vid körning. Båda mekanismerna är nödvändiga för fullt stöd av modern kod i gamla miljöer.
Ja, om målpubliken endast använder moderna webbläsare (Chrome 90+, Safari 15+, Firefox 90+). För projekt som stöder gamla enheter eller företagsanvändare (Internet Explorer 11 används fortfarande inom den offentliga sektorn) är polyfills obligatoriska. Analysera din publiks webbläsarstatistik via Google Analytics.
core-js i full byggnad väger ~85 KB (gzip). Vid användning av useBuiltIns: “usage” i Babel ansluts endast nödvändiga polyfills, vilket minskar storleken till 5–30 KB beroende på målwebbläsare. För moderna webbläsare (Chrome 100+) kan ingen polyfill behövas.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också