Une nouvelle méthode arrive dans le langage, la documentation en parle, vous l'utilisez. Puis un visiteur signale une erreur depuis un appareil de cinq ans, sur lequel cette méthode n'existe pas.
Un polyfill règle ce cas sans renoncer à écrire du code moderne : il fournit la fonction manquante, écrite en JavaScript ordinaire.
Définition
Un polyfill est un morceau de code qui implémente une fonctionnalité absente du moteur d'exécution, en n'utilisant que ce que ce moteur sait déjà faire. Il s'installe une fois, au chargement, et le reste du programme n'a plus à se poser la question.
// Polyfill de Array.prototype.at
if (!Array.prototype.at) {
Array.prototype.at = function (index) {
const i = Math.trunc(index) || 0;
const position = i < 0 ? this.length + i : i;
if (position < 0 || position >= this.length) return undefined;
return this[position];
};
}
console.log([10, 20, 30].at(-1)); // 30La condition if est le coeur du procédé : si le moteur fournit déjà la méthode, la sienne est conservée. Un polyfill ne remplace jamais l'implémentation native, il ne comble qu'un vide.
Trois notions voisines à distinguer
| Terme | Ce qu'il traite |
|---|---|
| Polyfill | Une fonction manquante, installée sur l'objet natif |
| Transpilation | Une syntaxe non comprise, réécrite avant l'envoi |
| Ponyfill | La même fonction, mais exportée sans toucher au natif |
La troisième option est la plus prudente : au lieu de modifier Array (tableau) pour toute la page, elle expose une fonction que vous importez explicitement. Aucun risque de conflit avec une bibliothèque tierce qui ferait le même travail autrement.
Modifier un objet natif engage l'ensemble de la page, y compris les scripts que vous n'avez pas écrits. Un polyfill approximatif produit alors des bugs très difficiles à situer, puisqu'ils se manifestent loin du fichier fautif.
Ne pas les charger pour tout le monde
Envoyer un lot de polyfills à chaque visiteur pénalise ceux dont le navigateur n'en a aucun besoin, c'est-à-dire la majorité. Deux approches évitent ce gaspillage.
La première consiste à laisser Babel injecter uniquement les polyfills correspondant aux fonctionnalités réellement employées, en fonction des navigateurs visés. La seconde teste la présence de la fonctionnalité au démarrage et ne charge le complément que si nécessaire, par import() (import dynamique).
Questions fréquentes
Faut-il écrire ses polyfills soi-même ?
Non, sauf pour comprendre le mécanisme. Les cas limites sont nombreux, souvent contre-intuitifs, et une bibliothèque éprouvée les traite déjà. Une implémentation maison qui diverge légèrement de la spécification est pire qu'une absence de polyfill, car l'erreur devient silencieuse.
Tout peut-il être comblé de cette façon ?
Non. Une méthode ou un objet manquant se reconstruit, mais une syntaxe inconnue provoque une erreur avant même l'exécution : aucun code ne peut la rattraper. De même, une fonctionnalité qui exige un accès matériel ne s'imite pas en JavaScript.
En ai-je encore besoin aujourd'hui ?
De moins en moins pour le grand public, les navigateurs se mettant à jour tout seuls. La question se pose encore pour les environnements figés, comme certains navigateurs intégrés à des applications ou du matériel ancien. Partez des statistiques de votre site plutôt que d'une impression générale.