Utilise-t-on encore des polyfills en 2026 ?
Des polyfills en 2026 ? Auditez core-js, Browserslist et Babel pour supprimer le poids mort, garder Temporal et abandonner polyfill.io.
Oui — mais presque aucun de ceux hérités par votre bundler. La configuration de polyfills en masse qui avait du sens en 2019 — livrer @babel/preset-env avec useBuiltIns: 'entry' contre une cible Browserslist large — envoie aujourd’hui du lest à l’écrasante majorité des utilisateurs pour prendre en charge une part de marché navigateur qui arrondit à zéro. Un polyfill reste le bon outil pour une liste courte et nommée de fonctionnalités genuinement non supportées en 2026 — et un risque pour tout le reste.
Cet article tranche une seule décision : si les polyfills de votre pipeline de build actuel méritent encore leurs octets. Il identifie quelles API constituent du lest inutile, lesquelles nécessitent encore légitimement un polyfill, ce que l’incident de la chaîne d’approvisionnement de polyfill.io a changé dans la façon de les charger, et les commandes exactes pour auditer ce que vous livrez réellement.
Points clés à retenir
- Pour une application React, Vue, Svelte ou Next.js ciblant des navigateurs evergreen en 2026, le nombre correct de polyfills pour la plupart des équipes est proche de zéro — avec des exceptions nommées pour Decorators, Temporal pendant sa transition cross-navigateur, et les contraintes de navigateurs d’entreprise verrouillés.
Array.flat,Object.entries,Promise.allSettled,structuredClone, le chaînage optionnel, la coalescence nulle etfetchsont tous largement supportés en 2026 ; les polyfiller envoie des octets qui ne servent presque aucun utilisateur réel.- Le pattern de service de polyfills distant (chargement d’un script depuis polyfill.io) est mort après l’incident de la chaîne d’approvisionnement de 2024 ; Cloudflare et Fastly ont mis en place des miroirs, mais le pattern lui-même n’est plus défendable.
- Exécutez
npx browserslistpour voir les navigateurs exacts ciblés par votre configuration, puis utilisezsource-map-explorerpour identifier le poids decore-jsque vous livrez. - La classification Enhancement / Additive / Critical de web.dev est le cadre le plus solide pour décider si une fonctionnalité manquante justifie un polyfill.
La base de support natif en 2026 : ce que vous n’avez plus besoin de polyfiller
La plupart des fonctionnalités JavaScript que les configurations de build polyfillent encore systématiquement sont désormais supportées par tous les navigateurs evergreen, ce qui signifie que les polyfiller envoie des octets dont presque aucun utilisateur réel n’a besoin. Les fonctionnalités qui ont ancré les tutoriels sur les polyfills pendant une décennie — Math.trunc, Array.prototype.flat, le chaînage optionnel — sont maintenant largement supportées et constituent exactement le lest qu’un audit 2026 devrait supprimer.
L’exemple pédagogique emblématique, le polyfill Math.trunc de javascript.info, en est l’illustration la plus claire. Math.trunc bénéficie d’un support universel depuis 2015 — selon les données de compatibilité MDN, il est disponible depuis Chrome 38, Firefox 25 et Safari 8. Écrire ou bundler un polyfill Math.trunc en 2026, c’est livrer une clause de garde pour un navigateur que personne n’utilise.
Il en va de même pour l’ensemble des API que les configurations obsolètes ciblent encore. Les pourcentages de support ci-dessous sont issus des données d’utilisation mondiale de caniuse.com (StatCounter, mai 2026) ; le « support mondial » désigne la part de marché pondérée des navigateurs suivis par caniuse.
| Fonctionnalité | Support mondial (caniuse, 2026) | Vaut-il encore la peine de la polyfiller ? |
|---|---|---|
Array.prototype.flat | 94,11 % | Non |
Object.entries | 95,06 % | Non |
Promise.allSettled | 94,04 % | Non |
structuredClone | 93,84 % | Non |
Chaînage optionnel (?.) | 93,99 % | Non (syntaxe — transpiler, ne pas polyfiller) |
Coalescence nulle (??) | 93,99 % | Non (syntaxe — transpiler, ne pas polyfiller) |
fetch | 96,3 % | Non |
Temporal | 65,16 % | Oui — transitoire |
| Decorators | 0 % natif | Oui |
Array.flat, Object.entries, Promise.allSettled, structuredClone, le chaînage optionnel, la coalescence nulle et fetch affichent tous un support mondial d’environ 94 à 96 % — et si votre configuration Babel polyfille encore ces fonctionnalités, vous livrez des octets qui ne servent presque aucun utilisateur.
Syntaxe vs. fonctions : Le chaînage optionnel et la coalescence nulle sont de la syntaxe, pas des fonctions manquantes, et sont donc gérés par un transpileur, pas un polyfill. Comme le formule javascript.info : utilisez un transpileur pour la syntaxe et les opérateurs modernes, et des polyfills pour les fonctions manquantes. La distinction est importante lors d’un audit — un « polyfill »
??dans votre configuration signale que les deux ont été confondus.
Quels polyfills méritent encore leur place en 2026 ?
Discover how at OpenReplay.com.
Les polyfills restent le bon outil pour un ensemble restreint et nommé de cas : les fonctionnalités sans support natif nulle part, les fonctionnalités en cours de transition entre navigateurs, et les environnements à navigateur verrouillé où l’hypothèse evergreen ne tient pas. Ce sont les exceptions qui justifient de conserver un mécanisme de polyfill dans votre pipeline.
Decorators. La proposition TC39 sur les decorators est au Stade 3 sans aucune implémentation native dans les navigateurs. Si vous utilisez des decorators — directement, ou via un framework comme Angular ou une bibliothèque qui en dépend — vous vous appuyez sur un transpileur et, dans certains cas, des helpers d’exécution. Il n’existe pas encore d’option « attendre le support natif » ; la fonctionnalité n’est pas disponible dans les navigateurs.
Temporal, pendant sa transition cross-navigateur. Temporal est une proposition TC39 finalisée — elle figure sur la liste des propositions finalisées de TC39 — et a commencé à être disponible nativement. Selon les données de compatibilité MDN pour Temporal, il est disponible dans Firefox 139+, Chrome 144+, Edge 144+ et Node.js 26+, tandis que Safari ne dispose pas encore du support activé. Ce déploiement inégal fait d’un polyfill Temporal une nécessité transitoire plutôt que permanente. Le dépôt proposal-temporal de TC39 liste @js-temporal/polyfill comme option en version alpha aux côtés d’alternatives — ce n’est pas le seul choix canonique.
Environnements d’entreprise et navigateurs verrouillés. Les systèmes financiers réglementés, les intranets gouvernementaux, et les appareils kiosque ou point de vente épinglent parfois une version de navigateur pendant des années. Si votre base d’utilisateurs réels inclut des navigateurs qui ne peuvent pas se mettre à jour, votre cible Browserslist est plus large que la valeur par défaut evergreen et certains polyfills sont essentiels. Le mot clé est réels — ce cas est invoqué bien plus souvent qu’il n’est mesuré. Validez-le avec vos analytics avant de conserver des polyfills pour cette raison.
Fonctionnalités CSS à disponibilité limitée derrière des polyfills JS. Certaines capacités CSS, comme les container queries sur les anciennes versions de Safari, ont été polyfillées en JavaScript lors de leur déploiement. Comme le note web.dev, le polyfill des container queries utilise ResizeObserver et MutationObserver pour simuler le comportement natif — et son README indique qu’il n’est plus maintenu. Ces polyfills comportent des mises en garde comportementales abordées ci-dessous.
Le consensus général — « utilisez des polyfills ciblés, basez vos décisions sur des données » — n’est pas faux, mais il sous-estime l’ampleur des changements : pour la plupart des applications en 2026, affirmer que « les polyfills continuent de jouer un rôle important » n’est plus exact. Ce rôle est désormais restreint et bien délimité.
L’incident polyfill.io a tué le pattern de service de polyfills distant
Le pattern de service de polyfills distant — charger un <script> depuis un CDN tiers qui retourne des polyfills adaptés au navigateur — n’est plus une architecture défendable après l’attaque sur la chaîne d’approvisionnement de polyfill.io en 2024. L’incident a contraint les équipes à auditer ce qu’elles chargeaient depuis des tiers, et la plupart ont constaté qu’elles n’en avaient pas besoin.
La chronologie :
- Début 2024 — changement de propriété. Le domaine polyfill.io a changé de mains. Le billet communautaire de Fastly documente ce changement et la réponse de Fastly pour les utilisateurs concernés.
- 25 juin 2024 — signalement de malware. La société de sécurité Sansec a rapporté que le service polyfill.io injectait des malwares dans les scripts servis aux utilisateurs finaux.
- Juin 2024 — miroirs et mesures d’atténuation. Cloudflare a annoncé le remplacement automatique des liens polyfill.io par son propre miroir, et Fastly a proposé un endpoint de remplacement.
Les miroirs maintiennent le fonctionnement des sites existants, mais ils ne réhabilitent pas le pattern. Un mode de défaillance standard en production mis en évidence par cet incident : des équipes avaient une balise script cdn.polyfill.io chargeant des bundles de polyfills dont elles n’avaient plus besoin depuis des années, exécutant du JavaScript tiers à chaque chargement de page pour prendre en charge des navigateurs qui s’étaient depuis mis à jour. Ne traitez pas le miroir Cloudflare ou Fastly comme un remplacement « sûr » — traitez l’incident comme le signal de supprimer complètement la balise script et d’intégrer les polyfills genuinement nécessaires dans votre propre bundle, où vous les contrôlez et les révisez.
Comment auditer ce que votre bundler livre réellement
Auditer votre empreinte de polyfills est une séquence en quatre étapes : lire votre vraie cible Browserslist, inspecter le bundle pour le poids de core-js, corriger la configuration Babel, et valider avec des données d’utilisateurs réels. Rien de tout cela ne nécessite de suppositions — chaque étape est une commande ou un diff de configuration que vous pouvez exécuter aujourd’hui.
Étape 1 : Voir votre liste de cibles réelle
Les requêtes Browserslist déterminent quels navigateurs votre configuration supporte, et la seule façon fiable de savoir ce que la vôtre résout est de l’interroger directement :
npx browserslist
Cette commande affiche la liste concrète de versions de navigateurs que votre configuration actuelle cible. Les valeurs par défaut de Browserslist (> 0.5%, last 2 versions, Firefox ESR, not dead) excluent déjà IE11 via not dead. Le vrai risque est une requête personnalisée héritée — un > 0.2% errant ou un plancher de version explicite vieux de plusieurs années — qui inclut silencieusement d’anciennes cibles. Exécutez la commande ; si la sortie inclut des navigateurs qu’aucun utilisateur réel n’utilise, c’est votre lest inutile.
Étape 2 : Trouver le poids de core-js dans votre bundle
core-js est la bibliothèque de polyfills depuis laquelle @babel/preset-env injecte, et elle peut représenter une fraction substantielle d’un bundle qui n’en a pas besoin. Inspectez un build de production :
npx source-map-explorer dist/assets/*.js
source-map-explorer génère une treemap de ce qui se trouve dans chaque bundle à partir de ses source maps. Cherchez les modules core-js — es.array.flat, es.object.entries, es.promise.all-settled. Chacun correspond à une fonctionnalité du tableau des lests inutiles ci-dessus. (Pour les projets webpack, webpack-bundle-analyzer offre la même vue.)
Étape 3 : Corriger la configuration Babel
La configuration canonique héritée par la plupart des équipes est incomplète. Un pattern courant ressemble à ceci :
{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "usage",
"corejs": 3
}]
]
}
Cette configuration présente deux problèmes. Premièrement, il n’y a pas de champ targets, donc la configuration se rabat sur votre fichier Browserslist — qui peut être la requête personnalisée obsolète de l’étape 1. Deuxièmement, corejs: 3 n’est pas épinglé à une version mineure ; selon la documentation de core-js, la version doit spécifier un mineur pour que preset-env injecte des polyfills correspondant à la version installée. Une version adaptée à 2026 :
{
"presets": [
["@babel/preset-env", {
"targets": "> 1%, last 2 versions, not dead",
"useBuiltIns": "usage",
"corejs": "3.40"
}]
]
}
Épinglez corejs à la version mineure que vous avez réellement installée plutôt que de copier n’importe quel numéro — preset-env l’utilise pour décider quels polyfills existent à injecter.
La valeur de useBuiltIns est le paramètre le plus déterminant. Selon la documentation de @babel/preset-env :
'entry'remplace un seulimport 'core-js'par l’ensemble complet des polyfills requis par vostargets— large, et la source de la plupart des surcharges héritées.'usage'ajoute des polyfills uniquement pour les fonctionnalités que votre code référence réellement, par fichier. C’est presque toujours ce que vous voulez : cela limite l’injection de polyfills à l’utilisation réelle plutôt qu’à l’ensemble de votre matrice de cibles.
Étape 4 : Valider avec des données d’utilisateurs réels
Une configuration est une hypothèse sur vos utilisateurs ; les données RUM la confirment ou l’infirment. web.dev recommande de mesurer le support réel des fonctionnalités avant de décider de les polyfiller, et pointe vers RUM Insights comme source de données globale. Le pattern observé : les fonctionnalités dans l’ensemble Baseline Widely available sont supportées par 98 % ou plus des utilisateurs. Si vos analytics montrent qu’une fonctionnalité approche ce seuil, le polyfill correspondant sert une fraction qui arrondit à du bruit.
Quand polyfiller ? Le cadre Enhancement, Additive, Critical
Lorsqu’une fonctionnalité n’est genuinement pas supportée par votre base d’utilisateurs réels, la classification Enhancement / Additive / Critical de web.dev est l’heuristique la plus utile pour décider de polyfiller : si une fonctionnalité manquante est invisible pour les utilisateurs, ne la polyfilllez pas ; si elle se dégrade gracieusement, penchezvers le non-polyfillage ; ce n’est que si son absence brise l’expérience qu’un polyfill justifie son coût en performance.
Les trois niveaux, tels que web.dev les définit :
- Enhancement — la fonctionnalité améliore l’expérience, mais son absence ne produit aucun changement visuel ni perte de fonctionnalité. Les hints de performance comme
fetchpriorityen sont l’exemple. Les utilisateurs sur des navigateurs non supportés ne le remarqueront pas. Ne pas polyfiller. - Additive — la fonctionnalité peut affecter l’apparence ou le comportement d’une page, mais pas de façon à créer de problèmes sérieux ; un utilisateur ne le remarquerait qu’en comparant des navigateurs. Si un polyfill existe, penchez plutôt vers le non-usage, surtout si vous polyfilllez déjà d’autres choses. Les fonctions de couleur et subgrid en sont des exemples.
- Critical — l’absence provoque une expérience brisée : erreurs d’exécution, mises en page cassées, fonctionnalités inutilisables. C’est ici qu’un polyfill (ou une approche entièrement différente) est justifié.
La règle d’ancrage de web.dev s’associe parfaitement au tableau de support ci-dessus : si une fonctionnalité est Widely available, vous ne devriez pas recourir à un polyfill — sauf si vous disposez de données sur vos utilisateurs qui vous indiquent explicitement le contraire.
Pourquoi les bugs de polyfill se cachent — et comment le session replay les révèle
Les bugs de polyfill appartiennent à une catégorie que les suites de tests standard ratent complètement : ils ne se manifestent que dans la tranche de navigateurs qui a déclenché le polyfill, qui n’est jamais le navigateur evergreen sur lequel votre CI s’exécute. Le session replay est l’une des rares techniques d’observabilité qui capture l’état DOM réel de ces utilisateurs, car il enregistre la séquence d’interaction et de mutation réelle depuis le navigateur qui a emprunté le chemin du polyfill.
Le session replay révèle trois patterns concrets de divergence entre les chemins de code polyfillés et natifs :
- Timing des décalages de mise en page dans le polyfill des container queries. Comme le note web.dev, le polyfill des container queries pilote la mise en page depuis des callbacks
ResizeObserver, qui se déclenchent juste avant que le navigateur peigne une nouvelle frame — augmentant le délai de présentation et affectant l’Interaction to Next Paint. Un timing de rendu différé peut produire des décalages de mise en page qui ne sont observables que dans les navigateurs ayant besoin du polyfill. - Divergence de fuseaux horaires avec Temporal. Pendant la transition cross-navigateur de Temporal, les équipes peuvent avoir besoin de tester les implémentations
Temporalnatives et polyfillées pour garantir un comportement cohérent entre navigateurs. Votre suite de tests peut ne s’exécuter que sur un seul chemin d’implémentation, tandis que les utilisateurs réels en rencontrent un autre ; les replays depuis des navigateurs où les implémentations native et polyfillée coexistent peuvent aider à révéler ces différences. - Lacunes dans la gestion du focus. Les polyfills axés sur l’accessibilité peuvent introduire des problèmes subtils de navigation au clavier et de gestion du focus dans les navigateurs sans support natif — le type de mode de défaillance que web.dev souligne plus généralement. Un replay avec capture des événements clavier montre l’utilisateur naviguant par tabulation à travers un arrière-plan modal, ce qu’un test automatisé réussi contre le polyfill ne révèlera pas.
Dans chaque cas, le facteur commun est le même : le bug vit dans la tranche d’utilisateurs que votre environnement de développement ne reproduit jamais. C’est la raison structurelle de livrer moins de polyfills — chaque chemin de polyfill que vous supprimez est un chemin de divergence que vous n’avez plus à surveiller.
Actions concrètes à entreprendre cette semaine
Réduire votre empreinte de polyfills est une séquence de petites modifications réversibles, chacune validée par rapport au bundle et à vos utilisateurs. L’objectif est de livrer du natif quand vous le pouvez, de charger conditionnellement pour la longue traîne genuinement nécessaire, et de supprimer tout le reste.
- Exécutez
npx browserslistet supprimez toute requête personnalisée héritée qui cible des navigateurs qu’aucun utilisateur réel n’utilise. Revenir à une cible plus stricte et actuelle est le changement à plus fort levier. - Définissez
useBuiltIns: 'usage'et un champtargetsexplicite dans votre configuration@babel/preset-env, et épinglezcorejsà votre version mineure installée. - Comparez le bundle avant et après avec
source-map-explorerpour confirmer que le poids decore-jsa réellement diminué, puis exécutez vos tests pour vérifier que rien de nécessaire n’a disparu. - Supprimez complètement toute balise script
cdn.polyfill.io; intégrez les polyfills genuinement nécessaires dans votre propre bundle. - Chargez conditionnellement les exceptions genuines. Pour Temporal pendant sa transition, chargez le polyfill uniquement pour les navigateurs qui en ont besoin plutôt que de le livrer à tout le monde. Pour Decorators, appuyez-vous sur la transpilation et les helpers d’exécution là où c’est nécessaire. Le point de web.dev selon lequel les polyfills pour les fonctionnalités à disponibilité limitée doivent être chargés conditionnellement s’applique directement.
- Validez avec des données RUM avant et après, afin que l’audit repose sur vos utilisateurs, pas sur la moyenne mondiale.
Conclusion
La réponse honnête en 2026 à la question de savoir si quelqu’un utilise encore des polyfills est oui — mais la liste défendable est courte et spécifique : Decorators, Temporal pendant qu’il franchit l’écart entre navigateurs, et les environnements à navigateur verrouillé que vous avez réellement mesurés. Tout le reste hérité par votre configuration représente des octets dépensés pour une part de marché de navigateurs qui arrondit à zéro, et l’incident polyfill.io rappelle que les charger de façon imprudente comporte un risque réel. Commencez par npx browserslist aujourd’hui ; l’écart entre ce qu’il affiche et les navigateurs que vos utilisateurs utilisent réellement est votre budget de polyfills, et pour la plupart des équipes, il est bien plus petit que ce que la configuration suppose.
FAQ
Quelle est la différence entre un polyfill et un transpileur ?
Un transpileur réécrit la syntaxe moderne en un équivalent plus ancien au moment du build, tandis qu'un polyfill ajoute une implémentation de fonction ou d'API manquante à l'exécution. Les fonctionnalités syntaxiques comme le chaînage optionnel et la coalescence nulle sont gérées par un transpileur car ce sont des opérateurs du langage, pas des fonctions appelables. Les API comme Promise.allSettled ou structuredClone sont gérées par des polyfills car ce sont des méthodes manquantes que le code d'exécution peut fournir. Un « polyfill » de coalescence nulle dans votre configuration signale que les deux ont été confondus.
Quelle est la différence entre useBuiltIns 'usage' et 'entry' dans babel-preset-env ?
Avec useBuiltIns défini sur 'entry', Babel remplace un seul import core-js par l'ensemble complet des polyfills requis par vos targets, ce qui est la source de la plupart des surcharges de bundle héritées. Avec 'usage', Babel injecte des polyfills uniquement pour les fonctionnalités que votre code référence réellement, par fichier. La valeur 'usage' est presque toujours préférable car elle livre des polyfills pour l'utilisation réelle plutôt que pour l'ensemble de votre matrice de cibles. Les deux nécessitent une version corejs épinglée à votre version mineure installée.
Est-il sûr de continuer à utiliser polyfill.io via le miroir Cloudflare ou Fastly ?
Les miroirs Cloudflare et Fastly maintiennent le fonctionnement des sites existants, mais ils ne réhabilitent pas le pattern de service de polyfills distant. Après que le domaine polyfill.io a changé de propriété début 2024 et que Sansec a rapporté le 25 juin 2024 que le service injectait des malwares, charger des polyfills adaptés au navigateur depuis un CDN tiers est devenu indéfendable pour les équipes soucieuses de la sécurité. Supprimez complètement la balise script cdn.polyfill.io et intégrez les polyfills genuinement nécessaires dans votre propre bundle, où vous les contrôlez et les révisez.
Ai-je encore besoin de core-js si mon application cible uniquement des navigateurs evergreen ?
Pour la plupart des applications ciblant des navigateurs evergreen en 2026, core-js livre près de zéro polyfills utiles, car des fonctionnalités comme Array.flat, Object.entries, Promise.allSettled, structuredClone et fetch sont déjà largement supportées. Les exceptions nommées sont Decorators, qui n'a aucune implémentation native dans les navigateurs, et Temporal pendant son déploiement inégal entre navigateurs. Exécutez source-map-explorer sur un build de production pour voir quels modules core-js sont présents, puis resserrez votre cible Browserslist et passez useBuiltIns à 'usage' pour supprimer le lest inutile.