Développer des sites à compatibilité descendante

  • Raccourci de la révision : Développement_Web/Développer_des_sites_à_compatibilité_descendante
  • Titre de la révision : Développer des sites à compatibilité descendante
  • ID de la révision : 266653
  • Créé :
  • Créateur : pixelastic
  • Version actuelle ? Non
  • Commentaire 84 words added, 72 words removed

Contenu de la révision

 

Cette page est en cours de traduction.

Cette page explique comment développer des sites qui continuent de fonctionner avec les mises à jour des navigateurs.

Cela est particulièrement important pour les intranets et autres sites non-publics; si on ne peut voir votre site, on ne peut pas voir s'il est cassé. Il n'est pas toujours possible de suivre tous les sites, mais en suivre autant que possible permettra d'assurer la pérennité de votre site.

JavaScript

Préfixer tous les accès à des variables globales dans les attributs onfoo par “window.”

Quand un attribut de gestion d'évenement (onclick, onmouseover, etc) est utilisé sur un élément HTML, toutes les résolutions de variable dans l'attribut sont d'abord résolues sur l'élément lui-même, puis sur le formulaire contenant l'élément si c'est un élément de formulaire, puis sur document, puis finalement sur window (là où se trouvent les variables globales que vous avez définies).

Par exemple, si vous avez le balisage suivant :

<div onclick="alert(ownerDocument)">Cliquez moi</div>

Alors cliquer sur le texte affichera le ownerDocument du div. Cela sera toujours le cas, même s'il y a une var ownerDocument déclarée dans l'espace de visibilité global.

Cela signifie qu'à chaque fois que vous accédez à une variable globale dans un attribut de gestion d'évenement (y compris n'importe quelle fonction déclarée globalement) vous pouvez vous retrouver avec une collision de nom. Il suffit pour cela qu'une nouvelle specification ajoute une nouvelle propriété DOM (et qu'un browser l'implémente) aux éléments qui porte le même nom que votre variable ou fonction.
Si cela arrive, alors soudainement votre function ne sera plus appellée. Ce cas est déjà arrivé de nombreuses fois à de multiples sites durant la phase d'évolution d'HTML5.

Pour éviter ce problème, qualifiez complétement vos variables globales en utilisant window., comme ceci :

<script>
  function nomLocal() {
    alert('La fonction nomLocal a été appellée.');
  }
</script>
<div onclick="window.nomLocal()">Cliquer sur moi devrait faire apparaitre un message.<div>

Ne concatenez pas les scripts dont vous n'avez pas le contrôle.

En ECMAScript, la directive "use strict;" s'applique sur la totalité du fichier. Ainsi, ajouter un script qui dépends d'un comportement non-strict à la suite d'un script en mode strict va forcément casser quelque chose.

Demandez aux auteurs des bibliothèques Javascript que vous utilisez de suivre ces recommendation.

Suggérez aux développeurs de vos bibliothèques favorites de suivre ces recommendations. S'ils ne le font pas, vous ne pouvez pas être sur que cette bibliothèque ne va pas casser dans le future. Malheureusement, les bibliothèques suivent rarement ces conseils.

Détection

Détecter des fonctionnalités particulières

Si vous avez l'intention d'utiliser une fonctionnalité en particulier, utiliser la détection d'objet pour détecter cette fonctionnalité particulière, si possible. Par exemple, ne considérez pas que si dans un navigateur "filter" in body.style s'évalue à true, alors forcément ce navigateur doit être Internet Explorer et que donc cela signifie qu'il possède un objet window.event disponible dans les gestionnaires d'évenement. 

Ne considérez pas que si un navigateur supporte une certaine fonctionnalité DOM, alors il doit forcément en supporter une autre, particulièrement si elle est non standard. Ou, à l'inverse, qu'ils ne supportent pas une autre feature (par exemple, ne considérez pas que si un navigateur supporte onload sur les éléments scripts, alors il ne supportera jamais onreadystatechange sur ces mêmes éléments).

De plus en plus les comportement des navigateurs convergent : des fonctionnalités sont ajoutées, supprimées, des bugs sont corrigés. Tout ceci arrive regulièrement et arrivera encore.

Donc, ne cherchez pas à détecter une fonctionnalité ou un objet pour en déduire ensuite que parce qu'elle existe (ou non) alors telle ou telle autre fonctionnalité doit alors aussi exister (ou non).

Ne détectez pas l'agent utilisateur

C'est une sous-catégorie très particuliere de penser qu'une certaine fonctionnalité (la présence ou non d'une certaine chaine de caractères dans l'agent utilisateur -UA-) implique la présence ou l'absence d'autres fonctionnalités.

Si vous devez détecter l'agent utilisateur, alors ne détectez que pour les anciennes versions.

Si vous devez vraiment detecter l'agent utilisateur, alors ne l'utilisez que pour cibler des versions déjà dépassées de navigateurs particuliers. Tout d'abord, prévoyez toujours un chemin dans votre code pour les navigateurs que vous ne connaissez pas et ceux pour lesquels vous avez testé votre site. Ensuite, si ce chemin par défaut ne fonctionne pas dans certaines anciennes versions de certains navigateurs et que l'erreur ne peut pas être détectée par l'absence de fonctionnalités utilisées par votre chemin par défaut, alors il est raisonnable d'ajouter des hacks qui ne ciblent que ces anciennes versions de certains navigateurs, en recourant à la détection de l'agent utilisateur.

Pour les besoins de ce conseil, considérez que "version courante" signifie la dernière version du navigateur que vous avez testé. Par exemple, si vous avez testé le chemin par défaut de votre code dans Firefox Aurora mais que Firefox Beta et les dernières versions ont un bug qui font planter votre code, alors il est raisonnable de considérer le numero de version de Aurora au moment du test comme étant la "version courante", et considérer la version Beta comme une version "ancienne", même si elle n'est pas encore sortie pour le public.

Ne créez pas de chemin de code inutiles pour différents navigateurs

N'allez pas créer trop de branches de code différentes, qui s'executent en fonction de l'agent utilisateur ou de la détection de fonctionnalité si vous avez une branche de code qui fonctionne pour tous les navigateurs. Il y a de fortes chances pour que les navigateurs convergent vers un comportement commun, ce qui risque de casser les chemins alternatifs que vous auriez créés pour tel ou tel navigateur.

Testing

Test with all major engines

Test your code at least in Firefox, Chrome or Safari (since both are based on the same WebKit engine), Opera, and Internet Explorer. If you are following the advice given above so that you have a single code path for all current and unknown browsers, testing that this single code path works in all the major engines makes it extremely probable that your code won't break in the future.

Sometimes browsers implement a given feature slightly differently. If you have a single code path that works in all the top engines, it means that you are either using features where browser behavior has already converged or, if the behavior hasn't quite converged yet, your code works regardless of which engine's behavior standards turn out to uphold.

Browser-specific features and prefixes

Don't target hacks at current or future versions of browsers

This is also a common instance of assuming that present correlation between bugs implies future correlation between bugs. Targeting hacks at old versions of browsers whose current versions no longer have the bug you're relying on for your hack is OK; once a browser has fixed bug X, you can know for certain that all releases that had bug X also had bug Y and use the presence of bug X to target workarounds for bug Y.

For the purpose of this piece of advice, "current" means the most recent version of a browser you have tested, as in the case of the UA sniffing advice above.

Avoid depending on cutting-edge nonstandard features

Even if the feature is prefixed, using it could be dangerous: as the specification evolves the browser's prefixed implementation can likewise change to track the specification. And once the feature is standardized, the prefixed version is likely to be removed.

Prefixed, non-standard features are provided by browser developers for you to experiment with and offer feedback on, and aren't meant to be deployed. If you choose to use them, be prepared to need to frequently update your site to keep up with changes.

When using cutting-edge features (even standard ones) that are not universally implemented, make sure to test fallback paths

Make sure to test what happens in a browser that doesn't implement the feature you're using, especially if you don't use such a browser day-to-day while working on the site.

Don't use vendor-prefixed features except to target old buggy versions

Vendor-prefixed features can change behavior in future releases.  Once a browser has shipped a feature unprefixed, however, you can use the prefixed version to target old releases by making sure to always use the unprefixed version of the feature when available.  A good example, for a browser vendor using the -vnd CSS prefix that has shipped an unprefixed implementation of the make-it-pretty property, with a behavior for the value "sometimes" that differs from the prefixed version:

<style>
  .pretty-element {
    -vnd-make-it-pretty: sometimes;
    make-it-pretty: sometimes;
  }
</style>

The order of the declarations in the rule above is important: the unprefixed one needs to come last.

Don't use unprefixed versions of CSS properties or APIs until at least one browser supports them

Until there's decently widespread support of the unprefixed version of something, its behavior can still change in unexpected ways.  Most especially, don't use the unprefixed version if no browser actually supports it. You can't assume that the syntax of the final version will be the same as the syntax of any of the prefixed versions.

Code hygiene

Avoid missing >

Passing a validator is one way to ensure this, but even if your website doesn't validate entirely you should make sure all your > characters are present. Missing those can lead to unexpected situations due to a following tag name being treated as an attribute on a previous tag. This can work for a bit, then break if a specification attaches a meaning to that attribute. Here's an example that works in browsers without HTML5 support but breaks in a browser supporting HTML5:

<form action="http://www.example.com">
  <input type="submit" value="Submit the form"
</form>

due to the missing > on the input tag.

Don't leave experiments that didn't work in your code

If you try using a CSS property to do something you want, but it has no effect, remove it.  It might start doing something you don't expect in the future.

 

Tag:needsEditorialReview

Tag:needsTechnicalReview

 

{{ languages( {"en":"en/Web_development/Writing_forward-compatible_websites" } ) }}

Source de la révision

<p> </p>
<div> <div class="warning">Cette page est en cours de traduction.</div> <p>Cette page explique comment développer des sites qui continuent de fonctionner avec les mises à jour des navigateurs.</p> <p>Cela est particulièrement important pour les intranets et autres sites non-publics; si on ne peut voir votre site, on ne peut pas voir s'il est cassé. Il n'est pas toujours possible de suivre tous les sites, mais en suivre autant que possible permettra d'assurer la pérennité de votre site.</p> <h2>JavaScript</h2> <h3>Préfixer tous les accès à des variables globales dans les attributs <code>onfoo</code> par “window.”</h3> <div>Quand un attribut de gestion d'évenement (<code>onclick</code>, <code>onmouseover</code>, etc) est utilisé sur un élément HTML, toutes les résolutions de variable dans l'attribut sont d'abord résolues sur l'élément lui-même, puis sur le formulaire contenant l'élément si c'est un élément de formulaire, puis sur <code>document</code>, puis finalement sur <code>window</code> (là où se trouvent les variables globales que vous avez définies).</div> <h3>Par exemple, si vous avez le balisage suivant :</h3> <pre>&lt;div onclick="alert(ownerDocument)"&gt;Cliquez moi&lt;/div&gt;</pre> <p>Alors cliquer sur le texte affichera le ownerDocument du div. Cela sera toujours le cas, même s'il y a une <code>var ownerDocument</code> déclarée dans l'espace de visibilité global.</p> <p>Cela signifie qu'à chaque fois que vous accédez à une variable globale dans un attribut de gestion d'évenement (y compris n'importe quelle fonction déclarée globalement) vous pouvez vous retrouver avec une collision de nom. Il suffit pour cela qu'une nouvelle specification ajoute une nouvelle propriété DOM (et qu'un browser l'implémente) aux éléments qui porte le même nom que votre variable ou fonction.<br> Si cela arrive, alors soudainement votre function ne sera plus appellée. Ce cas est déjà arrivé de nombreuses fois à de multiples sites durant la phase d'évolution d'HTML5.</p> <p>Pour éviter ce problème, qualifiez complétement vos variables globales en utilisant <code>window.</code>, comme ceci :</p> <pre>&lt;script&gt;
  function nomLocal() {
    alert('La fonction nomLocal a été appellée.');
  }
&lt;/script&gt;
&lt;div onclick="<strong>window.</strong>nomLocal()"&gt;Cliquer sur moi devrait faire apparaitre un message.&lt;div&gt;
</pre> <h3>Ne concatenez pas les scripts dont vous n'avez pas le contrôle.</h3> <p>En ECMAScript, la directive "use strict;" s'applique sur la totalité du fichier. Ainsi, ajouter un script qui dépends d'un comportement non-strict à la suite d'un script en mode strict va forcément casser quelque chose.</p> <h3>Demandez aux auteurs des bibliothèques Javascript que vous utilisez de suivre ces recommendation.</h3> <p>Suggérez aux développeurs de vos bibliothèques favorites de suivre ces recommendations. S'ils ne le font pas, vous ne pouvez pas être sur que cette bibliothèque ne va pas casser dans le future. Malheureusement, les bibliothèques suivent rarement ces conseils.</p> <h2>Détection</h2> <h3>Détecter des fonctionnalités particulières</h3> <p>Si vous avez l'intention d'utiliser une fonctionnalité en particulier, utiliser la détection d'objet pour détecter cette fonctionnalité particulière, si possible. Par exemple, ne considérez pas que si dans un navigateur <code>"filter" in body.style</code> s'évalue à <code>true</code>, alors forcément ce navigateur doit être Internet Explorer et que donc cela signifie qu'il possède un objet <code>window.event</code> disponible dans les gestionnaires d'évenement. </p> <p>Ne considérez pas que si un navigateur supporte une certaine fonctionnalité DOM, alors il doit forcément en supporter une autre, particulièrement si elle est non standard. Ou, à l'inverse, qu'ils ne supportent <em>pas</em> une autre feature (par exemple, ne considérez pas que si un navigateur supporte <code>onload</code> sur les éléments scripts, alors il ne supportera jamais <code>onreadystatechange</code> sur ces mêmes éléments).</p> <p>De plus en plus les comportement des navigateurs convergent : des fonctionnalités sont ajoutées, supprimées, des bugs sont corrigés. Tout ceci arrive regulièrement et arrivera encore.</p> <p>Donc, ne cherchez pas à détecter une fonctionnalité ou un objet pour en déduire ensuite que parce qu'elle existe (ou non) alors telle ou telle autre fonctionnalité doit alors aussi exister (ou non).</p> <h3>Ne détectez pas l'agent utilisateur</h3> <p>C'est une sous-catégorie très particuliere de penser qu'une certaine fonctionnalité (la présence ou non d'une certaine chaine de caractères dans l'agent utilisateur -UA-) implique la présence ou l'absence d'autres fonctionnalités.</p> <h4>Si vous devez détecter l'agent utilisateur, alors ne détectez que pour les anciennes versions.</h4> <p>Si vous devez vraiment detecter l'agent utilisateur, alors ne l'utilisez que pour cibler des versions déjà dépassées de navigateurs particuliers. Tout d'abord, prévoyez toujours un chemin dans votre code pour les navigateurs que vous ne connaissez pas et ceux pour lesquels vous avez testé votre site. Ensuite, si ce chemin par défaut ne fonctionne pas dans certaines anciennes versions de certains navigateurs et que l'erreur ne peut pas être détectée par l'absence de fonctionnalités utilisées par votre chemin par défaut, alors il est raisonnable d'ajouter des hacks qui ne ciblent que ces anciennes versions de certains navigateurs, en recourant à la détection de l'agent utilisateur.</p> <p>Pour les besoins de ce conseil, considérez que "version courante" signifie la dernière version du navigateur que vous avez testé. Par exemple, si vous avez testé le chemin par défaut de votre code dans Firefox Aurora mais que Firefox Beta et les dernières versions ont un bug qui font planter votre code, alors il est raisonnable de considérer le numero de version de Aurora au moment du test comme étant la "version courante", et considérer la version Beta comme une version "ancienne", même si elle n'est pas encore sortie pour le public.</p> <h3>Ne créez pas de chemin de code inutiles pour différents navigateurs</h3> <h3>N'allez pas créer trop de branches de code différentes, qui s'executent en fonction de l'agent utilisateur ou de la détection de fonctionnalité si vous avez une branche de code qui fonctionne pour tous les navigateurs. Il y a de fortes chances pour que les navigateurs convergent vers un comportement commun, ce qui risque de casser les chemins alternatifs que vous auriez créés pour tel ou tel navigateur.</h3> <h2>Testing</h2> <h3>Test with all major engines</h3> <p>Test your code at least in Firefox, Chrome or Safari (since both are based on the same WebKit engine), Opera, and Internet Explorer. If you are following the advice given above so that you have a single code path for all current and unknown browsers, testing that this single code path works in all the major engines makes it extremely probable that your code won't break in the future.</p> <p>Sometimes browsers implement a given feature slightly differently. If you have a single code path that works in all the top engines, it means that you are either using features where browser behavior has already converged or, if the behavior hasn't quite converged yet, your code works regardless of which engine's behavior standards turn out to uphold.</p> <h2>Browser-specific features and prefixes</h2> <h3>Don't target hacks at current or future versions of browsers</h3> <p>This is also a common instance of assuming that present correlation between bugs implies future correlation between bugs. Targeting hacks at <strong>old</strong> versions of browsers whose current versions no longer have the bug you're relying on for your hack is OK; once a browser has fixed bug X, you can know for certain that all releases that had bug X also had bug Y and use the presence of bug X to target workarounds for bug Y.</p> <p>For the purpose of this piece of advice, "current" means the most recent version of a browser you have tested, as in the case of the UA sniffing advice above.</p> <h3>Avoid depending on cutting-edge nonstandard features</h3> <p>Even if the feature is prefixed, using it could be dangerous: as the specification evolves the browser's prefixed implementation can likewise change to track the specification. And once the feature is standardized, the prefixed version is likely to be removed.</p> <p>Prefixed, non-standard features are provided by browser developers for you to experiment with and offer feedback on, and aren't meant to be deployed. If you choose to use them, be prepared to need to frequently update your site to keep up with changes.</p> <h3>When using cutting-edge features (even standard ones) that are not universally implemented, make sure to test fallback paths</h3> <p>Make sure to test what happens in a browser that doesn't implement the feature you're using, especially if you don't use such a browser day-to-day while working on the site.</p> <h3>Don't use vendor-prefixed features except to target old buggy versions</h3> <p>Vendor-prefixed features can change behavior in future releases.  Once a browser has shipped a feature unprefixed, however, you can use the prefixed version to target old releases by making sure to always use the unprefixed version of the feature when available.  A good example, for a browser vendor using the <code>-vnd</code> CSS prefix that has shipped an unprefixed implementation of the <code>make-it-pretty</code> property, with a behavior for the value <code>"sometimes"</code> that differs from the prefixed version:</p> <pre class="brush: html">&lt;style&gt;
  .pretty-element {
    -vnd-make-it-pretty: sometimes;
    make-it-pretty: sometimes;
  }
&lt;/style&gt;
</pre> <p>The order of the declarations in the rule above is important: the unprefixed one needs to come last.</p> <h3>Don't use unprefixed versions of CSS properties or APIs until at least one browser supports them</h3> <p>Until there's decently widespread support of the unprefixed version of something, its behavior can still change in unexpected ways.  Most especially, don't use the unprefixed version if no browser actually supports it. You can't assume that the syntax of the final version will be the same as the syntax of any of the prefixed versions.</p> <h2>Code hygiene</h2> <h3>Avoid missing <code>&gt;</code></h3> <p>Passing a validator is one way to ensure this, but even if your website doesn't validate entirely you should make sure all your <code>&gt;</code> characters are present. Missing those can lead to unexpected situations due to a following tag name being treated as an attribute on a previous tag. This can work for a bit, then break if a specification attaches a meaning to that attribute. Here's an example that works in browsers without HTML5 support but breaks in a browser supporting HTML5:</p> <pre class="brush: html">&lt;form action="http://www.example.com"&gt;
  &lt;input type="submit" value="Submit the form"
&lt;/form&gt;
</pre> <p>due to the missing <code>&gt;</code> on the <code>input</code> tag.</p> <h3>Don't leave experiments that didn't work in your code</h3> <p>If you try using a CSS property to do something you want, but it has no effect, remove it.  It might start doing something you don't expect in the future.</p> <p> </p> <p>Tag:needsEditorialReview</p> <p>Tag:needsTechnicalReview</p>
</div>
<p> </p>
<p>{{ languages( {"en":"en/Web_development/Writing_forward-compatible_websites" } ) }}</p>
Revenir à cette révision