Polyfill ist Code, der fehlende Funktionalität (APIs, Methoden, Objekte) in Umgebungen emuliert, in denen sie nicht nativ implementiert ist. Polyfill ermöglicht die Verwendung moderner JavaScript-, CSS- oder Web-API-Funktionen in älteren Browsern und Laufzeitumgebungen. Laut MDN Web Docs sind Polyfills ein wichtiges Werkzeug für progressive Verbesserung und browserübergreifende Kompatibilität.
Die wichtigsten Punkte
Polyfill ist ein Code-Ausschnitt (meist JavaScript), der Funktionalität implementiert, die die Laufzeitumgebung nicht nativ unterstützt. Der Begriff wurde 2009 von Remy Sharp als Wortspiel geprägt: Polyfill ist analog zu Polyfilla, einem Füllmaterial, das Risse in einer Wand füllt. Polyfill füllt die Lücken zwischen dem Standard und seiner Unterstützung in einem bestimmten Browser oder Runtime.
Polyfill ändert vorhandenen Code nicht — es erweitert die Laufzeitumgebung. Wenn ein Browser Array.prototype.includes nicht unterstützt, fügt das Polyfill diese Methode vor der Ausführung des Hauptcodes zum Array-Prototyp hinzu. Polyfills können neue globale Objekte (Promise, Map, Set, Symbol), statische Methoden (Array.from, Object.assign) und Prototyp-Methoden emulieren.
Feature Detection ist ein obligatorischer Mechanismus vor der Installation eines Polyfills. Anstatt den User-Agent (welcher Browser) zu prüfen, sollte die Existenz der Methode geprüft werden: if (!Array.prototype.includes) { Array.prototype.includes = ... }. Dadurch wird sichergestellt, dass das Polyfill die native Implementierung nicht überschreibt, falls sie bereits existiert. Google Analytics und andere Dienste sammeln API-Supportdaten für Analysen.
Die ersten Polyfills erschienen in der Internet-Explorer-6–8-Ära (2005–2009), als Entwickler eine Lücke zwischen W3C-Standards und Browser-Implementierungen entdeckten. Der Begriff wurde von Remy Sharp 2009 auf der BarCamp London eingeführt. Das erste Massen-Polyfill war html5shiv (2009) — eine Bibliothek, die Unterstützung für HTML5-Tags (<section>, <article>, <nav>) im Internet Explorer hinzufügt.
Mit dem Aufkommen von ES6 (2015) und dem jährlichen ECMAScript-Update-Zyklus stieg die Anzahl der benötigten Polyfills. Jedes Jahr fügt der Standard neue Methoden hinzu (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled), die von älteren Browsern nicht unterstützt werden. core-js, 2014 als es6-shim gestartet, wurde zu einer universellen Lösung. Ab 2026 enthält core-js über 5.000 Polyfill-Module für ES5–ES2025.
| Kategorie | Kann polyfilliert werden | Kann nicht polyfilliert werden |
|---|---|---|
| Prototyp-Methoden | Array.includes, String.startsWith | — |
| Globale Objekte | Promise, Map, Set, Symbol | — |
| Statische Methoden | Object.assign, Array.from | — |
| Sprachsyntax | — | Arrow Functions, async/await, class |
| Web-API | fetch, IntersectionObserver | Service Worker (erfordert native Unterstützung) |
Transpilierung wandelt neue Syntax in alte Syntax um (const → var, () => {} → function() {}). Polyfill fügt fehlende Methoden und Objekte hinzu (Promise, Array.includes). Diese beiden Mechanismen ergänzen sich: Die Transpilierung macht den Code syntaktisch kompatibel, Polyfills gewährleisten die API-Vollständigkeit. Babel + core-js ist die Standardkombination für vollständige Unterstützung.
Babel @babel/preset-env mit der Option useBuiltIns bestimmt, welche Polyfills basierend auf den Zielbrowsern benötigt werden. useBuiltIns: "usage" analysiert, welche APIs im Code verwendet werden, und importiert nur die benötigten Polyfills aus core-js. useBuiltIns: "entry" importiert alle Polyfills für die Zielbrowser über einen einzigen core-js/stable-Import.
// Prüfung auf Vorhandensein und Hinzufügen von 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,
});
}
// Verwendung — jetzt sicher in jedem Browser
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // truePolyfill für Array.prototype.includes prüft, ob die Methode im Array-Prototyp definiert ist. Falls nicht, wird die Eigenschaft über Object.defineProperty mit den Flags writable: true, configurable: true erstellt. Die Implementierung folgt der ES2016-Spezifikation: null/undefined-Prüfung, Konvertierung in ein Objekt, Behandlung von negativem fromIndex. Nach dem Hinzufügen des Polyfills funktioniert arr.includes(3) in allen Browsern, einschließlich Internet Explorer 11.
core-js ist die umfassendste JavaScript-Polyfill-Bibliothek, die alle TC39-Stage-4-Vorschläge (ECMAScript-Standard) unterstützt. core-js enthält Polyfills für Promise, Symbol, Map, Set, WeakMap, WeakSet, Array-Methoden, String-Methoden, Object-Methoden, Number-Methoden, Math-Methoden, Reflect, globalThis und alle Stage-4-Vorschläge. Die aktuelle Version core-js 3.38+ deckt ES5–ES2025 ab.
core-js integriert sich über @babel/preset-env und die Option useBuiltIns in Babel. Ohne diese Integration müssten Entwickler jedes Polyfill manuell importieren: import "core-js/stable/array/includes". @babel/preset-env fügt automatisch die erforderlichen Importe basierend auf den Zielbrowsern aus .browserslistrc hinzu. Dies reduziert die Bündelgröße — nur die benötigten Polyfills werden eingeschlossen.
Fetch-API ist eine der am häufigsten polyfillierten Web-APIs. Die native fetch-Implementierung ist in Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015) verfügbar, fehlt jedoch im Internet Explorer und in älteren WebViews. Das whatwg-fetch-Polyfill emuliert fetch über XMLHttpRequest. Alternativ kann isomorphic-fetch (ein Polyfill für Node.js und Browser) oder die universelle Bibliothek axios verwendet werden, die keine Polyfills benötigt.
// Fetch-Polyfill nur für alte Browser laden
if (typeof self.fetch !== "function") {
import("whatwg-fetch").then(module => {
self.fetch = module.fetch;
console.log("fetch polyfill loaded");
});
}
// Fetch verwenden (funktioniert mit Polyfill und nativer 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);
}
}Dynamischer Import des fetch-Polyfills über import() stellt sicher, dass moderne Browser keinen unnötigen Code laden. Das Polyfill wird asynchron geladen und blockiert den Hauptthread nicht. Nach dem Laden ersetzt self.fetch die native Implementierung oder fügt die fehlende hinzu. Dies ist eine Technik der progressiven Verbesserung: Moderne Browser erhalten nur nativen Code, ältere erhalten das zusätzliche 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 — Zielbrowser
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12useBuiltIns: "usage" analysiert den Code und fügt nur die tatsächlich verwendeten Polyfills hinzu. corejs.version gibt die core-js-Version im Projekt an. targets.browsers definiert die Mindest-Browserebene — je älter die Zielbrowser, desto mehr Polyfills werden eingeschlossen. .browserslistrc wird nicht nur von Babel, sondern auch von Autoprefixer, PostCSS und Stylelint für konsistentes Targeting verwendet.
Polyfill.io ist ein Dienst (und eine gleichnamige Bibliothek), der dynamisch ermittelt, welche Polyfills der Browser des Benutzers benötigt, und nur diese zurückgibt. Polyfill.io verwendet den User-Agent-Header, um die Browserversion zu ermitteln, und stellt einen minimalen Satz von Polyfills bereit. Dies reduziert die übertragene Datenmenge im Vergleich zu einem universellen Polyfill-Bündel.
Die Verbindung von Polyfill.io erfolgt über ein <script>-Tag vor dem Hauptanwendungscode. Der Dienst analysiert den User-Agent und gibt eine JavaScript-Datei mit Polyfills nur für diesen Browser zurück. Chrome erhält keine Polyfills, IE 11 erhält den vollständigen Satz. Dies ist ein optimaler Ansatz für die Leistung: Moderne Browser laden keinen unnötigen Code.
<!-- Polyfill.io: dynamisches Laden -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>
<!-- Lokale Polyfill.io-Version -->
<script src="/js/polyfill.js"></script>
<script>
// feature detection for fetch
if (!self.fetch) {
loadScript("/js/fetch-polyfill.js");
}
</script>Der Parameter features in der Polyfill.io-URL gibt an, welche Polyfills geladen werden sollen. Mögliche Werte: Methodennamen (Array.prototype.includes), globale Objekte (Promise) oder Flags (es6, es2016). Das Flag "default" lädt einen Basissatz für modernes JavaScript. Für Produktionsprojekte wird empfohlen, Polyfill.io auf einem eigenen CDN zu hosten oder eine lokale Version der Bibliothek zur Kontrolle der Verfügbarkeit zu verwenden.
WebView in mobilen Anwendungen (Android WebView, WKWebView auf iOS) ist eine besondere Umgebung für Polyfills. Die WebView-Version hängt von der OS-Version und dem installierten Chrome System WebView-Update (Android) oder WKWebView von iOS Safari ab. In älteren Android-Versionen (4.4, 5.0) basiert WebView auf Chromium 30–37 — ohne Unterstützung für fetch, Promise, IntersectionObserver.
React Native verwendet JavaScriptCore (iOS) oder Hermes (Android) — diese Engines implementieren ES6+ unterschiedlich. JavaScriptCore auf iOS unterstützt die meisten ES6-Funktionen, kann aber einige Stage-3-Vorschläge vermissen lassen. Hermes (standardmäßig in React Native 0.70+ verwendet) unterstützt einen begrenzten Satz des ES-Standards — Polyfills sind dafür obligatorisch.
// Feature Detection für WebView
const polyfills = [];
// Promise
if (typeof Promise === "undefined") {
polyfills.push("Promise");
}
// Fetch API
if (typeof self.fetch === "undefined") {
polyfills.push("fetch");
}
// IntersectionObserver (für Lazy Loading benötigt)
if (typeof IntersectionObserver === "undefined") {
polyfills.push("IntersectionObserver");
}
// Dynamisches Laden von 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 prüft das Vorhandensein kritischer APIs (Promise, fetch, IntersectionObserver) und lädt dynamisch Polyfills nur für fehlende. Dadurch wird sichergestellt, dass moderne WebViews (Chrome 100+ auf Android 12) keinen unnötigen Code laden, während ältere WebViews (Android 5.0) die erforderliche Unterstützung erhalten.
Häufig gestellte Fragen
React Native auf Hermes benötigt Polyfills für einige ES-Methoden: Array.flat, Array.flatMap, globalThis, TextEncoder. Es wird empfohlen, core-js oder react-native-polyfill-globals für Produktions-Builds einzuschließen. JavaScriptCore auf iOS unterstützt mehr Funktionen, kann aber auch Polyfills für Stage-3-Vorschläge erfordern.
Polyfills reduzieren die Leistung um 1–5%, da die JavaScript-Implementierung langsamer ist als die native C++-Implementierung im Engine. Beispielsweise ist ein Promise-Polyfill in reinem JS langsamer als ein natives Promise in V8. Für die meisten Anwendungen ist der Unterschied jedoch vernachlässigbar. Für kritischen Code wird empfohlen, die native Implementierung per Feature Detection zu prüfen.
Transpilierung wandelt die Syntax um: const → var, Pfeilfunktionen → function. Polyfill fügt neue Objekte/Methoden hinzu: Promise, Array.includes, fetch. Die Transpilierung arbeitet zur Build-Zeit, das Polyfill wird zur Laufzeit geladen. Beide Mechanismen sind für die vollständige Unterstützung modernen Codes in älteren Umgebungen erforderlich.
Ja, wenn die Zielgruppe nur moderne Browser verwendet (Chrome 90+, Safari 15+, Firefox 90+). Für Projekte mit Unterstützung älterer Geräte oder Unternehmensnutzer (Internet Explorer 11 wird immer noch im öffentlichen Sektor verwendet) sind Polyfills obligatorisch. Analysieren Sie die Browserstatistiken Ihrer Zielgruppe über Google Analytics.
core-js wiegt im vollständigen Build ~85 KB (gzip). Bei Verwendung von useBuiltIns: "usage" in Babel werden nur die benötigten Polyfills eingeschlossen, was die Größe je nach Zielbrowsern auf 5–30 KB reduziert. Für moderne Browser (Chrome 100+) sind möglicherweise überhaupt keine Polyfills erforderlich.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch