Polyfill : qu'est-ce que c'est, principe de fonctionnement et bibliothèques pour émuler une API

Auteur : IT Sectr Publié le : 2026-05-19 Temps de lecture : 9 min

Polyfill est un code qui émule des fonctionnalités manquantes (API, méthodes, objets) dans des environnements où elles ne sont pas implémentées nativement. Polyfill permet d'utiliser des fonctionnalités modernes de JavaScript, CSS ou Web API dans des navigateurs anciens et des environnements d'exécution. Selon MDN Web Docs, les polyfills sont un outil clé pour l'amélioration progressive et la compatibilité entre navigateurs.

Points essentiels

  • Polyfill est une émulation logicielle d'une API manquante dans un environnement d'exécution où cette API n'est pas implémentée
  • core-js est la bibliothèque standard de polyfills pour JavaScript moderne avec le support de toutes les propositions stage-4
  • Polyfill.io est un service qui fournit dynamiquement des polyfills uniquement pour le navigateur de l'utilisateur
  • Transpilation vs polyfill : la transpilation transforme la syntaxe (arrow function → function), le polyfill ajoute de nouvelles méthodes (Array.includes, Promise)
  • Détection de fonctionnalités vérifie la présence d'une implémentation native avant de charger un polyfill pour éviter les conflits

Qu'est-ce que Polyfill ?

Polyfill est un fragment de code (généralement JavaScript) qui implémente des fonctionnalités que l'environnement d'exécution ne supporte pas nativement. Le terme a été inventé par Remy Sharp en 2009 comme un jeu de mots : Polyfill est analogue à Polyfilla, un enduit qui comble les fissures dans un mur. Polyfill comble les lacunes entre la norme et sa prise en charge dans un navigateur ou un environnement d'exécution spécifique.

Polyfill ne modifie pas le code existant — il étend l'environnement d'exécution. Si un navigateur ne supporte pas Array.prototype.includes, le polyfill ajoute cette méthode au prototype Array avant l'exécution du code principal. Les polyfills peuvent émuler de nouveaux objets globaux (Promise, Map, Set, Symbol), des méthodes statiques (Array.from, Object.assign) et des méthodes de prototype.

Détection de fonctionnalités est un mécanisme obligatoire avant d'installer un polyfill. Au lieu de vérifier le user-agent (quel navigateur), il faut vérifier l'existence de la méthode : if (!Array.prototype.includes) { Array.prototype.includes = ... }. Cela garantit que le polyfill n'écrase pas l'implémentation native si elle existe déjà. Google Analytics et d'autres services collectent des données de support d'API pour analyse.

Quand les polyfills sont apparus

Les premiers polyfills sont apparus à l'époque d'Internet Explorer 6–8 (2005–2009), lorsque les développeurs ont découvert un écart entre les normes W3C et les implémentations des navigateurs. Le terme a été introduit par Remy Sharp en 2009 au BarCamp London. Le premier polyfill de masse a été html5shiv (2009) — une bibliothèque qui ajoute la prise en charge des balises HTML5 (<section>, <article>, <nav>) dans Internet Explorer.

Avec l'avènement d'ES6 (2015) et du cycle annuel de mises à jour ECMAScript, le nombre de polyfills nécessaires a augmenté. Chaque année, la norme ajoute de nouvelles méthodes (Array.includes, String.padStart, Object.fromEntries, Promise.allSettled) qui ne sont pas supportées par les navigateurs anciens. core-js, démarré comme es6-shim en 2014, est devenu une solution universelle. En 2026, core-js contient plus de 5 000 modules de polyfill pour ES5–ES2025.

Ce qui peut et ne peut pas être polyfillé

CatégoriePeut être polyfilléNe peut pas être polyfillé
Méthodes de prototypeArray.includes, String.startsWith
Objets globauxPromise, Map, Set, Symbol
Méthodes statiquesObject.assign, Array.from
Syntaxe du langageArrow functions, async/await, class
Web APIfetch, IntersectionObserverService Worker (nécessite un support natif)

Polyfill vs transpilation : différences et interaction

Transpilation convertit la nouvelle syntaxe en ancienne syntaxe (const → var, () => {} → function() {}). Polyfill ajoute des méthodes et objets manquants (Promise, Array.includes). Ces deux mécanismes se complètent : la transpilation rend le code syntaxiquement compatible, les polyfills assurent la complétude de l'API. Babel + core-js est la combinaison standard pour un support complet.

Babel @babel/preset-env avec l'option useBuiltIns détermine quels polyfills sont nécessaires en fonction des navigateurs cibles. useBuiltIns: "usage" analyse quelles API sont utilisées dans le code et importe uniquement les polyfills nécessaires depuis core-js. useBuiltIns: "entry" importe tous les polyfills pour les navigateurs cibles via un seul import core-js/stable.

Exemple : polyfill pour Array.prototype.includes

js
// Vérification de l'existence et ajout du 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,
  });
}

// Utilisation — désormais sûr dans tous les navigateurs
const arr = [1, 2, 3, 4, 5];
console.log(arr.includes(3)); // true

Polyfill pour Array.prototype.includes vérifie si la méthode est définie sur le prototype Array. Si ce n'est pas le cas, il crée la propriété via Object.defineProperty avec les indicateurs writable: true, configurable: true. L'implémentation suit la spécification ES2016 : vérification de null/undefined, conversion en objet, gestion de fromIndex négatif. Après l'ajout du polyfill, l'appel arr.includes(3) fonctionne dans tous les navigateurs, y compris Internet Explorer 11.

core-js : la bibliothèque standard de polyfills

core-js est la bibliothèque de polyfills JavaScript la plus complète, supportant toutes les propositions stage-4 de TC39 (norme ECMAScript). core-js inclut des polyfills pour Promise, Symbol, Map, Set, WeakMap, WeakSet, les méthodes Array, les méthodes String, les méthodes Object, les méthodes Number, les méthodes Math, Reflect, globalThis et toutes les propositions stage-4. La version actuelle core-js 3.38+ couvre ES5–ES2025.

core-js s'intègre avec Babel via @babel/preset-env et l'option useBuiltIns. Sans cette intégration, les développeurs devraient importer manuellement chaque polyfill : import "core-js/stable/array/includes". @babel/preset-env ajoute automatiquement les importations nécessaires en fonction des navigateurs cibles depuis .browserslistrc. Cela réduit la taille du bundle — seuls les polyfills nécessaires sont inclus.

Exemple : polyfill pour fetch

Fetch API est l'une des Web API les plus fréquemment polyfillées. L'implémentation native de fetch est disponible dans Chrome 42+ (2015), Safari 10.1+ (2017), Firefox 39+ (2015), mais est absente d'Internet Explorer et des WebViews anciens. Le polyfill whatwg-fetch émule fetch via XMLHttpRequest. Une alternative — utiliser isomorphic-fetch (un polyfill pour Node.js et le navigateur) ou la bibliothèque universelle axios, qui ne nécessite pas de polyfills.

js
// Charger le polyfill fetch uniquement pour les anciens navigateurs
if (typeof self.fetch !== "function") {
  import("whatwg-fetch").then(module => {
    self.fetch = module.fetch;
    console.log("fetch polyfill loaded");
  });
}

// Utiliser fetch (fonctionne à la fois avec le polyfill et l'API native)
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 dynamique du polyfill fetch via import() garantit que les navigateurs modernes ne chargent pas de code inutile. Le polyfill se charge de manière asynchrone et ne bloque pas le thread principal. Après le chargement, self.fetch remplace l'implémentation native ou ajoute celle manquante. C'est une technique d'amélioration progressive : les navigateurs modernes reçoivent uniquement du code natif, les anciens reçoivent le polyfill supplémentaire.

Intégration de core-js avec 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 — navigateurs cibles
> 0.5%
last 2 versions
not dead
not op_mini all
ie >= 11
not ios_saf < 12

useBuiltIns: "usage" analyse le code et ajoute uniquement les polyfills réellement utilisés. corejs.version spécifie la version de core-js dans le projet. targets.browsers définit le niveau minimal de navigateurs — plus les navigateurs cibles sont anciens, plus il y aura de polyfills inclus. .browserslistrc est utilisé non seulement par Babel mais aussi par Autoprefixer, PostCSS et Stylelint pour un ciblage cohérent.

Polyfill.io et le chargement dynamique de polyfills

Polyfill.io est un service (et une bibliothèque du même nom) qui détermine dynamiquement quels polyfills le navigateur de l'utilisateur nécessite et ne retourne que ceux-ci. Polyfill.io utilise l'en-tête User-Agent pour déterminer la version du navigateur et fournit un ensemble minimal de polyfills. Cela réduit la quantité de données transférées par rapport à un bundle universel de polyfills.

La connexion de Polyfill.io se fait via une balise <script> avant le code principal de l'application. Le service analyse le User-Agent et retourne un fichier JavaScript avec des polyfills uniquement pour ce navigateur. Chrome ne recevra aucun polyfill, IE 11 recevra l'ensemble complet. C'est une approche optimale pour les performances : les navigateurs modernes ne chargent pas de code inutile.

Connexion de Polyfill.io

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

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

Le paramètre features dans l'URL de Polyfill.io spécifie quels polyfills charger. Les valeurs possibles : noms de méthodes (Array.prototype.includes), objets globaux (Promise) ou indicateurs (es6, es2016). L'indicateur "default" charge un ensemble de base pour JavaScript moderne. Pour les projets de production, il est recommandé d'héberger Polyfill.io sur votre propre CDN ou d'utiliser une version locale de la bibliothèque pour contrôler la disponibilité.

Polyfills dans les applications mobiles et WebView

WebView dans les applications mobiles (Android WebView, WKWebView sur iOS) est un environnement spécial pour les polyfills. La version de WebView dépend de la version du système d'exploitation et de la mise à jour installée de Chrome System WebView (Android) ou de WKWebView d'iOS Safari. Dans les anciennes versions d'Android (4.4, 5.0), WebView est basé sur Chromium 30–37 — sans support pour fetch, Promise, IntersectionObserver.

React Native utilise JavaScriptCore (iOS) ou Hermes (Android) — ces moteurs implémentent ES6+ différemment. JavaScriptCore sur iOS supporte la plupart des fonctionnalités ES6, mais peut manquer de certaines propositions stage-3. Hermes (utilisé par défaut dans React Native 0.70+) supporte un ensemble limité de la norme ES — les polyfills sont obligatoires pour celui-ci.

Vérification du support dans WebView

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

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

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

// IntersectionObserver (nécessaire pour le chargement différé)
if (typeof IntersectionObserver === "undefined") {
  polyfills.push("IntersectionObserver");
}

// Chargement dynamique de 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);
}

Détection de fonctionnalités pour WebView vérifie la présence d'API critiques (Promise, fetch, IntersectionObserver) et charge dynamiquement des polyfills uniquement pour celles manquantes. Cela garantit que les WebViews modernes (Chrome 100+ sur Android 12) ne chargent pas de code inutile, tandis que les WebViews anciennes (Android 5.0) obtiennent le support nécessaire.

Foire aux questions

Les polyfills sont-ils nécessaires pour React Native ?

React Native sur Hermes nécessite des polyfills pour certaines méthodes ES : Array.flat, Array.flatMap, globalThis, TextEncoder. Il est recommandé d'inclure core-js ou react-native-polyfill-globals pour les builds de production. JavaScriptCore sur iOS supporte plus de fonctionnalités, mais peut également nécessiter des polyfills pour les propositions stage-3.

Les polyfills affectent-ils les performances ?

Les polyfills réduisent les performances de 1–5 %, car l'implémentation JavaScript est plus lente que l'implémentation native en C++ dans le moteur. Par exemple, un polyfill de Promise en JS pur est plus lent qu'un Promise natif dans V8. Cependant, pour la plupart des applications, la différence est négligeable. Pour le code critique, il est recommandé de vérifier l'implémentation native via la détection de fonctionnalités.

En quoi un polyfill diffère-t-il de la transpilation ?

Transpilation convertit la syntaxe : const → var, fonctions fléchées → function. Polyfill ajoute de nouveaux objets/méthodes : Promise, Array.includes, fetch. La transpilation fonctionne au moment de la construction, le polyfill se charge à l'exécution. Les deux mécanismes sont nécessaires pour un support complet du code moderne dans des environnements anciens.

Peut-on éviter les polyfills en 2026 ?

Oui, si votre public cible utilise uniquement des navigateurs modernes (Chrome 90+, Safari 15+, Firefox 90+). Pour les projets supportant des appareils anciens ou des utilisateurs en entreprise (Internet Explorer 11 est encore utilisé dans le secteur public), les polyfills sont obligatoires. Analysez les statistiques de navigateurs de votre audience via Google Analytics.

Quelle est la taille du bundle de polyfills core-js ?

core-js dans une build complète pèse ~85 Ko (gzip). En utilisant useBuiltIns: "usage" dans Babel, seuls les polyfills nécessaires sont inclus, réduisant la taille à 5–30 Ko selon les navigateurs cibles. Pour les navigateurs modernes (Chrome 100+), aucun polyfill peut être nécessaire.

Résumé

  • Polyfill est une émulation d'une API manquante dans un environnement d'exécution, garantissant la compatibilité du code moderne avec les environnements anciens
  • core-js est la bibliothèque standard de polyfills pour ES5–ES2025, intégrée avec Babel via @babel/preset-env
  • Polyfill.io est un service de chargement dynamique de polyfills basé sur le User-Agent du navigateur
  • Transpilation + polyfills est une solution complète : Babel transforme la syntaxe, core-js ajoute les API manquantes
  • Détection de fonctionnalités vérifie l'implémentation native avant de charger un polyfill pour les performances
  • WebView et Hermes nécessitent des polyfills obligatoires pour fetch, Promise et IntersectionObserver dans les versions anciennes

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi