Polyfill (πολύφιλ) — κώδικας που εξομοιώνει λειτουργικότητα που λείπει (API, μεθόδους, αντικείμενα) σε περιβάλλοντα όπου δεν έχει υλοποιηθεί εγγενώς. Το Polyfill επιτρέπει τη χρήση σύγχρονων δυνατοτήτων JavaScript, CSS ή Web API σε παλιά προγράμματα περιήγησης και χρόνους εκτέλεσης. Σύμφωνα με το MDN Web Docs, τα polyfill είναι βασικό εργαλείο προοδευτικής βελτίωσης και διασφάλισης συμβατότητας μεταξύ προγραμμάτων περιήγησης.
Κύρια σημεία
Polyfill — ένα τμήμα κώδικα (συνήθως JavaScript) που υλοποιεί λειτουργικότητα την οποία το περιβάλλον εκτέλεσης δεν υποστηρίζει εγγενώς. Ο όρος προτάθηκε από τον Remy Sharp το 2009 ως λογοπαίγνιο: Polyfill — αναλογία στόκου (Polyfilla) που γεμίζει ρωγμές στον τοίχο. Το Polyfill γεμίζει τα κενά μεταξύ του προτύπου και της υποστήριξης σε ένα συγκεκριμένο πρόγραμμα περιήγησης ή χρόνο εκτέλεσης.
Το Polyfill δεν αλλάζει τον υπάρχοντα κώδικα — επεκτείνει το περιβάλλον εκτέλεσης. Εάν το πρόγραμμα περιήγησης δεν υποστηρίζει το Array.prototype.includes, το polyfill προσθέτει αυτή τη μέθοδο στο πρωτότυπο Array πριν από την εκτέλεση του κύριου κώδικα. Τα polyfill μπορούν να εξομοιώσουν νέα καθολικά αντικείμενα (Promise, Map, Set, Symbol), στατικές μεθόδους (Array.from, Object.assign) και μεθόδους πρωτοτύπων.
Feature detection — υποχρεωτικός μηχανισμός πριν από την εγκατάσταση του polyfill. Αντί να ελέγχετε το user-agent (ποιο πρόγραμμα περιήγησης), θα πρέπει να ελέγχετε την ύπαρξη της μεθόδου: if (!Array.prototype.includes) { Array.prototype.includes = ... }. Αυτό εγγυάται ότι το polyfill δεν θα αντικαταστήσει την εγγενή υλοποίηση εάν υπάρχει ήδη. Τα Google Analytics και άλλες υπηρεσίες συλλέγουν δεδομένα σχετικά με την υποστήριξη API για ανάλυση.
Τα πρώτα polyfill εμφανίστηκαν στην εποχή του Internet Explorer 6–8 (2005–2009), όταν οι προγραμματιστές ανακάλυψαν το χάσμα μεταξύ των προτύπων W3C και της υλοποίησης στα προγράμματα περιήγησης. Ο όρος εισήχθη από τον Remy Sharp το 2009 στο συνέδριο BarCamp London. Το πρώτο μαζικό polyfill ήταν το html5shiv (2009) — μια βιβλιοθήκη που πρόσθεσε υποστήριξη για ετικέτες HTML5 (<section>, <article>, <nav>) στον Internet Explorer.
Με την εμφάνιση του ES6 (2015) και τον ετήσιο κύκλο ενημέρωσης του ECMAScript, ο αριθμός των απαραίτητων polyfill αυξήθηκε. Κάθε χρόνο το πρότυπο προσθέτει νέες μεθόδους (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) που δεν υποστηρίζονται από παλιά προγράμματα περιήγησης. Το core-js, που ξεκίνησε ως es6-shim το 2014, έγινε η καθολική λύση. Μέχρι το 2026, το core-js περιέχει πάνω από 5000 λειτουργικές μονάδες polyfill για ES5–ES2025.
| Κατηγορία | Μπορεί να γίνει polyfill | Δεν μπορεί να γίνει polyfill |
|---|---|---|
| Μέθοδοι πρωτοτύπων | 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). Αυτοί οι δύο μηχανισμοί αλληλοσυμπληρώνονται: η μεταγλώττιση εξασφαλίζει συντακτική συμβατότητα, τα polyfill εξασφαλίζουν πληρότητα API. Babel + core-js — ο τυπικός συνδυασμός για πλήρη υποστήριξη.
Το Babel @babel/preset-env με την επιλογή useBuiltIns καθορίζει ποια polyfill χρειάζονται βάσει των προγραμμάτων περιήγησης-στόχων. Το useBuiltIns: “usage” αναλύει ποια API χρησιμοποιούνται στον κώδικα και συνδέει μόνο τα απαραίτητα polyfill από το core-js. Το useBuiltIns: “entry” συνδέει όλα τα polyfill για τα προγράμματα περιήγησης-στόχους μέσω ενός μοναδικού import core-js/stable.
// Έλεγχος ύπαρξης και προσθήκη 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,
});
}
// Χρήση — τώρα ασφαλές σε οποιοδήποτε πρόγραμμα περιήγησης
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // trueΤο polyfill για Array.prototype.includes ελέγχει εάν η μέθοδος ορίζεται στο πρωτότυπο Array. Εάν όχι — δημιουργεί μια ιδιότητα μέσω Object.defineProperty με σημαίες writable: true, configurable: true. Η υλοποίηση ακολουθεί την προδιαγραφή ES2016: έλεγχος null/undefined, μετατροπή σε αντικείμενο, εργασία με αρνητικό fromIndex. Μετά την προσθήκη του polyfill, η κλήση arr.includes(3) λειτουργεί σε όλα τα προγράμματα περιήγησης, συμπεριλαμβανομένου του Internet Explorer 11.
core-js — η πληρέστερη βιβλιοθήκη polyfill JavaScript, που υποστηρίζει όλες τις προτάσεις stage-4 της TC39 (πρότυπο ECMAScript). Το core-js περιέχει polyfill για 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. Χωρίς αυτήν την ενσωμάτωση, ο προγραμματιστής θα έπρεπε να εισάγει χειροκίνητα κάθε polyfill: import “core-js/stable/array/includes”. Το @babel/preset-env προσθέτει αυτόματα τις απαραίτητες εισαγωγές βάσει των προγραμμάτων περιήγησης-στόχων από το .browserslistrc. Αυτό μειώνει το μέγεθος του bundle — συνδέονται μόνο τα απαραίτητα polyfill.
Fetch API — ένα από τα πιο συχνά polyfill που εφαρμόζονται σε Web API. Η εγγενής υλοποίηση του fetch είναι διαθέσιμη στο Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015), αλλά λείπει από τον Internet Explorer και τα παλιά WebView. Το polyfill whatwg-fetch εξομοιώνει το fetch μέσω XMLHttpRequest. Εναλλακτικά — χρησιμοποιούμε το isomorphic-fetch (polyfill για Node.js και πρόγραμμα περιήγησης) ή την καθολική βιβλιοθήκη axios, που δεν απαιτεί polyfill.
// Φόρτωση polyfill fetch μόνο για παλιά προγράμματα περιήγησης
if (typeof self.fetch !== "function") {
import("whatwg-fetch").then(module => {
self.fetch = module.fetch;
console.log("fetch polyfill loaded");
});
}
// Χρήση fetch (λειτουργεί τόσο με polyfill όσο και με εγγενές 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);
}
}Δυναμική εισαγωγή του polyfill fetch μέσω import() εγγυάται ότι τα σύγχρονα προγράμματα περιήγησης δεν φορτώνουν περιττό κώδικα. Το polyfill φορτώνεται ασύγχρονα και δεν μπλοκάρει το κύριο νήμα. Μετά τη φόρτωση, το self.fetch αντικαθιστά την εγγενή υλοποίηση ή προσθέτει αυτήν που λείπει. Αυτή είναι μια τεχνική προοδευτικής βελτίωσης: τα σύγχρονα προγράμματα περιήγησης λαμβάνουν μόνο εγγενή κώδικα, τα παλιά — επιπλέον 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 — προγράμματα περιήγησης-στόχοι
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12useBuiltIns: “usage” αναλύει τον κώδικα και προσθέτει μόνο εκείνα τα polyfill που χρησιμοποιούνται πραγματικά. Το corejs.version υποδεικνύει την έκδοση του core-js στο έργο. Το targets.browsers καθορίζει το ελάχιστο επίπεδο προγραμμάτων περιήγησης — όσο παλαιότερα είναι τα προγράμματα περιήγησης, τόσο περισσότερα polyfill θα συνδεθούν. Το .browserslistrc χρησιμοποιείται όχι μόνο από το Babel, αλλά και από τα Autoprefixer, PostCSS και Stylelint για συνεπή στόχευση.
Polyfill.io — μια υπηρεσία (και βιβλιοθήκη με το ίδιο όνομα) που καθορίζει δυναμικά ποια polyfill χρειάζονται από το πρόγραμμα περιήγησης του χρήστη και επιστρέφει μόνο αυτά. Το Polyfill.io χρησιμοποιεί την κεφαλίδα User-Agent για να καθορίσει την έκδοση του προγράμματος περιήγησης και παρέχει το ελάχιστο σύνολο polyfill. Αυτό μειώνει τον όγκο των μεταδιδόμενων δεδομένων σε σύγκριση με ένα καθολικό bundle polyfill.
Η σύνδεση του Polyfill.io γίνεται μέσω μιας ετικέτας <script> πριν από τον κύριο κώδικα της εφαρμογής. Η υπηρεσία αναλύει το User-Agent και επιστρέφει ένα αρχείο JavaScript με polyfill μόνο για αυτό το πρόγραμμα περιήγησης. Το Chrome δεν θα λάβει κανένα polyfill, το 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>
// ανίχνευση χαρακτηριστικών για fetch
if (!self.fetch) {
loadScript("/js/fetch-polyfill.js");
}
</script>Η παράμετρος features στο URL του Polyfill.io καθορίζει ποια polyfill πρέπει να φορτωθούν. Πιθανές τιμές: ονόματα μεθόδων (Array.prototype.includes), καθολικά αντικείμενα (Promise) ή σημαίες (es6, es2016). Η σημαία “default” συνδέει το βασικό σύνολο για σύγχρονο JavaScript. Για έργα παραγωγής, συνιστάται η φιλοξενία του Polyfill.io σε δικό σας CDN ή η χρήση τοπικής έκδοσης της βιβλιοθήκης για έλεγχο της διαθεσιμότητας.
WebView σε εφαρμογές κινητών (Android WebView, WKWebView σε iOS) — ένα ιδιαίτερο περιβάλλον για polyfill. Η έκδοση 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 — γι’ αυτόν τα polyfill είναι υποχρεωτικά.
// Ανίχνευση χαρακτηριστικών για 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");
}
// Δυναμική φόρτωση polyfill
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) και φορτώνει δυναμικά polyfill μόνο για αυτά που λείπουν. Αυτό εγγυάται ότι τα σύγχρονα WebView (Chrome 100+ σε Android 12) δεν φορτώνουν περιττό κώδικα, ενώ τα παλιά WebView (Android 5.0) λαμβάνουν την απαραίτητη υποστήριξη.
Συχνές Ερωτήσεις
Το React Native στον Hermes απαιτεί polyfill για ορισμένες μεθόδους ES: Array.flat, Array.flatMap, globalThis, TextEncoder. Συνιστάται η σύνδεση core-js ή react-native-polyfill-globals για εκδόσεις παραγωγής. Το JavaScriptCore σε iOS υποστηρίζει περισσότερες λειτουργίες, αλλά μπορεί επίσης να απαιτεί polyfill για προτάσεις stage-3.
Τα polyfill μειώνουν την απόδοση κατά 1–5%, καθώς η υλοποίηση JavaScript είναι πιο αργή από την εγγενή υλοποίηση C++ στη μηχανή. Για παράδειγμα, το polyfill Promise σε καθαρό JS είναι πιο αργό από το εγγενές Promise στο V8. Ωστόσο, για τις περισσότερες εφαρμογές η διαφορά είναι ανεπαίσθητη. Για κρίσιμο κώδικα, συνιστάται ο έλεγχος ύπαρξης εγγενούς υλοποίησης μέσω feature detection.
Μεταγλώττιση μετατρέπει τη σύνταξη: const → var, συναρτήσεις βέλους → function. Polyfill προσθέτει νέα αντικείμενα/μεθόδους: Promise, Array.includes, fetch. Η μεταγλώττιση λειτουργεί στη φάση δημιουργίας, το polyfill φορτώνεται κατά το χρόνο εκτέλεσης. Και οι δύο μηχανισμοί είναι απαραίτητοι για την πλήρη υποστήριξη σύγχρονου κώδικα σε παλιά περιβάλλοντα.
Μπορούμε, εάν το κοινό-στόχος χρησιμοποιεί μόνο σύγχρονα προγράμματα περιήγησης (Chrome 90+, Safari 15+, Firefox 90+). Για έργα που υποστηρίζουν παλιές συσκευές ή εταιρικούς χρήστες (ο Internet Explorer 11 χρησιμοποιείται ακόμα στον δημόσιο τομέα), τα polyfill είναι υποχρεωτικά. Αναλύστε στατιστικά προγραμμάτων περιήγησης του κοινού σας μέσω του Google Analytics.
Το core-js σε πλήρη κατασκευή ζυγίζει ~85 KB (gzip). Κατά τη χρήση του useBuiltIns: “usage” στο Babel, συνδέονται μόνο τα απαραίτητα polyfill, μειώνοντας το μέγεθος σε 5–30 KB ανάλογα με τα προγράμματα περιήγησης-στόχους. Για σύγχρονα προγράμματα περιήγησης (Chrome 100+) μπορεί να μην απαιτείται κανένα polyfill.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης