[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Learn_web_development/Core/Scripting/Debugging_JavaScript [Back]  [Original]

Grer les problmes courants en JavaScript - Apprendre | MDN

Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.

View in English Always switch to English

Grer les problmes courants en JavaScript

Dans cet article, nous verrons certains problmes frquents qui se posent entre les diffrents navigateurs avec JavaScript, et aussi comment les rsoudre.

Pour cela, nous aborderons entre autres les outils de dveloppement des navigateurs pour diagnostiquer et corriger les problmes, les prothses d'mulation (ou polyfills) et les bibliothques pour contourner les problmes en parvenant faire fonctionner des fonctionnalits JavaScript rcentes dans d'anciens navigateurs.

Prrequis : Connaissance des bases de HTML, CSS, et JavaScript. Une ide gnrale des principes de tests entre les diffrents navigateurs.
Objectifs : tre capable de diagnostiquer les problmes frquents, causs par JavaScript, entre les diffrents navigateurs et utiliser les techniques et outils appropris pour les rsoudre.

Dans cet article

Le problme avec JavaScript

Par le pass, JavaScript tait la source de nombreux problmes de compatibilit entre les diffrents navigateurs. Dans les annes 1990, les navigateurs principaux existants alors (Internet Explorer et Netscape) n'implmentaient pas les scripts avec exactement le mme langage (Netscape utilisait JavaScript, et IE utilisait JScript en permettant aussi d'utiliser VBScript). Bien que JavaScript et JScript taient compatibles un certain niveau (les deux taient bass sur la spcification ECMAScript), la plupart des choses taient implmentes de faon incompatible et conflictuelle, entranant des nuds au cerveau lorsqu'il fallait dvelopper un site web compatible.

De tels problmes ont subsist jusqu'aux dbuts des annes 2000, o ces anciens navigateurs taient alors encore utiliss et o il fallait continuer de les prendre en charge. Par exemple, dans du code utilis pour crer un objet XMLHttpRequest, il fallait grer le cas particulier d'Internet Explorer 6 :

js
if (window.XMLHttpRequest) {
  // Mozilla, Safari, IE7+
  httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
  // IE 6 et les versions antrieures
  httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}

C'est l'une des raisons pour lesquelles des bibliothques comme jQuery sont apparues : permettre de gommer les diffrences d'implmentation entre les navigateurs afin de pouvoir utiliser une fonction comme jQuery.ajax(), qui grerait ces diffrences en arrire-plan.

La situation s'est grandement amliore depuis. Les navigateurs modernes ont une bonne compatibilit concernant les fonctionnalits JavaScript classiques, et les contraintes o il fallait prendre en charge les anciens navigateurs se sont allgs (ceux-ci tant beaucoup moins utiliss, mais toujours existants).

De nos jours, les problmes de compatibilit JavaScript entre les diffrents navigateurs se posent lorsque :

  • Du code de pitre qualit essayant de dterminer le navigateur utilis ou essayant de dtecter certaines fonctionnalits, ou encore utilisant des prfixes propritaires empche les navigateurs d'excuter du code qui aurait fonctionn correctement sinon.
  • Des fonctionnalits trs rcemment ajoutes JavaScript ou des API Web rcentes sont prsentes dans le code, et cela ne fonctionne pas pour les navigateurs plus anciens.

Nous verrons ces diffrents problmes, ainsi que d'autres, par la suite.

Rsolution gnrale des problmes en JavaScript

Comme nous l'avons dit dans l'article prcdent propos de HTML et CSS, assurez vous que votre code fonctionne dj normalement avant de vous concentrer sur les problmes entre les navigateurs. Si vous n'avez pas lu l'article Diagnostiquer des problmes JavaScript, nous vous invitons le faire avant de poursuivre. En effet, identifier de nombreux problmes rencontrs avec JavaScript comme ceux-ci pourra vous aider mieux diagnostiquer un problme de compatibilit. Parmi les problmes frquents causs par JavaScript, on a :

  • Les problmes de syntaxe et de logique de base (voir Diagnostiquer des problmes JavaScript).

  • La gestion des portes pour la dfinition des variables : s'assurer qu'il n'y a pas de conflits entre les diffrentes valeurs dclares diffrents endroits (Voir Porte d'une fonction et conflits).

  • La confusion propos de this, la porte laquelle il s'applique, pouvant changer la valeur laquelle on s'attend. Vous pouvez lire Qu'est-ce que  this  ? comme introduction ce sujet, et aussi tudier quelques exemples comme celui-ci, qui illustre un usage classique o on enregistre la valeur de this pour une porte donne dans une variable spare afin de l'utiliser dans des fonctions imbriques, pour tre sre d'appliquer le code au bon this.

  • L'usage incorrect de fonctions au sein de boucles qui utilisent une variable globale (ce qui correspond plus gnralement une confusion sur les portes). Par exemple, dans bad-for-loop.html (voir le code source), on excute 10 itrations en utilisant une variable dfinie avec var, en crant chaque fois un paragraphe auquel on attache un gestionnaire d'vnement onclick. Lorsqu'on clique sur les paragraphes, on souhaite afficher un message d'alerte indiquant le numro du paragraphe (c'est--dire la valeur de i au moment o le paragraphe a t ajout). Au lieu de ce rsultat, tous les messages d'alertes affichent la valeur 11, car la boucle for a termin ses itrations avant que les fonctions imbriques soient appeles.

    Note : La solution la plus simple consiste dclarer la variable d'itration avec let plutt que var pour que la valeur i associe chaque fonction soit unique pour chaque itration. Malheureusement, cela ne fonctionne pas avec IE11, et c'est pourquoi nous n'avons pas utilis cette solution pour la version correcte de cet exemple.

    Pour que cela fonctionne, il faut dfinir sparment une fonction attacher aux gestionnaires, et l'appeler chaque itration en lui passant la valeur courante pour para et i. Voir le fichier good-for-loop.html (et le code source correspondant) pour une version fonctionnelle.

  • Tenter d'utiliser des rsultats d'oprations asynchrones non termines. Il faudra par exemple s'assurer qu'une requte est bien termine et qu'elle a fourni une rponse avant de vouloir utiliser la rponse en quesiton. L'ajout des promesses en JavaScript a permis de simplifier ce problme.

Outils d'analyse de code (linters)

Comme pour HTML et CSS, vous pouvez vous aider d'un linter pour crire du JavaScript de meilleure qualit. Un tel outil vous indiquera certaines erreurs et pourra aussi mettre des avertissements quant des mauvaises pratiques. Vous pourrez le paramtrer pour qu'il soit plus ou moins strict. Nous vous recommandons particulirement ESLint et nous verrons certains usages par la suite.

Utilisation en ligne

Le bac sable ESLint permet de le tester dans un navigateur web en saisissant du code JavaScript dans le volet gauche. Dans la zone en dessous, vous pourrez voir les diffrentes erreurs et avertissement.

Une capture d'cran du bac  sable ESLint o la zone suprieure gauche est l'diteur de code avec les numros de ligne et la coloration syntaxe. Sur la zone droite, diffrentes options de configuration sont disponibles. La zone infrieure gauche affiche deux messages d'avertissement, dont un sur la valeur de la condition de la boucle for et l'autre sur l'utilisation possible de const pour une variable affecte une seule fois. [Une capture d'cran du bac sable ESLint o la zone suprieure gauche est l'diteur de code avec les numros de ligne et la coloration syntaxe. Sur la zone droite, diffrentes options de configuration sont disponibles. La zone infrieure gauche affiche deux messages d'avertissement, dont un sur la valeur de la condition de la boucle for et l'autre sur l'utilisation possible de const pour une variable affecte une seule fois.]

Extensions pour les diteurs

Copier-coller du texte sur une page web n'est pas une option valable au quotidien. On veut qu'un tel outil soit bien intgr l'diteur de texte qu'on utilise. De nombreux IDE et diteurs peuvent tre configurs pour utiliser ces outils, voir la page sur les intgrations d'ESLint.

Autres cas d'usage

Il existe d'autres faons d'utiliser ces linters. Pour en savoir plus, rfrez vous leur documentation (par exemple, la page pour dmarrer avec ESLint (en anglais)).

On peut notamment utiliser ces outils avec la ligne de commande et les installer pour cet usage avec npm (Node Package Manager, qui ncessite d'avoir install Node.js). La ligne de commande suivante permet d'installer ESLint :

bash
npm install -g eslint

On peut alors utiliser la commande eslint dans un projet pour en analyser les fichiers.

Ces outils peuvent tre utiliss avec les outils de compilation comme Gulp ou Webpack pour analyser automatiquement le code JavaScript lors du dveloppement (voir comment Utiliser un agent pour automatiser les tests dans un article suivant). Voir la page sur les intgrations ESLint avec les outils de compilation.

Les outils de dveloppement des navigateurs

Les outils de dveloppement prsents dans les navigateurs disposent de fonctionnalits utiles pour aider dboguer du code JavaScript. La console JavaScript est un point de dpart intressant et permet de voir les erreurs l'excution.

Enregistrez une copie locale du code source de l'exemple broken-ajax.html, puis ouvrez le fichier HTML dans votre navigateur.

Si vous ouvrez la console, vous pourrez voir le message d'erreur "Uncaught TypeError: can't access property "length", heroes is undefined", et la rfrence la ligne 49. Dans le fichier source, cela correspond la section suivante :

js
function showHeroes(jsonObj) {
  let heroes = jsonObj["members"];

  for (const hero of heroes) {
    // 
  }

  // 
}

On voit que le code choue ds qu'on accde une proprit de jsonObj (dont on s'attend ce que ce soit un objet JSON). Cette valeur est normalement rcupre depuis un fichier JSON tiers l'aide de l'appel XHR suivant :

js
let requestURL =
  "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json";
let request = new XMLHttpRequest();
request.open("GET", requestURL);
request.send();

let superHeroes = request.response;
populateHeader(superHeroes);
showHeroes(superHeroes);

Mais cela choue.

L'API Console

Vous savez peut-tre dj ce qui cloche, mais voyons comment investiguer. Pour commencer, nous disposons de l'API Console qui permet du code JavaScript d'interagir avec la console JavaScript du navigateur. Cette API possde diffrentes fonctionnalits, mais nous allons ici utiliser console.log() qui permet d'afficher un message personnalis dans la console.

Insrez la ligne suivante juste aprs la ligne 31 :

js
console.log("Valeur de la rponse : ", superHeroes);

Actualisez la page dans le navigateur et vous pourrez alors voir un message dans la console  Valeur de la rponse : , suivi du mme message d'erreur qu'auparavant.

L'appel console.log() nous permet de voir que l'objet superHeroes ne semble rien contenir. Nous avons ici un problme rcurrent avec les requtes asynchrones comme celle-ci, o nous essayons d'utiliser la rponse avant que celle-ci ait effectivement t envoye sur le rseau. Corrigeons ce problme en excutant le code aprs que l'vnement load a t dclench. Retirez la ligne avec console.log(), et changez le fragment suivant :

js
const superHeroes = request.response;
populateHeader(superHeroes);
showHeroes(superHeroes);

En cette version :

js
request.onload = function () {
  let superHeroes = request.response;
  populateHeader(superHeroes);
  showHeroes(superHeroes);
};

Pour rsumer, lorsque quelque chose ne fonctionne pas et qu'une valeur n'est pas ce qu'elle devrait tre un endroit du code, vous pouvez utiliser console.log() pour l'afficher et analyser ce qui se passe.

Utiliser le dbogueur JavaScript

Malheureusement, l'erreur est toujours l. Continuons notre enqute en utilisant un outil plus avanc : le dbogueur JavaScript.

Note : Des outils quivalents sont disponibles dans les autres navigateurs : l'onglet Sources de Chrome et Edge, le dbogueur de Safari (voir les outils de dveloppement de Safari).

Dans Firefox, l'onglet du dbogueur se prsente ainsi :

Capture d'cran du dbogueur JavaScript dans Firefox [Capture d'cran du dbogueur JavaScript dans Firefox]

  • Sur la gauche, on peut slectionner le script qu'on souhaite dboguer (ici il n'y en a qu'un).
  • Le panneau central affiche le code du script slectionn.
  • Le panneau droite affiche diffrents dtails propos de l'environnement actuel (points d'arrt, pile d'excution, et portes actives entre autres).

La fonctionnalit principale du dbogueur est la possibilit d'ajouter des points d'arrt dans le code. Il s'agit de points o le code s'arrtera et o on pourra examiner l'environnement dans son tat actuel, pour tudier ce qui se passe, avant de reprendre la suite de l'excution.

Exploitons donc cet outil. L'erreur se produit dsormais la ligne 49. Cliquez sur la ligne 49 dans le panneau central pour ajouter un point d'arrt (vous verrez une flche bleue apparatre gauche). Actualisez ensuite la page (Cmd/Ctrl + R) et le navigateur suspendra l'excution la ligne 49. Le panneau droite affichera alors plusieurs informations utiles.

Le dbogueur de Firefox avec un point d'arrt [Le dbogueur de Firefox avec un point d'arrt]

  • Dans la section Points d'arrt, vous pouvez voir les dtails sur le point d'arrt que vous avez plac.
  • Sous Pile d'excution, vous pouvez voir la liste des fonctions qui ont t appeles pour que la fonction courante soit appele. En haut, nous avons showHeroes(), qui est la fonction courante, et en dessous, nous avons onload, qui correspond la fonction de gestion d'vnement qui contient l'appel showHeroes().
  • Sous Portes, vous pouvez voir la porte active de la fonction que nous regardons. Il y a ici trois portes : showHeroes, bloc, et Window (la porte globale). Chaque porte peut tre dveloppe pour afficher les valeurs des variables l'intrieur de la porte au moment o l'excution a t suspendue.

Nous avons ici plusieurs informations trs utiles.

  1. En dpliant la porte showHeroes, on peut voir que la variable heroes vaut undefined, ce qui indique que l'accs la proprit members de l'objet jsonObj (la premire ligne de la fonction) n'a pas fonctionn.
  2. On peut aussi voir que la variable jsonObj contient une chane de caractres et pas un objet JSON.
  3. En cliquant sur onload dans la section Pile d'excution, on peut analyser ce qui s'est pass l'appel de la fonction. La vue est alors mise jour pour afficher la fonction request.onload dans le panneau central et sa porte dans la section Portes.
  4. Si vous dveloppez la porte onload, vous pourrez voir que la variable superHeroes est galement une chane de caractres et pas un objet. C'est l notre problme, l'appel XMLHttpRequest renvoie du JSON sous forme de texte et pas sous forme d'un objet JSON.

Nous vous donnons ici l'occasion de corriger le problme par vous-mme. Pour vous donner quelques pistes, vous pouvez paramtrer l'objet de la requte XMLHttpRequest pour recevoir explicitement une rponse au format JSON, ou convertir le texte obtenu en JSON aprs avoir reu la rponse. Si vous coincez, vous pouvez consulter le code source de l'exemple corrig.

Note : Le dbogueur possde de nombreuses autres fonctionnalits que nous n'avons pas abordes ici, comme les points d'arrt conditionnels et les expressions espionnes. Pour plus d'informations, rfrez vous la documentation du dbogueur Firefox.

Les problmes de performance

Lorsqu'une application devient de plus en plus complexer et qu'on utilise de plus en plus de JavaScript, on pourra rencontrer des problmes de performances, notamment sur les appareils les plus lents. L'optimisation des performances est un vaste sujet que nous ne pourrons couvrir entirement dans cet article. Voici quelques conseils rapides :

  • Pour viter de charger plus de JavaScript que ncessaire, vous pouvez empaqueter vos scripts dans un seul fichier l'aide d'un outil comme Browserify. De faon gnrale, rduire le nombre de requtes HTTP permet d'amliorer les performances.
  • Minifiez/compressez vos fichiers avant de les dployer sur votre serveur de production. La minification consiste compresser l'ensemble du code sur une seule ligne et en renommant certaines des variables pour obtenir un fichier beaucoup plus petit. Le code obtenu est presqu'illisible, mais ce moment, il est l pour tre excut plutt que lu. terser est un exemple d'outil de minification.
  • Lorsque vous utilisez des API, assurez vous de dsactiver les fonctionnalits que vous n'utilisez pas. Certains appels d'API ont un impact lev sur les performances. Par exemple, lors de l'affichage d'un flux vido, assurez vous de l'arrter lorsque la vido est hors de la zone d'affichage de la page. De mme, si vous suivez la position gographique d'une personne l'aide d'appels l'API Geolocation, assurez vous d'arrter les appels lorsque la personne n'utilise plus le site ou l'application.
  • Les animations peuvent s'avrer coteuses en performances. De nombreuses bibliothques JavaScript fournissent des outils d'animation en JavaScript. Toutefois, il est plus efficace d'implmenter des animations avec des fonctionnalits natives comme les animations CSS ou l'API Web Animations.

Les problmes de compatibilit entre navigateurs causs par JavaScript

Dans cette section, nous verrons certains des problmes causs par JavaScript en ce qui concerne la compatibilit entre les navigateurs. Nous verrons :

  • L'utilisation de fonctionnalits JavaScript rcentes
  • L'utilisation d'API Web rcentes
  • L'utilisation de mauvais code pour tenter d'identifier le navigateur
  • Les problmes de performance

Utilisation d'API Web ou de fonctionnalits JavaScript rcentes

Dans l'article prcdent, nous avons vu comment grer certains problmes lis aux fonctionnalits HTML ou CSS non prises en charge grce la nature de ces langages. Toutefois, JavaScript n'est pas aussi permissif que HTML et CSS, si le moteur JavaScript rencontre une erreur ou une syntaxe qu'il ne reconnait pas (par exemple lorsqu'une nouvelle fonctionnalit, pas encore prise en charge, est utilise), il dclenchera une erreur.

Il existe diffrentes stratgies pour grer la prise en charge des fonctionnalits rcentes. Voyons-en quelques-unes.

Note : Ces stratgies ne s'excluent pas les unes les autres. Vous pouvez les combiner si besoin. Par exemple, vous pouvez utiliser la dtection de fonctionnalit pour dterminer si une API est prise en charge, et si elle ne l'est pas, excuter du code pour charger une bibliothque ou une prothse d'mulation pour palier ce manque.

Dtection de fonctionnalit

L'ide de cette stratgie consiste excuter un test pour dterminer si une fonctionnalit JavaScript est prise en charge dans le navigateur courant, puis d'excuter du code de faon conditionnelle afin de fournir un rsultat acceptable dans les deux cas. Prenons un exemple rapide avec l'API Geolocation (qui expose les donnes d'emplacement gographique de l'appareil sur lequel le navigateur est excut), qui a un point d'entre principal avec la proprit globale geolocation, disponible sur l'objet navigator. Pour dtecter si le navigateur prend en charge la golocalisation, on pourra crire ceci :

js
if ("geolocation" in navigator) {
  navigator.geolocation.getCurrentPosition((position) => {
    // On affiche l'emplacement sur une carte, par exemple avec un fond de carte OpenStreetMap
    // qui volue en temps rel
  });
} else {
  // On utilise plutt une carte statique  dfaut
}

On pourra crire un test analogue pour la prise en charge d'une fonctionnalit CSS, en testant l'existence de element.style.propriete (par exemple paragraph.style.transform !== undefined). Si vous souhaitez appliquer des styles selon la prise en charge d'une fonctionnalit CSS, vous pouvez directement utiliser la rgle @ @supports. Ainsi, si on souhaite dterminer si le navigateur courant prend en charge les requtes de conteneur, on pourra crire :

css
@supports (container-type: inline-size) {
  /* On utilise les requtes de conteneur si elles sont prises en charge */
}

Attention, il ne faut pas confondre la dtection de fonctionnalit avec la tentative d'identification du navigateur (browser sniffing) (qui vise dterminer quel est le navigateur qui accde au site). Cette dernire est une mauvaise pratique qui doit tre vite. Voir ci-aprs Utilisation de mauvais code pour tenter d'identifier le navigateur pour plus de dtails.

Note : Nous reviendrons plus en dtails sur la dtection de fonctionnalits dans un article ddi, dans la suite du module.

Bibliothques

Les bibliothques JavaScript sont des composants tiers qu'on peut attacher une page et qui fournissent des fonctionnalits prtes l'emploi, nous vitant d'avoir les redvelopper. De nombreuses bibliothques JavaScript ont t cres pour partager des fonctions utilitaires rcurrentes et gagner du temps sur l'crire de future projets.

Il existe diffrentes varits de bibliothques JavaScript (certaines servant plusieurs choses) :

Les bibliothques utilitaires

Elles fournissent un ensemble de fonctions pour que les tches rcurrentes soient plus simples et moins ennuyantes grer. jQuery des outils de manipulation du DOM (mme si ceux-ci sont mettre en perspective des mthodes natives Document.querySelector(), Document.querySelectorAll() et de l'interface Node.

Les bibliothques de simplification

Elles simplifient certaines tches complexes. L'API WebGL est par exemple une API trs complexe et difficile manipuler directement   la main . C'est pour cela que des bibliothques Three.js, construites par-dessus WebGL, peuvent s'avrer intressantes en fournissant une API indirecte, plus simple manipuler (pour crer des objets 3D, des clairages, des textures, etc.). De mme, l'API Service Worker peut se rvler complexe utiliser et certaines bibliothques ont t cres pour simplifier les cas d'usage classiques des service workers (voir le livre de recettes des service worker pour diffrents exemples).

Les bibliothqus d'interface

Elles fournissent des mthodes pour implmenter des interfaces utilisateur complexes, qu'il aurait t dlicat d'implmenter partir de 0 et de faon compatible entre les diffrents navigateurs. On pourra citer Bootstrap, et Material-UI (ce dernier s'utilisant avec le framework React). Ces bibliothques sont gnralement utilises pour l'intgralit de l'interface utilisateur et il est souvent difficile de les adopter pour implmenter une seule partie de l'interface.

Les bibliothques d'abstraction

Elles offrent une syntaxe simple qui permet de raliser une tche donne sans avoir se soucier des diffrences entre les navigateurs. La bibliothque s'occupera de manipuler les API adquates en arrire-plan pour obtenir la fonctionnalit souhaite (en thorie).

Lors du choix d'une bibliothque, assurez vous qu'elle fonctionne sur l'ensemble des navigateurs que vous ciblez et testez votre implmentation avec soin. Pour choisir une bibliothque, il faut aussi vrifier certains critres, comme sa maintenance, sa prise en charge, voire sa popularit, pour viter une bibliothque qui devienne obsolte rapidement. N'hsitez pas changer avec d'autres personnes pour savoir ce qu'elles utilisent ou recommandent, vrifiez l'activit sur le dpt de code de la bibliothque si ses sources sont ouvertes, etc.

Pour utiliser une bibliothque, il faudra gnralement tlcharger ses fichiers (JavaScript, parfois CSS et/ou avec d'autres dpendances) et les attacher la page (par exemple via un lment <script>). D'autres mthodes existent aussi, comme l'installation sous forme de composants Bower ou l'inclusion comme dpendances avec Webpack. Rfrez vous la documentation d'installation de chaque bibliothque pour plus d'informations.

Note : Vous rencontrerez probablement certains frameworks JavaScript comme React, Ember et Angular. Les bibliothques s'utilisent pour rgler diffrents problmes et s'intgrer des sites existants. Les frameworks sont plutt des solutions compltes pour dvelopper des applications web complexes.

Prothses d'mulation (polyfills)

Les polyfills sont des fichiers JavaScript tiers que vous pouvez intgrer votre projet. Ce ne sont pas des bibliothques qui amliorent des fonctionnalits existantes, mais des prothses qui permettent d'muler des fonctionnalits absentes nativement. Les polyfills utilisent JavaScript ou d'autres technologies pour implmenter la fonctionnalit afin de la rendre disponible dans un navigateur qui ne la prend pas en charge. On peut par exemple utiliser des prothses comme promise-polyfill ou es6-promise pour faire fonctionner les promesses dans les navigateurs qui ne les prennent pas en charge.

Prenons un exemple o nous utiliserons une prothse pour l'API Fetch et une autre pour les promesses. Bien que ces deux fonctionnalits soient bien prises en charge par les dernires gnrations de navigateurs, si on souhaite cibler un navigateur plus ancien qui ne prend pas en charge l'API Fetch, il y a de grandes chances qu'il ne soit pas non plus compatible avec les promesses (largement utilises par l'API Fetch).

  1. Pour commencer, tlchargez un exemplaire de fetch-polyfill.html et cette image dans un nouveau rpertoire. Nous allons crire du code pour rcuprer cette image et l'afficher sur la page.

  2. Ensuite, enregistrez une copie de la prothse d'mulation pour Fetch, dans le mme rpertoire que le fichier HTML prcdent.

  3. Appliquez les polyfills la page en utilisant le code suivant avant l'lment <script> afin qu'elles soient disponibles sur la page lorsqu'on commence utiliser l'API Fetch. Nous incluons la prothse d'mulation des promesses via un CDN :

    html
    <script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js"></script>
    <script src="fetch.js"></script>
    
  4. Dans l'lment <script> qui contient notre script, on ajoute le code suivant :

    js
    const myImage = document.querySelector(".my-image");
    
    fetch("flowers.jpg").then((response) => {
      response.blob().then((myBlob) => {
        const objectURL = URL.createObjectURL(myBlob);
        myImage.src = objectURL;
      });
    });
    
  5. Si vous chargez alors la page dans un navigateur qui n'est pas compatible avec l'API Fetch, vous devriez nanmoins voir l'image apparatre ! Un titre &quot;fetch basic example&quot; suivi d'une photo de fleurs violettes [Un titre &quot;fetch basic example&quot; suivi d'une photo de fleurs violettes]

Note : Vous pouvez consulter l'exemple finalis en ligne (et aussi le code source correspondant).

Note : Il existe diffrentes faons pour utiliser des prothses d'mulation. L encore, rfrez vous la documentation de chacune pour en savoir plus.

Mais dans ce cas, pourquoi toujours charger le code du polyfill, mme si elle n'est pas ncessaire ? Lorsqu'un site ou une application devient de plus en plus complexe, on peut charger de plus en plus de bibliothque et de prothses d'mulation superflues dans certains cas, ce qui pourra avoir un impact sur les performances, notamment sur les appareils ou rseaux les moins puissants. Autant ne charger que les fichiers qui sont ncessaires.

Cela demande une logique supplmentaire dans le code JavaScript. On pourra avoir besoin d'une dtection de fonctionnalit qui dtermine si le navigateur prend en charge les fonctionnalits voulues :

js
if (navigateurPrendEnCharge()) {
  main();
} else {
  chargerScript("polyfills.js", main);
}

function main(err) {
  // le code de notre application va ici
}

On commence par un test avec la fonction navigateurPrendEnCharge(). Si ce test renvoie true, on excute la fonction main() qui contient le code de notre application. La fonction navigateurPrendEnCharge() ressemble ceci :

js
function navigateurPrendEnCharge() {
  return window.Promise && window.fetch;
}

Nous testons ici si l'objet Promise et si la fonction fetch() existent dans le navigateur. Si c'est le cas pour les deux, la fonction renvoie true. Dans le cas contraire, on excute le code situ dans l'autre branche conditionnelle, qui appelle la fonction chargerScript(), qui s'occupe de charger les polyfills dans la page avant d'appeler main() lorsque le chargement est termin. chargerScript() est implmente ainsi :

js
function chargerScript(src, done) {
  const js = document.createElement("script");
  js.src = src;
  js.onload = () => {
    done();
  };
  js.onerror = () => {
    done(new Error(`Failed to load script ${src}`));
  };
  document.head.appendChild(js);
}

Cette fonction cre un nouvel lment <script> et renseigne son attribut src avec le chemin que nous lui avons fourni en premier argument (dans notre exemple, nous l'avons appel avec 'polyfills.js'). Lorsque le script est charg, on appelle la mthode passe en deuxime argument (main() dans notre exemple avant). Si une erreur se produit lors du chargement du script, on appelle tout de mme la fonction, mais avec une erreur personnalise qui pourra nous aider diagnostiquer en cas de problme.

Le fichier polyfills.js dont il est question ici correspond l'assemblage des deux prothses dans un seul fichier. Nous avons construit ce fichier manuellement, mais sachez qu'il existe d'autres outils pour cela, comme Browserify. Il est gnralement utile de fusionner les fichiers JavaScript ensemble pour diminuer le nombre de requtes HTTP ncessaires et ainsi amliorer les performances d'un site.

Vous pouvez voir le rsultat obtenu (et le code source correspondant). Cet exemple a initialement t crit par Philip Walton, dont le billet Loading Polyfills Only When Needed (en anglais) contient de nombreuses explications ce propos.

Transpilation JavaScript

Une autre option pour utiliser des fonctionnalits JavaScript rcentes consiste convertir le code dans une version qui fonctionnera pour les anciens navigateurs.

Note : On appelle transpilation cette transformation du code qui ne transforme pas le code dans un langage de plus bas niveau (comme un programme C compil en binaire), mais qui transforme le code en changeant sa syntaxe avec un mme niveau d'abstraction, afin que celui-ci puisse tre utilis dans d'autres circonstances.

Un transpilateur populaire est Babel.js, mais il en existe d'autres.

N'essayez pas de deviner le navigateur

Par le pass, certains sites essayaient de deviner le navigateur utilis (browser sniffing) pour fournir le code appropri pour ce navigateur.

Tous les navigateurs utilisent une chane de caractres user-agent via l'en-tte HTTP User-Agent qui identifie certaines caractristiques du navigateur (sa version, son nom, le systme d'exploitation, etc.). Pour certains sites et applications, le code de dtection tait incorrect ou n'a pas t maintenu, ce qui a empch certains navigateurs de les afficher correctement. Ce problme est devenu si frquent que les navigateurs ont fini par mentir en changeant leur chane d'agent utilisateur pour contourner ces mauvaises dtections. Les navigateurs ont galement mis disposition des outils permettant aux personnes de modifier par elles-mmes la chane User-Agent, ce qui a fragilis encore plus les sites et applications qui exploitaient cette chane de caractres, voire ce qui a rendu cette technique compltement vaine.

Le billet d'Aaron Anderson, History of the browser user-agent string en anglais, fournit un historique utile voire amusant de cette technique. On privilgiera la dtection de fonctionnalit (et @supports en CSS) pour dtecter de faon fiable lorsqu'une fonctionnalit donne est prise en charge. Cette mthode ne ncessite pas de mettre jour le code lorsque de nouvelles versions des navigateurs sont publies.

Gestion des prfixes en JavaScript

Dans l'article prcdent, nous avons discut longuement de la gestion des prfixes navigateur en CSS. Pendant un temps, les prfixes taient galement utiliss pour les implmentations de nouvelles fonctionnalits en JavaScript (les prfixes pour JavaScript taient crits en camel case et non avec des tirets comme CSS). Par exemple, si un nouvel objet, avec le nom standard Object, tait implment :

  • Firefox aurait utilis mozObject
  • Chrome, Opera, et Safari auraient utilis webkitObject
  • Internet Explorer aurait utilis msObject

Voici un exemple, tir de la dmo violent-theremin (voir le code source correspondant), qui utilise l'API Canvas et l'API Web Audio pour crer un outil de dessin un peu bruyant :

js
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioCtx = new AudioContext();

Pour l'API Web Audio, le point d'entre de l'API pour Chrome tait prfix par webkit (les navigateurs bass sur Chromium prennent dsormais en charge la version standard sans prfixe). La mthode la plus simple pour contourner le problme consistait crer une nouvelle version de l'objet en utilisant la version prfixe si la version standard n'tait pas disponible.

C'tait ensuite cette version de l'objet qui tait utilise pour manipuler l'API plutt que la version originale. Dans notre exemple, nous avons cr une version modifie du constructeur AudioContext avant de crer une nouvelle instance de contexte audio utiliser.

Cette mthode fonctionne pour toutes les fonctionnalits prfixes en JavaScript et peut tre utilise par les bibliothques et prothses d'mulation pour rajouter un niveau d'abstraction et simplifier l'htrognit des navigateurs pour la dveloppeuse ou le dveloppeur.

Mais il faut rappeler que les fonctionnalits prfixes n'taient pas censes tre utilises sur des sites web de production et pouvaient tre modifies voire retires tout moment. Utiliser ces versions en production pouvaient donc causer des problmes de compatibilit entre les navigateurs. Si vous persistez vouloir utiliser des fonctionnalits prfixes, assurez-vous d'utiliser la bonne version et pour de bonnes raisons. Vous pouvez consulter les pages de rfrence de MDN et des sites comme caniuse.com pour savoir si les prfixes sont ncessaires. En cas de doute, vous pouvez galement tester directement dans un navigateur en ouvrant la console et en tapant le nom de la fonctionnalit voulue : si le navigateur dclenche l'auto-compltion lors de la saisie, cela signifie que la fonctionnalit est prsente.

La console du navigateur o on voit l'autocompltion du navigateur aprs le curseur [La console du navigateur o on voit l'autocompltion du navigateur aprs le curseur]

Savoir trouver de l'aide

Vous pourrez tomber sur de nombreux autres problmes en JavaScript (comme avec tout langage) : le plus important est de savoir comment trouver des rponses en ligne. Voyez la section correspondante de l'article sur HTML et CSS pour nos conseils.

Rsum

Et voil pour JavaScript. Ce n'est pas si simple, mais cet article devrait vous donner quelques points de dpart et ides pour diagnostiquer et rsoudre certains problmes JavaScript que vous pourriez rencontrer l'avenir.


Web Proxy Viewer  |  New URL  |  Original Page