Polyfill: cos'è, principio di funzionamento e librerie per emulare API

Autore: IT Sectr Pubblicato: 2026-05-19 Tempo di lettura: 9 min

Polyfill è un codice che emula funzionalità mancanti (API, metodi, oggetti) in ambienti in cui non sono implementate nativamente. Polyfill consente di utilizzare funzionalità moderne di JavaScript, CSS o Web API in browser vecchi e runtime. Secondo MDN Web Docs, i polyfill sono uno strumento chiave per il miglioramento progressivo e la compatibilità tra browser.

Punti chiave

  • Polyfill è un'emulazione software di un'API mancante in un ambiente di esecuzione in cui tale API non è implementata
  • core-js è la libreria standard di polyfill per JavaScript moderno con supporto di tutte le proposte stage-4
  • Polyfill.io è un servizio che fornisce polyfill dinamicamente solo per il browser dell'utente
  • Transpilazione vs polyfill: la transpilazione trasforma la sintassi (arrow function → function), il polyfill aggiunge nuovi metodi (Array.includes, Promise)
  • Rilevamento delle funzionalità verifica la presenza di un'implementazione nativa prima di caricare un polyfill per evitare conflitti

Cos'è Polyfill?

Polyfill è un frammento di codice (di solito JavaScript) che implementa funzionalità che l'ambiente di esecuzione non supporta nativamente. Il termine è stato coniato da Remy Sharp nel 2009 come un gioco di parole: Polyfill è analogo a Polyfilla, uno stucco che riempie le crepe in un muro. Polyfill colma le lacune tra lo standard e il suo supporto in un browser o runtime specifico.

Polyfill non modifica il codice esistente — estende l'ambiente di esecuzione. Se un browser non supporta Array.prototype.includes, il polyfill aggiunge questo metodo al prototipo Array prima dell'esecuzione del codice principale. I polyfill possono emulare nuovi oggetti globali (Promise, Map, Set, Symbol), metodi statici (Array.from, Object.assign) e metodi di prototipo.

Rilevamento delle funzionalità è un meccanismo obbligatorio prima di installare un polyfill. Invece di controllare lo user-agent (quale browser), si dovrebbe verificare l'esistenza del metodo: if (!Array.prototype.includes) { Array.prototype.includes = ... }. Questo garantisce che il polyfill non sovrascriva l'implementazione nativa se esiste già. Google Analytics e altri servizi raccolgono dati di supporto API per l'analisi.

Quando sono comparsi i polyfill

I primi polyfill sono apparsi nell'era di Internet Explorer 6–8 (2005–2009), quando gli sviluppatori hanno scoperto un divario tra gli standard W3C e le implementazioni dei browser. Il termine è stato introdotto da Remy Sharp nel 2009 al BarCamp London. Il primo polyfill di massa è stato html5shiv (2009) — una libreria che aggiunge il supporto per i tag HTML5 (<section>, <article>, <nav>) in Internet Explorer.

Con l'avvento di ES6 (2015) e del ciclo annuale di aggiornamenti ECMAScript, il numero di polyfill necessari è cresciuto. Ogni anno lo standard aggiunge nuovi metodi (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) che non sono supportati dai browser vecchi. core-js, nato come es6-shim nel 2014, è diventato una soluzione universale. Nel 2026, core-js contiene oltre 5.000 moduli di polyfill per ES5–ES2025.

Cosa può e non può essere polyfillato

CategoriaPuò essere polyfillatoNon può essere polyfillato
Metodi di prototipoArray.includes, String.startsWith
Oggetti globaliPromise, Map, Set, Symbol
Metodi staticiObject.assign, Array.from
Sintassi del linguaggioArrow functions, async/await, class
Web APIfetch, IntersectionObserverService Worker (richiede supporto nativo)

Polyfill vs transpilazione: differenze e interazione

Transpilazione converte la sintassi nuova in sintassi vecchia (const → var, () => {} → function() {}). Polyfill aggiunge metodi e oggetti mancanti (Promise, Array.includes). Questi due meccanismi si completano a vicenda: la transpilazione rende il codice sintatticamente compatibile, i polyfill garantiscono la completezza dell'API. Babel + core-js è la combinazione standard per il supporto completo.

Babel @babel/preset-env con l'opzione useBuiltIns determina quali polyfill sono necessari in base ai browser target. useBuiltIns: "usage" analizza quali API vengono utilizzate nel codice e importa solo i polyfill necessari da core-js. useBuiltIns: "entry" importa tutti i polyfill per i browser target tramite un singolo import core-js/stable.

Esempio: polyfill per Array.prototype.includes

js
// Verifica dell'esistenza e aggiunta del 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,
  });
}

// Utilizzo — ora sicuro in qualsiasi browser
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true

Polyfill per Array.prototype.includes verifica se il metodo è definito sul prototipo Array. In caso contrario, crea la proprietà tramite Object.defineProperty con i flag writable: true, configurable: true. L'implementazione segue la specifica ES2016: controllo null/undefined, conversione in oggetto, gestione di fromIndex negativo. Dopo l'aggiunta del polyfill, la chiamata arr.includes(3) funziona in tutti i browser, incluso Internet Explorer 11.

core-js: la libreria standard di polyfill

core-js è la libreria di polyfill JavaScript più completa, che supporta tutte le proposte stage-4 di TC39 (standard ECMAScript). core-js include polyfill per Promise, Symbol, Map, Set, WeakMap, WeakSet, metodi Array, metodi String, metodi Object, metodi Number, metodi Math, Reflect, globalThis e tutte le proposte stage-4. La versione attuale core-js 3.38+ copre ES5–ES2025.

core-js si integra con Babel tramite @babel/preset-env e l'opzione useBuiltIns. Senza questa integrazione, gli sviluppatori dovrebbero importare manualmente ogni polyfill: import "core-js/stable/array/includes". @babel/preset-env aggiunge automaticamente le importazioni necessarie in base ai browser target da .browserslistrc. Questo riduce la dimensione del bundle — solo i polyfill necessari vengono inclusi.

Esempio: polyfill per fetch

Fetch API è una delle Web API più frequentemente polyfillate. L'implementazione nativa di fetch è disponibile in Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015), ma è assente in Internet Explorer e WebView vecchi. Il polyfill whatwg-fetch emula fetch tramite XMLHttpRequest. Alternativa — utilizzare isomorphic-fetch (un polyfill per Node.js e browser) o la libreria universale axios, che non richiede polyfill.

js
// Caricare polyfill fetch solo per browser vecchi
if (typeof self.fetch !== "function") {
  import("whatwg-fetch").then(module => {
    self.fetch = module.fetch;
    console.log("fetch polyfill loaded");
  });
}

// Usare fetch (funziona sia con polyfill che con API nativa)
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 dinamico del polyfill fetch tramite import() garantisce che i browser moderni non carichino codice non necessario. Il polyfill viene caricato in modo asincrono e non blocca il thread principale. Dopo il caricamento, self.fetch sostituisce l'implementazione nativa o aggiunge quella mancante. Questa è una tecnica di miglioramento progressivo: i browser moderni ricevono solo codice nativo, quelli vecchi ricevono il polyfill aggiuntivo.

Integrazione di core-js con Babel

js
// 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"],
      },
    }],
  ],
};
none
# .browserslistrc — browser target
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12

useBuiltIns: "usage" analizza il codice e aggiunge solo i polyfill effettivamente utilizzati. corejs.version specifica la versione di core-js nel progetto. targets.browsers definisce il livello minimo di browser — più i browser target sono vecchi, più polyfill verranno inclusi. .browserslistrc è utilizzato non solo da Babel ma anche da Autoprefixer, PostCSS e Stylelint per un targeting coerente.

Polyfill.io e caricamento dinamico dei polyfill

Polyfill.io è un servizio (e una libreria omonima) che determina dinamicamente quali polyfill il browser dell'utente necessita e restituisce solo quelli. Polyfill.io utilizza l'intestazione User-Agent per determinare la versione del browser e fornisce un set minimo di polyfill. Questo riduce la quantità di dati trasferiti rispetto a un bundle universale di polyfill.

La connessione di Polyfill.io avviene tramite un tag <script> prima del codice principale dell'applicazione. Il servizio analizza lo User-Agent e restituisce un file JavaScript con polyfill solo per quel browser. Chrome non riceverà alcun polyfill, IE 11 riceverà il set completo. Questo è un approccio ottimale per le prestazioni: i browser moderni non caricano codice non necessario.

Connessione di Polyfill.io

html
<!-- Polyfill.io: caricamento dinamico -->
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=Promise%2CArray.prototype.includes%2CObject.assign%2Cfetch"></script>

<!-- Versione locale di Polyfill.io -->
<script src="/js/polyfill.js"></script>
<script>
  // feature detection for fetch
  if (!self.fetch) {
    loadScript("/js/fetch-polyfill.js");
  }
</script>

Il parametro features nell'URL di Polyfill.io specifica quali polyfill caricare. Valori possibili: nomi di metodi (Array.prototype.includes), oggetti globali (Promise) o flag (es6, es2016). Il flag "default" carica un set base per JavaScript moderno. Per i progetti di produzione, si consiglia di ospitare Polyfill.io sul proprio CDN o utilizzare una versione locale della libreria per il controllo della disponibilità.

Polyfill nelle applicazioni mobili e WebView

WebView nelle applicazioni mobili (Android WebView, WKWebView su iOS) è un ambiente speciale per i polyfill. La versione di WebView dipende dalla versione del sistema operativo e dall'aggiornamento installato di Chrome System WebView (Android) o WKWebView di iOS Safari. Nelle versioni vecchie di Android (4.4, 5.0), WebView si basa su Chromium 30–37 — senza supporto per fetch, Promise, IntersectionObserver.

React Native utilizza JavaScriptCore (iOS) o Hermes (Android) — questi motori implementano ES6+ in modo diverso. JavaScriptCore su iOS supporta la maggior parte delle funzionalità ES6, ma potrebbe non avere alcune proposte stage-3. Hermes (utilizzato per impostazione predefinita in React Native 0.70+) supporta un set limitato dello standard ES — i polyfill sono obbligatori per esso.

Verifica del supporto in WebView

js
// feature detection per WebView
const polyfills = [];

// Promise
if (typeof Promise === "undefined") {
  polyfills.push("Promise");
}

// Fetch API
if (typeof self.fetch === "undefined") {
  polyfills.push("fetch");
}

// IntersectionObserver (necessario per lazy loading)
if (typeof IntersectionObserver === "undefined") {
  polyfills.push("IntersectionObserver");
}

// Caricamento dinamico di 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);
}

Rilevamento delle funzionalità per WebView verifica la presenza di API critiche (Promise, fetch, IntersectionObserver) e carica dinamicamente polyfill solo per quelle mancanti. Questo garantisce che i WebView moderni (Chrome 100+ su Android 12) non carichino codice non necessario, mentre i WebView vecchi (Android 5.0) ottengano il supporto necessario.

Domande frequenti

Sono necessari polyfill per React Native?

React Native su Hermes richiede polyfill per alcuni metodi ES: Array.flat, Array.flatMap, globalThis, TextEncoder. Si consiglia di includere core-js o react-native-polyfill-globals per le build di produzione. JavaScriptCore su iOS supporta più funzionalità, ma potrebbe anche richiedere polyfill per proposte stage-3.

I polyfill influiscono sulle prestazioni?

I polyfill riducono le prestazioni dell'1–5%, poiché l'implementazione JavaScript è più lenta dell'implementazione nativa in C++ nel motore. Ad esempio, un polyfill di Promise in JS puro è più lento di un Promise nativo in V8. Tuttavia, per la maggior parte delle applicazioni la differenza è trascurabile. Per il codice critico, si consiglia di verificare l'implementazione nativa tramite rilevamento delle funzionalità.

In cosa differisce il polyfill dalla transpilazione?

Transpilazione converte la sintassi: const → var, funzioni freccia → function. Polyfill aggiunge nuovi oggetti/metodi: Promise, Array.includes, fetch. La transpilazione funziona al momento della build, il polyfill viene caricato in fase di esecuzione. Entrambi i meccanismi sono necessari per il supporto completo del codice moderno in ambienti vecchi.

Si possono evitare i polyfill nel 2026?

, se il tuo pubblico di destinazione utilizza solo browser moderni (Chrome 90+, Safari 15+, Firefox 90+). Per i progetti che supportano dispositivi vecchi o utenti aziendali (Internet Explorer 11 è ancora utilizzato nel settore pubblico), i polyfill sono obbligatori. Analizza le statistiche dei browser del tuo pubblico tramite Google Analytics.

Quanto è grande il bundle di polyfill core-js?

core-js in una build completa pesa circa 85 KB (gzip). Utilizzando useBuiltIns: "usage" in Babel, vengono inclusi solo i polyfill necessari, riducendo la dimensione a 5–30 KB a seconda dei browser target. Per i browser moderni (Chrome 100+), potrebbe non essere necessario alcun polyfill.

Riepilogo

  • Polyfill è un'emulazione di un'API mancante in un ambiente di esecuzione, che garantisce la compatibilità del codice moderno con ambienti vecchi
  • core-js è la libreria standard di polyfill per ES5–ES2025, integrata con Babel tramite @babel/preset-env
  • Polyfill.io è un servizio di caricamento dinamico di polyfill basato sullo User-Agent del browser
  • Transpilazione + polyfill è una soluzione completa: Babel trasforma la sintassi, core-js aggiunge le API mancanti
  • Rilevamento delle funzionalità verifica l'implementazione nativa prima di caricare un polyfill per le prestazioni
  • WebView e Hermes richiedono polyfill obbligatori per fetch, Promise e IntersectionObserver nelle versioni vecchie

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche