Conformité dans l'écosystème de frameworks JavaScript
Dans notre article de blog de présentation, nous avons expliqué comment nous avons beaucoup appris en créant et en utilisant des frameworks et des outils pour développer et gérer des applications Web à grande échelle telles que la recherche Google, Maps, Photos, etc. En protégeant les développeurs contre l'écriture de code pouvant affecter négativement l'expérience utilisateur, nous avons prouvé que les frameworks peuvent jouer un rôle clé dans l'amélioration des résultats en termes de performances et de qualité des applications.
En interne, chez Google, nous avons utilisé le terme Conformité pour décrire cette méthodologie. Cet article explique comment nous prévoyons de rendre ce concept Open Source pour l'écosystème de frameworks JavaScript.
Qu'est-ce que la conformité ?
Chez Google, la conformité a évolué. Les équipes s'appuyaient sur un petit groupe de mainteneurs très expérimentés qui effectuaient des examens approfondis du code, en signalant les éléments qui affectaient la qualité et la maintenabilité de l'application bien au-delà des problèmes d'exactitude. Pour l'adapter aux équipes croissantes de développeurs d'applications, un système de conformité a été développé pour codifier les bonnes pratiques de manière automatisée et applicable. Cela a permis de maintenir un niveau élevé de qualité des applications et de facilité de gestion du codebase, quel que soit le nombre de contributeurs au code.
La conformité est un système qui garantit que les développeurs restent sur le chemin éclairé. Elle renforce la confiance et garantit des résultats prévisibles. Il rend les équipes productives et devient crucial pour la mise à l'échelle, à mesure que les équipes se développent et que davantage de fonctionnalités sont développées simultanément. Il permet aux développeurs de se concentrer sur la création de fonctionnalités de produit, ce qui les libère des détails et du paysage en constante évolution dans divers domaines tels que les performances, l'accessibilité, la sécurité, etc. Tout le monde peut désactiver la conformité à tout moment. Elle doit être personnalisable dans la mesure où les équipes auront la possibilité de mettre en œuvre tout ce qu'elles décident de s'engager à respecter.
La conformité repose sur des paramètres par défaut stricts et sur la fourniture de règles exploitables pouvant être appliquées au moment de la création. Il se décompose en trois principes :
1. Paramètres par défaut sécurisés
Un aspect fondamental de la conformité consiste à s'assurer que les outils utilisés par les développeurs disposent de valeurs par défaut solides. Cela signifie que les solutions ne sont pas seulement intégrées aux frameworks, mais que les modèles de conception de framework permettent de faire ce qui est juste et de ne pas suivre les anti-modèles. Le framework aide les développeurs à concevoir des applications et à structurer leur code.
Pour améliorer les performances de chargement, toutes les ressources (polices, CSS, JavaScript, images, etc.) doivent être optimisées. Il s'agit d'un défi complexe qui implique de couper des octets, de réduire les aller-retours et de séparer ce qui est nécessaire pour le premier rendu, la préparation visuelle et l'interaction utilisateur. Par exemple, en extrayant le CSS critique et en définissant la priorité sur les images importantes.
2. Règles exploitables
Même si les optimisations de base sont en place, les développeurs doivent toujours faire des choix. Il existe un large éventail d'optimisations possibles en fonction de la quantité d'informations requises de la part du développeur:
- Valeurs par défaut qui ne nécessitent aucune intervention du développeur, comme l'intégration du CSS critique.
- Nécessite une activation par le développeur. Par exemple, en utilisant un composant d'image fourni par le framework pour dimensionner et mettre à l'échelle des images.
- Nécessitent une activation et une personnalisation par le développeur. Par exemple, en taguant les images importantes à charger plus tôt.
- Il ne s'agit pas d'une fonctionnalité spécifique, mais de décisions qui restent à prendre par le développeur. Par exemple, en évitant les polices ou les scripts synchrones qui retardent le rendu anticipé.
Les optimisations qui nécessitent une décision des développeurs présentent un risque pour les performances de l'application. À mesure que des fonctionnalités sont ajoutées et que votre équipe se développe, même les développeurs les plus expérimentés ne peuvent pas suivre les bonnes pratiques en constante évolution, et ce n'est pas la meilleure façon d'utiliser leur temps. Pour la conformité, des règles pratiques appropriées sont aussi importantes que des valeurs par défaut strictes pour s'assurer que l'application continue de respecter une certaine norme, même lorsque les développeurs continuent d'apporter des modifications.
3. Heure de création
Il est important de détecter et d'éviter les problèmes de performances dès le début du cycle de vie du développement. La phase d'écriture, avant le commit du code, est idéale pour détecter et résoudre les problèmes. Plus un problème est détecté tardivement dans le cycle de développement, plus il est difficile et coûteux à résoudre. Bien que cela s'applique aux problèmes d'exactitude, cela est également vrai pour les problèmes de performances, car bon nombre de ces problèmes ne seront pas résolus rétroactivement une fois intégrés au codebase.
Aujourd'hui, la plupart des commentaires sur les performances sont hors bande via la documentation, des audits ponctuels ou sont affichés trop tard via la régression des métriques après le déploiement en production. Nous souhaitons l'intégrer au moment de la création.
Conformité dans les frameworks
Pour maintenir un niveau élevé d'expérience utilisateur pour les performances de chargement, vous devez répondre aux questions suivantes:
- Qu'est-ce qu'un chargement optimal et quels sont les problèmes courants qui peuvent l'affecter négativement ?
- Quelles solutions peuvent être intégrées sans nécessiter l'intervention d'un développeur ?
- Comment pouvons-nous nous assurer que le développeur utilise ces solutions et les exploite de manière optimale ?
- Quels autres choix le développeur peut-il faire pour avoir un impact sur les performances de chargement ?
- Quels sont les modèles de code qui peuvent nous renseigner sur ces choix (numéros 3 et 4 ci-dessus) dès le début de la création ?
- Quelles règles pouvons-nous formuler pour évaluer ces modèles de code ? Comment les présenter au développeur au moment de la création, tout en les intégrant parfaitement à son workflow ?
Pour étendre le modèle de conformité que nous utilisons en interne chez Google aux frameworks open source, notre équipe a beaucoup expérimenté Next.js. Nous sommes ravis de partager notre vision et nos plans affinés. Nous avons réalisé que le meilleur ensemble de règles permettant d'évaluer les modèles de code doit être une combinaison d'analyse statique du code et de vérifications dynamiques. Ces règles peuvent s'appliquer à plusieurs surfaces, y compris:
- ESLint
- TypeScript
- Vérifications dynamiques sur le serveur de développement de l'utilisateur (après la création du DOM)
- Bundleur de modules (webpack)
- Outils CSS (en phase d'exploration)
En fournissant des règles via différents outils, nous pouvons nous assurer qu'elles sont cohérentes, mais aussi qu'elles couvrent tous les problèmes d'expérience utilisateur qui ont un impact direct sur les performances de chargement. De plus, ces règles peuvent également être présentées aux développeurs à différents moments:
- Lors du développement local sur le serveur de développement, le navigateur et l'IDE de l'utilisateur affichent des avertissements, invitant les développeurs à apporter de petites modifications au code.
- Au moment de la compilation, les problèmes non résolus sont à nouveau affichés dans le terminal de l'utilisateur.
En résumé, les équipes choisiront les résultats qui les intéressent, tels que les Core Web Vitals ou les performances de chargement, et activeront les règles pertinentes que tous les contributeurs au code devront suivre.
Bien que cette approche fonctionne très bien pour les nouveaux projets, il n'est pas facile de mettre à niveau de grands codebases pour qu'ils respectent des règles complètes. Chez Google, nous disposons d'un système étendu pour désactiver les fonctionnalités à différents niveaux, tels que des lignes de code source individuelles, des répertoires entiers, des anciens codebases ou des parties de l'application qui ne sont pas en cours de développement. Nous étudions activement des stratégies efficaces pour proposer cette fonctionnalité aux équipes qui utilisent des frameworks Open Source.
Conformité dans Next.js
ESLint est largement utilisé par les développeurs JavaScript. Plus de 50% des applications Next.js utilisent ESLint dans une partie de leur workflow de compilation. La version 11 de Next.js a introduit la prise en charge d'ESLint prête à l'emploi, qui comprend un plug-in personnalisé et une configuration partageable pour faciliter la détection des problèmes courants spécifiques au framework lors du développement et au moment de la compilation. Cela peut aider les développeurs à résoudre des problèmes importants au moment de la création. Par exemple, lorsqu'un composant est utilisé ou non d'une manière qui pourrait nuire aux performances (Aucun lien HTML pour la page). Ou si une certaine police, feuille de style ou script peut avoir un impact négatif sur le chargement de ressources sur une page. Par exemple, Aucun script synchrone.
En plus d'ESLint, la validation des types intégrée en développement et en production est prise en charge dans Next.js depuis la version 9 avec la prise en charge de TypeScript. Plusieurs composants fournis par le framework (Image, Script, Link) ont été créés en tant qu'extension des éléments HTML (<img>
, <script>
, <a>
) afin de fournir aux développeurs une approche performante pour ajouter du contenu à une page Web. La vérification de type permet une utilisation appropriée de ces fonctionnalités en s'assurant que les propriétés et les options attribuées sont dans la portée acceptable des valeurs et des types compatibles. Pour en savoir plus, consultez la section Largeur et hauteur de l'image requises.
Affichage d'erreurs avec des toasts et des superpositions
Comme indiqué précédemment, les règles de conformité peuvent s'afficher dans plusieurs zones. Les toasts et les superpositions sont actuellement étudiés pour afficher des erreurs directement dans le navigateur dans l'environnement de développement local de l'utilisateur.
De nombreux outils de vérification des erreurs et d'audit sur lesquels les développeurs s'appuient (Lighthouse, onglet "Problèmes" de Chrome DevTools) sont passifs et nécessitent une forme d'interaction avec l'utilisateur pour récupérer des informations. Les développeurs sont plus susceptibles d'agir lorsque des erreurs apparaissent directement dans leur outil existant et lorsqu'ils fournissent des actions concrètes et spécifiques à prendre pour résoudre le problème.
Conformité dans d'autres frameworks
La conformité est d'abord étudiée dans Next.js dans le but de l'étendre à d'autres frameworks (Nuxt, Angular, etc.). ESLint et TypeScript sont déjà utilisés dans de nombreux frameworks de différentes manières, mais le concept d'un système d'exécution cohérent au niveau du navigateur est en cours d'exploration.
Conclusion
La conformité codifie les bonnes pratiques en règles qui sont exploitables par les développeurs en tant que modèles de code simples. L'équipe Aurora s'est concentrée sur les performances de chargement, mais d'autres bonnes pratiques, telles que l'accessibilité et la sécurité, sont tout aussi applicables.
Le respect des règles de conformité devrait entraîner des résultats prévisibles. Atteindre un niveau élevé d'expérience utilisateur peut devenir un effet secondaire de la création de votre pile technologique. La conformité rend les équipes productives et garantit un niveau de qualité élevé pour l'application, même lorsque les équipes et les bases de code augmentent au fil du temps.