Certaines technologies récentes ne sont pas supportées de manière égale par les différents navigateurs présents sur le marché, et vous vous grattez régulièrement les cheveux à propos de la prise en charge de telle ou telle méthode lors de vos développements. Il arrive donc de devoir tester si telle ou telle fonctionnalité est supportée et ensuite de devoir déployer des solutions alternatives. Une vraie misère de développeur. Bonne nouvelle, les polyfills sont là pour nous aider.
Un polyfill représente tout simplement une légère surcouche visant à implémenter de manière homogène une fonctionnalité particulière de façon à en assurer la prise en charge sur tous les navigateurs.
En matière d’intégration web et de développement front-end, le concept de polyfill peut être étendu à d’autres langages comme HTML et CSS, mais ce n’est pas le sujet de cet article. Notez simplement que le fait de détecter le support d’une technologie et de déployer des solutions alternatives n’est pas une technique uniquement liée aux problèmes de conception rencontrés en Javascript.
Pour illustrer ce concept, prenons un exemple : l’implémentation de l’objet XHR dans les navigateurs et leurs versions. Car oui, un même navigateur peut présenter des implémentations différentes d’une version à l’autre, autrement ça ne serait plus drôle. L’objet XHR est implémenté différemment par Internet Explorer et le reste du monde. Ainsi, si je veux créer une instance de l’objet XHR de façon standardisée, j’ai tendance à écrire ceci :
var xhr = new XMLHttpRequest();
Oui mais voilà, malheureusement, toutes les opérations que je réaliserai via cette instance ne fonctionneront tout simplement pas sur Internet Explorer <= 9, ce qui est plutôt embêtant.
Alors, comment faire pour assurer portabilité, robustesse, maintenabilité et clarté du code ?! Il n’est absolument pas concevable de devoir, en aval, gérer deux instances différentes pour arriver à un même résultat. Dans la mesure où la fonctionnalité risque fort bien d’être utilisée à différents endroits dans le code, il n’est pas concevable non plus d’effectuer des traitements disparates afin de vérifier à qui l’on à faire.
Nous allons donc créer une fonction unique chargée de ces vérifications et des adaptations à apporter en fonction des forces en présences. C’est ici que notre polyfill entre en jeu pour assurer une prise en charge homogène de notre fonctionnalité.
function getXmlHttpRequest() {
var xhr;
// Si l'objet XMLHttpRequest est implémenté (navigateurs standards et IE >= 10)
if(window.XMLHttpRequest) {
return xhr = new XMLHttpRequest();
}
// Si l'objet ActiveXObject est implémenté (IE <= 9)
else if(window.ActiveXObject) {
// On sait qu'IE a changé son implémentation de l'objet XHR en cours de route
var versions = ["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];
// Pour chaque implémentation connue
for(var i in versions) {
// On essaye d'instancier et on retourne l'objet en cas de succès
try {
return xhr = new ActiveXObject(versions[i]);
} catch (e) {
// Gestion de l'erreur
}
}
}
// Le navigateur est trop vieux ou ne supporte pas l'objet XHR
else {
alert("Votre navigateur ne supporte pas l'objet XMLHttpRequest");
return xhr = false;
}
}
Voilà, nous pouvons à présent développer tranquillement nos scripts utilisant l'objet XHR pour faire des requêtes asynchrones sans nous soucier de leur prise en charge puisque, quoi qu'il arrive, nous instancierons notre objet grâce à la fonction getXmlHttpRequest()
. C'est là tout l'intérêt d'un polyfill.
Il existe de nombreux polyfills et il est plutôt rare d'avoir à en développer un soi-même. Les plus connus sont certainement ceux assurant la prise en charge de fonctionnalités très usitées comme trim()
, isArray()
ou encore forEach()
. Le MDN regorge de polyfills connus et les propose directement en documentation des méthodes standardisées. Une bonne recherche sur le net vous livrera également généralement le polyfill que vous souhaitez implémenter.