Détectez la fonction du navigateur, ne reniflez jamais l'agent
L'affirmation Décider ce que fait votre application Web selon le navigateur qu'elle croit que le visiteur utilise — lire la chaîne d'agent utilisateur et brancher dessus — est une...
L'affirmation
Décider ce que fait votre application Web selon le navigateur qu'elle croit que le visiteur utilise — lire la chaîne d'agent utilisateur et brancher dessus — est une technique qui casse des sites Web depuis deux décennies et continue de le faire. La bonne approche est de demander si la capacité précise dont vous avez besoin est présente, non qui le navigateur prétend être. La détection de fonctions est plus fiable, vieillit mieux, et ne punit pas les utilisateurs sur des navigateurs que vous n'avez pas pensé à tester, et ce n'est pas sensiblement plus de travail que l'alternative fragile.
Pourquoi renifler l'agent utilisateur est un piège
La chaîne d'agent utilisateur est une étiquette autodéclarée, et brancher votre comportement dessus échoue de plusieurs façons à la fois. C'est une cible mouvante : les navigateurs se mettent à jour sans cesse, de nouveaux apparaissent, et une vérification qui reconnaît les versions d'aujourd'hui gère mal en silence celles de demain. Elle est couramment usurpée et altérée, par des navigateurs s'imitant pour la compatibilité et par des outils de confidentialité qui la changent délibérément, de sorte que la chaîne ne décrit souvent pas le navigateur avec exactitude même quand vous l'analysez correctement. Et elle invite la défaillance précise de servir une expérience dégradée à un navigateur que vous n'avez pas testé — votre code ne reconnaît pas la chaîne, retombe sur un recours, et un navigateur parfaitement capable obtient le chemin brisé parce qu'il était inconnu plutôt qu'incapable.
La preuve historique est accablante. La raison pour laquelle les chaînes d'agent utilisateur sont l'enchevêtrement qu'elles sont aujourd'hui — chaque navigateur prétendant en être plusieurs autres — est précisément que des décennies de sites les ont reniflées et ont servi la mauvaise chose, forçant chaque nouveau navigateur à mentir sur son identité juste pour recevoir le chemin de code fonctionnel. Le reniflage a créé le désordre même qui rend le reniflage non fiable.
Interrogez la capacité, pas l'identité
La détection de fonctions teste directement la chose qui vous importe réellement : la capacité que je m'apprête à utiliser est-elle disponible ? Le nom du navigateur n'entre jamais en jeu.
// faux : brancher sur qui le navigateur pretend etre
if (navigator.userAgent.includes('Safari')) { /* fragile, faux demain */ }
// juste : demander si la capacite existe
if ('IntersectionObserver' in window) {
useIntersectionObserver();
} else {
useScrollFallback();
}
C'est correct quel que soit le navigateur qui visite, y compris ceux qui n'existaient pas quand vous avez écrit le code. Un nouveau navigateur qui prend en charge la fonction prend le bon chemin automatiquement ; un qui ne la prend pas prend le recours automatiquement ; et ni l'un ni l'autre ne dépend de ce que votre code reconnaisse un nom. Le test porte sur la capacité, qui est la chose qui détermine réellement si votre code fonctionnera.
Bâtissez à partir d'une base qui fonctionne partout
L'application la plus forte de ce principe est l'amélioration progressive : commencez par une version qui fonctionne en n'utilisant que les capacités que tout navigateur possède, puis superposez des améliorations gardées par la détection de fonctions. L'expérience de base — lire le contenu, soumettre le formulaire, compléter l'achat — ne dépend de rien d'exotique et fonctionne donc partout. Les améliorations — l'interaction plus fluide, le contrôle plus riche — ne s'activent que là où leur capacité requise est présente.
// le formulaire fonctionne avec une soumission simple partout.
// l'ameliorer seulement la ou l'API necessaire existe :
if ('fetch' in window) {
form.addEventListener('submit', submitWithoutReload);
}
Bâti ainsi, un navigateur sans une capacité n'obtient pas une expérience brisée — il obtient l'expérience de base, qui est pleinement fonctionnelle. Vous avez rendu l'amélioration optionnelle plutôt que la fonctionnalité conditionnelle, ce qui signifie que le mode de défaillance d'un navigateur inconnu ou limité est « un peu moins soigné », non « brisé ».
Les usages étroits et légitimes de l'agent utilisateur
Il y a quelques usages honnêtes de la chaîne d'agent utilisateur, et il vaut la peine d'être précis à leur sujet pour que la règle ne soit pas mal lue comme n'y touchant jamais. L'analytique agrégée — comprendre à peu près quel mélange de navigateurs vos visiteurs utilisent, afin de décider quoi tester — est un usage raisonnable, car elle informe vos tests plutôt que de brancher votre comportement. Contourner un bogue précis et documenté dans une version précise d'un navigateur, comme mesure temporaire avec un plan pour la retirer, est défendable quand il n'y a vraiment aucune fonction à détecter. Ce qui n'est pas légitime est le motif général de décider quelles fonctions offrir selon l'identité du navigateur, car c'est le motif qui casse à mesure que le paysage des navigateurs change sous lui.
La règle à tenir
Quand vous vous surprenez à vous apprêter à lire la chaîne d'agent utilisateur pour décider ce que votre application devrait faire, arrêtez et demandez quelle capacité vous testez réellement, puis testez cette capacité à la place. Votre code devient correct pour des navigateurs dont vous n'avez jamais entendu parler, cesse de servir des expériences brisées à des utilisateurs dont le seul péché était d'utiliser quelque chose d'inconnu, et cesse de contribuer au désordre d'usurpation d'identité qui a rendu le reniflage non fiable au départ. Le nom du navigateur n'est pas l'information dont vous avez besoin ; la présence de la capacité l'est, et vous pouvez la demander directement.