Performances frontales 2021 : définir l'environnement

Publié: 2022-03-10
Résumé rapide ↬ Faisons 2021… vite ! Une liste de contrôle annuelle des performances front-end avec tout ce que vous devez savoir pour créer des expériences rapides sur le Web aujourd'hui, des métriques aux outils et techniques front-end. Mis à jour depuis 2016.

Table des matières

  1. Se préparer : planification et métriques
  2. Fixer des objectifs réalistes
  3. Définir l'environnement
  4. Optimisations des actifs
  5. Construire des optimisations
  6. Optimisations de livraison
  7. Mise en réseau, HTTP/2, HTTP/3
  8. Test et surveillance
  9. Victoires rapides
  10. Tout sur une seule page
  11. Télécharger la liste de contrôle (PDF, pages Apple, MS Word)
  12. Abonnez-vous à notre newsletter par e-mail pour ne pas manquer les prochains guides.

Définir l'environnement

  1. Choisissez et configurez vos outils de construction.
    Ne faites pas trop attention à ce qui est censé être cool de nos jours. Tenez-vous en à votre environnement de construction, que ce soit Grunt, Gulp, Webpack, Parcel ou une combinaison d'outils. Tant que vous obtenez les résultats dont vous avez besoin et que vous n'avez aucun problème à maintenir votre processus de construction, tout va bien.

    Parmi les outils de build, Rollup continue de gagner du terrain, tout comme Snowpack, mais Webpack semble être le plus établi, avec littéralement des centaines de plugins disponibles pour optimiser la taille de vos builds. Attention à la feuille de route Webpack 2021.

    L'une des stratégies les plus notables apparues récemment est la segmentation granulaire avec Webpack dans Next.js et Gatsby pour minimiser le code en double. Par défaut, les modules qui ne sont pas partagés dans chaque point d'entrée peuvent être demandés pour les routes qui ne l'utilisent pas. Cela finit par devenir une surcharge car plus de code est téléchargé que nécessaire. Avec la segmentation granulaire dans Next.js, nous pouvons utiliser un fichier manifeste de construction côté serveur pour déterminer quels segments de sortie sont utilisés par différents points d'entrée.

    Pour réduire le code en double dans les projets Webpack, nous pouvons utiliser la segmentation granulaire, activée dans Next.js et Gatsby par défaut
    Pour réduire le code en double dans les projets Webpack, nous pouvons utiliser la segmentation granulaire, activée par défaut dans Next.js et Gatsby. Crédit photo : Addy Osmani. ( Grand aperçu )

    Avec SplitChunksPlugin, plusieurs fragments fractionnés sont créés en fonction d'un certain nombre de conditions pour empêcher la récupération de code dupliqué sur plusieurs routes. Cela améliore le temps de chargement des pages et la mise en cache lors des navigations. Livré dans Next.js 9.2 et dans Gatsby v2.20.7.

    Démarrer avec Webpack peut cependant être difficile. Donc, si vous voulez vous plonger dans Webpack, il existe d'excellentes ressources :

    • La documentation Webpack - évidemment - est un bon point de départ, tout comme Webpack - The Confusing Bits de Raja Rao et An Annotated Webpack Config d'Andrew Welch.
    • Sean Larkin a un cours gratuit sur Webpack : The Core Concepts et Jeffrey Way a publié un fantastique cours gratuit sur Webpack pour tout le monde. Les deux sont d'excellentes introductions pour plonger dans Webpack.
    • Webpack Fundamentals est un cours très complet de 4h avec Sean Larkin, publié par FrontendMasters.
    • Les exemples Webpack contiennent des centaines de configurations Webpack prêtes à l'emploi, classées par sujet et par objectif. Bonus : il existe également un configurateur de configuration Webpack qui génère un fichier de configuration de base.
    • awesome-webpack est une liste organisée de ressources, bibliothèques et outils Webpack utiles, y compris des articles, des vidéos, des cours, des livres et des exemples pour les projets Angular, React et indépendants du framework.
    • Le voyage vers des builds rapides d'assets de production avec Webpack est l'étude de cas d'Etsy sur la façon dont l'équipe est passée d'un système de build JavaScript basé sur RequireJS à Webpack et comment elle a optimisé ses builds, gérant plus de 13 200 assets en 4 minutes en moyenne.
    • Les conseils de performance Webpack sont un fil de discussion d'Ivan Akulov, contenant de nombreux conseils axés sur les performances, y compris ceux axés spécifiquement sur Webpack.
    • awesome-webpack-perf est un dépôt Goldmine GitHub avec des outils Webpack et des plugins utiles pour les performances. Également entretenu par Ivan Akulov.
Une visualisation du parcours d'Etsy vers des builds de production rapides avec Webpack
Le voyage d'Etsy vers des constructions de production rapides avec Webpack (via Addy Osmani) ( Grand aperçu )
  1. Utilisez l'amélioration progressive par défaut.
    Pourtant, après toutes ces années, conserver l'amélioration progressive comme principe directeur de votre architecture frontale et de votre déploiement est une valeur sûre. Concevez et construisez d'abord l'expérience de base, puis améliorez l'expérience avec des fonctionnalités avancées pour les navigateurs capables, en créant des expériences résilientes. Si votre site Web fonctionne rapidement sur une machine lente avec un écran médiocre dans un navigateur médiocre sur un réseau sous-optimal, il ne fonctionnera que plus rapidement sur une machine rapide avec un bon navigateur sur un réseau décent.

    En fait, avec le service de module adaptatif, nous semblons porter l'amélioration progressive à un autre niveau, en servant des expériences de base "légères" aux appareils bas de gamme et en améliorant avec des fonctionnalités plus sophistiquées pour les appareils haut de gamme. L'amélioration progressive n'est pas susceptible de s'estomper de si tôt.

  2. Choisissez une base de performance solide.
    Avec autant d'inconnues ayant un impact sur le chargement - le réseau, la limitation thermique, l'éviction du cache, les scripts tiers, les modèles de blocage de l'analyseur, les E/S de disque, la latence IPC, les extensions installées, les logiciels antivirus et les pare-feu, les tâches du processeur en arrière-plan, les contraintes matérielles et de mémoire, différences dans la mise en cache L2/L3, RTTS — JavaScript a le coût le plus élevé de l'expérience, à côté des polices Web bloquant le rendu par défaut et des images consommant souvent trop de mémoire. Avec les goulots d'étranglement des performances qui s'éloignent du serveur vers le client, en tant que développeurs, nous devons considérer toutes ces inconnues de manière beaucoup plus détaillée.

    Avec un budget de 170 Ko qui contient déjà le chemin critique HTML/CSS/JavaScript, le routeur, la gestion de l'état, les utilitaires, le framework et la logique d'application, nous devons examiner en profondeur le coût de transfert réseau, le temps d'analyse/compilation et le coût d'exécution. du cadre de notre choix. Heureusement, nous avons constaté une énorme amélioration au cours des dernières années dans la vitesse à laquelle les navigateurs peuvent analyser et compiler les scripts. Pourtant, l'exécution de JavaScript reste le principal goulot d'étranglement, donc prêter une attention particulière au temps d'exécution du script et au réseau peut avoir un impact.

    Tim Kadlec a mené une recherche fantastique sur les performances des frameworks modernes, et les a résumés dans l'article "Les frameworks JavaScript ont un coût". Nous parlons souvent de l'impact des frameworks autonomes, mais comme le note Tim, dans la pratique, il n'est pas rare d'utiliser plusieurs frameworks . Peut-être une ancienne version de jQuery qui migre lentement vers un framework moderne, ainsi que quelques applications héritées utilisant une ancienne version d'Angular. Il est donc plus raisonnable d'explorer le coût cumulé des octets JavaScript et du temps d'exécution du processeur qui peuvent facilement rendre les expériences utilisateur à peine utilisables, même sur des appareils haut de gamme.

    En général, les frameworks modernes ne donnent pas la priorité aux appareils moins puissants , de sorte que les expériences sur un téléphone et sur un ordinateur de bureau seront souvent radicalement différentes en termes de performances. Selon les recherches, les sites avec React ou Angular passent plus de temps sur le CPU que les autres (ce qui bien sûr ne veut pas nécessairement dire que React est plus cher sur le CPU que Vue.js).

    Selon Tim, une chose est évidente : "si vous utilisez un framework pour créer votre site, vous faites un compromis en termes de performances initiales , même dans le meilleur des scénarios".

Le coût des frameworks, le temps CPU JavaScript : les sites SPA fonctionnent mal
Le coût des frameworks, bye JavaScript : les sites SPA fonctionnent (encore) mal
Temps CPU lié aux scripts pour les appareils mobiles et octets JavaScript pour les appareils de bureau. En général, les sites avec React ou Angular passent plus de temps sur le CPU que les autres. Mais cela dépend de la façon dont vous construisez le site. Recherche par Tim Kadlec. ( Grand aperçu )
  1. Évaluer les frameworks et les dépendances.
    Maintenant, tous les projets n'ont pas besoin d'un framework et toutes les pages d'une application à page unique n'ont pas besoin de charger un framework. Dans le cas de Netflix, "la suppression de React, de plusieurs bibliothèques et du code d'application correspondant du côté client a réduit la quantité totale de JavaScript de plus de 200 Ko, entraînant une réduction de plus de 50 % du temps d'interactivité de Netflix pour la page d'accueil déconnectée. ." L'équipe a ensuite utilisé le temps passé par les utilisateurs sur la page de destination pour prérécupérer React pour les pages suivantes sur lesquelles les utilisateurs étaient susceptibles d'atterrir (lisez la suite pour plus de détails).

    Et si vous supprimiez complètement un framework existant sur les pages critiques ? Avec Gatsby, vous pouvez vérifier gatsby-plugin-no-javascript qui supprime tous les fichiers JavaScript créés par Gatsby à partir des fichiers HTML statiques. Sur Vercel, vous pouvez également autoriser la désactivation du runtime JavaScript en production pour certaines pages (expérimental).

    Une fois qu'un cadre est choisi, nous allons rester avec lui pendant au moins quelques années, donc si nous devons en utiliser un, nous devons nous assurer que notre choix est éclairé et bien réfléchi - et cela vaut en particulier pour les mesures de performance clés que nous s'en soucier.

    Les données montrent que, par défaut, les frameworks sont assez chers : 58,6 % des pages React expédient plus de 1 Mo de JavaScript, et 36 % des chargements de pages Vue.js ont un First Contentful Paint de <1,5s. Selon une étude d'Ankur Sethi, "votre application React ne se chargera jamais plus rapidement qu'environ 1,1 seconde sur un téléphone moyen en Inde, peu importe à quel point vous l'optimisez. Votre application Angular prendra toujours au moins 2,7 secondes pour démarrer. les utilisateurs de votre application Vue devront attendre au moins 1 seconde avant de pouvoir commencer à l'utiliser." De toute façon, vous ne ciblez peut-être pas l'Inde comme marché principal, mais les utilisateurs accédant à votre site avec des conditions de réseau sous-optimales auront une expérience comparable.

    Bien sûr, il est possible de créer des SPA rapidement, mais ils ne sont pas rapides prêts à l'emploi, nous devons donc tenir compte du temps et des efforts nécessaires pour les créer et les maintenir rapides. Ce sera probablement plus facile en choisissant très tôt un coût de performance de base léger.

    Alors comment choisit-on un cadre ? C'est une bonne idée de considérer au moins le coût total sur la taille + les temps d'exécution initiaux avant de choisir une option ; des options légères telles que Preact, Inferno, Vue, Svelte, Alpine ou Polymer peuvent très bien faire le travail. La taille de votre ligne de base définira les contraintes du code de votre application.

    Comme l'a noté Seb Markbage, un bon moyen de mesurer les coûts de démarrage des frameworks consiste à restituer d'abord une vue, puis à la supprimer, puis à restituer car elle peut vous indiquer comment le framework évolue. Le premier rendu a tendance à réchauffer un tas de code compilé paresseusement, dont un arbre plus grand peut bénéficier lorsqu'il évolue. Le deuxième rendu est essentiellement une émulation de la façon dont la réutilisation du code sur une page affecte les caractéristiques de performance à mesure que la page devient plus complexe.

    Vous pouvez aller jusqu'à évaluer vos candidats (ou toute bibliothèque JavaScript en général) sur le système de notation à 12 points de Sacha Greif en explorant les fonctionnalités, l'accessibilité, la stabilité, les performances, l' écosystème de packages , la communauté, la courbe d'apprentissage, la documentation, l'outillage, les antécédents. , équipe, compatibilité, sécurité par exemple.

    Perf Track suit les performances du framework à grande échelle
    Perf Track suit les performances du framework à grande échelle. ( Grand aperçu )

    Vous pouvez également vous fier aux données collectées sur le Web sur une période plus longue. Par exemple, Perf Track suit les performances du framework à grande échelle, en affichant les scores Core Web Vitals agrégés par origine pour les sites Web construits dans Angular, React, Vue, Polymer, Preact, Ember, Svelte et AMP. Vous pouvez même spécifier et comparer des sites Web construits avec Gatsby, Next.js ou Create React App, ainsi que des sites Web construits avec Nuxt.js (Vue) ou Sapper (Svelte).

    Un bon point de départ consiste à choisir une bonne pile par défaut pour votre application. Gatsby (React), Next.js (React), Vuepress (Vue), Preact CLI et PWA Starter Kit fournissent des valeurs par défaut raisonnables pour un chargement rapide et prêt à l'emploi sur du matériel mobile moyen. Jetez également un coup d'œil aux conseils de performance spécifiques au framework web.dev pour React et Angular ( merci, Phillip ! ).

    Et peut-être pourriez-vous adopter une approche légèrement plus rafraîchissante pour créer des applications d'une seule page - Turbolinks, une bibliothèque JavaScript de 15 Ko qui utilise HTML au lieu de JSON pour afficher les vues. Ainsi, lorsque vous suivez un lien, Turbolinks récupère automatiquement la page, échange son <body> et fusionne son <head> , le tout sans encourir le coût d'un chargement complet de la page. Vous pouvez consulter les détails rapides et la documentation complète sur la pile (Hotwire).

Un graphique de type histogramme montrant les performances de calcul des téléphones les plus vendus
Performances du processeur et du calcul des téléphones les plus vendus (Crédit image : Addy Osmani) ( Grand aperçu )
  1. Rendu côté client ou rendu côté serveur ? Tous les deux!
    C'est une conversation assez animée à avoir. L'approche ultime consisterait à mettre en place une sorte de démarrage progressif : utilisez le rendu côté serveur pour obtenir un First Contentful Paint rapide, mais incluez également un minimum de JavaScript nécessaire pour maintenir le temps d'interactivité proche du First Contentful Paint. Si JavaScript arrive trop tard après le FCP, le navigateur verrouillera le thread principal lors de l'analyse, de la compilation et de l'exécution de JavaScript découvert tardivement, ce qui entravera l'interactivité du site ou de l'application.

    Pour l'éviter, divisez toujours l'exécution des fonctions en tâches distinctes et asynchrones et, si possible, utilisez requestIdleCallback . Envisagez de charger paresseusement des parties de l'interface utilisateur à l'aide de la prise en charge dynamique import() de WebPack, en évitant les coûts de chargement, d'analyse et de compilation jusqu'à ce que les utilisateurs en aient vraiment besoin ( merci Addy ! ).

    Comme mentionné ci-dessus, Time to Interactive (TTI) nous indique le temps entre la navigation et l'interactivité. En détail, la métrique est définie en regardant la première fenêtre de cinq secondes après le rendu du contenu initial, dans laquelle aucune tâche JavaScript ne prend plus de 50 ms ( Long Tasks ). Si une tâche de plus de 50 ms se produit, la recherche d'une fenêtre de cinq secondes recommence. En conséquence, le navigateur supposera d'abord qu'il a atteint Interactive , juste pour passer à Frozen , juste pour finalement revenir à Interactive .

    Une fois que nous avons atteint Interactive , nous pouvons ensuite, à la demande ou si le temps le permet, démarrer les parties non essentielles de l'application. Malheureusement, comme l'a remarqué Paul Lewis, les frameworks n'ont généralement pas de concept simple de priorité qui puisse être présenté aux développeurs, et donc le démarrage progressif n'est pas facile à mettre en œuvre avec la plupart des bibliothèques et des frameworks.

    Pourtant, nous y arrivons. Ces jours-ci, il y a quelques choix que nous pouvons explorer, et Houssein Djirdeh et Jason Miller fournissent un excellent aperçu de ces options dans leur exposé sur le rendu sur le Web et l'article de Jason et Addy sur les architectures frontales modernes. L'aperçu ci-dessous est basé sur leur travail stellaire.

    • Rendu complet côté serveur (SSR)
      Dans les SSR classiques, comme WordPress, toutes les requêtes sont entièrement traitées sur le serveur. Le contenu demandé est renvoyé sous la forme d'une page HTML finie et les navigateurs peuvent le restituer immédiatement. Par conséquent, les applications SSR ne peuvent pas vraiment utiliser les API DOM, par exemple. L'écart entre First Contentful Paint et Time to Interactive est généralement faible, et la page peut être rendue immédiatement lorsque le code HTML est diffusé sur le navigateur.

      Cela évite des allers-retours supplémentaires pour la récupération de données et la création de modèles sur le client, car il est géré avant que le navigateur n'obtienne une réponse. Cependant, nous nous retrouvons avec un temps de réflexion du serveur plus long et par conséquent le temps jusqu'au premier octet et nous n'utilisons pas les fonctionnalités réactives et riches des applications modernes.

    • Rendu statique
      Nous construisons le produit comme une application d'une seule page, mais toutes les pages sont pré-rendues en HTML statique avec un minimum de JavaScript comme étape de construction. Cela signifie qu'avec le rendu statique, nous produisons à l'avance des fichiers HTML individuels pour chaque URL possible , ce que peu d'applications peuvent se permettre. Mais comme le code HTML d'une page n'a pas besoin d'être généré à la volée, nous pouvons obtenir un délai d'obtention du premier octet toujours rapide. Ainsi, nous pouvons afficher rapidement une page de destination, puis prérécupérer un cadre SPA pour les pages suivantes. Netflix a adopté cette approche en réduisant le chargement et le temps d'interaction de 50 %.

    • Rendu côté serveur avec (ré)hydratation (rendu universel, SSR + CSR)
      Nous pouvons essayer d'utiliser le meilleur des deux mondes - les approches SSR et RSE. Avec l'hydratation dans le mélange, la page HTML renvoyée par le serveur contient également un script qui charge une application côté client à part entière. Idéalement, cela permet d'obtenir une First Contentful Paint rapide (comme SSR) puis de continuer le rendu avec (ré)hydratation. Malheureusement, c'est rarement le cas. Le plus souvent, la page semble prête mais elle ne peut pas répondre aux entrées de l'utilisateur, produisant des clics et des abandons de rage.

      Avec React, nous pouvons utiliser le module ReactDOMServer sur un serveur Node comme Express, puis appeler la méthode renderToString pour restituer les composants de niveau supérieur sous forme de chaîne HTML statique.

      Avec Vue.js, nous pouvons utiliser le vue-server-renderer pour rendre une instance Vue en HTML en utilisant renderToString . Dans Angular, nous pouvons utiliser @nguniversal pour transformer les demandes des clients en pages HTML entièrement rendues par le serveur. Une expérience entièrement rendue par le serveur peut également être réalisée prête à l'emploi avec Next.js (React) ou Nuxt.js (Vue).

      L'approche a ses inconvénients. En conséquence, nous bénéficions d'une flexibilité totale des applications côté client tout en offrant un rendu plus rapide côté serveur, mais nous nous retrouvons également avec un écart plus long entre First Contentful Paint et Time To Interactive et un délai de première entrée accru. La réhydratation est très coûteuse, et généralement cette stratégie seule ne sera pas suffisante car elle retarde considérablement le Time To Interactive.

    • Rendu côté serveur en streaming avec hydratation progressive (SSR + CSR)
      Pour minimiser l'écart entre Time To Interactive et First Contentful Paint, nous rendons plusieurs requêtes à la fois et envoyons le contenu par blocs au fur et à mesure qu'ils sont générés. Nous n'avons donc pas besoin d'attendre la chaîne complète de HTML avant d'envoyer du contenu au navigateur, et donc d'améliorer Time To First Byte.

      Dans React, au lieu de renderToString() , nous pouvons utiliser renderToNodeStream() pour diriger la réponse et envoyer le HTML en morceaux. Dans Vue, nous pouvons utiliser renderToStream() qui peut être canalisé et diffusé. Avec React Suspense, nous pourrions également utiliser le rendu asynchrone à cette fin.

      Côté client, plutôt que de démarrer l'ensemble de l'application en une seule fois, nous démarrons les composants progressivement . Les sections des applications sont d'abord décomposées en scripts autonomes avec découpage du code, puis hydratées progressivement (dans l'ordre de nos priorités). En fait, nous pouvons d'abord hydrater les composants critiques, tandis que le reste pourrait être hydraté plus tard. Le rôle du rendu côté client et côté serveur peut alors être défini différemment par composant. Nous pouvons alors également différer l'hydratation de certains composants jusqu'à ce qu'ils apparaissent, ou soient nécessaires pour l'interaction de l'utilisateur, ou lorsque le navigateur est inactif.

      Pour Vue, Markus Oberlehner a publié un guide sur la réduction du temps d'interaction des applications SSR en utilisant l'hydratation sur l'interaction de l'utilisateur ainsi que vue-lazy-hydration, un plugin de stade précoce qui permet l'hydratation des composants sur la visibilité ou l'interaction spécifique de l'utilisateur. L'équipe Angular travaille sur l'hydratation progressive avec Ivy Universal. Vous pouvez également implémenter une hydratation partielle avec Preact et Next.js.

    • Rendu trisomorphe
      Avec les techniciens de service en place, nous pouvons utiliser le rendu du serveur de streaming pour les navigations initiales/non-JS, puis demander au technicien de service de prendre en charge le rendu du HTML pour les navigations après son installation. Dans ce cas, le technicien de service préaffiche le contenu et active les navigations de style SPA pour afficher de nouvelles vues dans la même session. Fonctionne bien lorsque vous pouvez partager le même code de modèle et de routage entre le serveur, la page client et le service worker.

    Une illustration montrant comment le rendu trisomorphe fonctionne à 3 endroits tels que le rendu DOM, le prérendu de service worker et le rendu côté serveur
    Rendu trisomorphe, avec le même rendu de code à 3 endroits quelconques : sur le serveur, dans le DOM ou dans un service worker. (Source de l'image : Google Developers) ( Grand aperçu )
    • RSE avec prérendu
      Le prérendu est similaire au rendu côté serveur, mais plutôt que de rendre les pages sur le serveur de manière dynamique, nous rendons l'application en HTML statique au moment de la construction. Alors que les pages statiques sont entièrement interactives sans beaucoup de JavaScript côté client, le prérendu fonctionne différemment . Fondamentalement, il capture l'état initial d'une application côté client sous forme de HTML statique au moment de la construction, tandis qu'avec le prérendu, l'application doit être démarrée sur le client pour que les pages soient interactives.

      Avec Next.js, nous pouvons utiliser l'exportation HTML statique en pré-affichant une application en HTML statique. Dans Gatsby, un générateur de site statique open source qui utilise React, utilise la méthode renderToStaticMarkup au lieu de la méthode renderToString pendant les constructions, le bloc JS principal étant préchargé et les routes futures sont prérécupérées, sans les attributs DOM qui ne sont pas nécessaires pour les pages statiques simples.

      Pour Vue, nous pouvons utiliser Vuepress pour atteindre le même objectif. Vous pouvez également utiliser prerender-loader avec Webpack. Navi fournit également un rendu statique.

      Le résultat est un meilleur Time To First Byte et First Contentful Paint, et nous réduisons l'écart entre Time To Interactive et First Contentful Paint. Nous ne pouvons pas utiliser l'approche si l'on s'attend à ce que le contenu change beaucoup. De plus, toutes les URL doivent être connues à l'avance pour générer toutes les pages. Ainsi, certains composants peuvent être rendus à l'aide du prérendu, mais si nous avons besoin de quelque chose de dynamique, nous devons compter sur l'application pour récupérer le contenu.

    • Rendu complet côté client (CSR)
      Toute la logique, le rendu et le démarrage sont effectués sur le client. Le résultat est généralement un écart énorme entre Time To Interactive et First Contentful Paint. En conséquence, les applications semblent souvent lentes car l'intégralité de l'application doit être démarrée sur le client pour rendre quoi que ce soit.

      Comme JavaScript a un coût de performance, à mesure que la quantité de JavaScript augmente avec une application, un fractionnement de code agressif et un report de JavaScript seront absolument nécessaires pour apprivoiser l'impact de JavaScript. Dans de tels cas, un rendu côté serveur sera généralement une meilleure approche au cas où peu d'interactivité serait requise. Si ce n'est pas une option, envisagez d'utiliser le modèle App Shell.

      En général, SSR est plus rapide que CSR. Pourtant, c'est une implémentation assez fréquente pour de nombreuses applications.

    Alors, côté client ou côté serveur ? En général, c'est une bonne idée de limiter l'utilisation de frameworks entièrement côté client aux pages qui en ont absolument besoin. Pour les applications avancées, ce n'est pas non plus une bonne idée de s'appuyer uniquement sur le rendu côté serveur. Le rendu serveur et le rendu client sont tous deux désastreux s'ils sont mal exécutés.

    Que vous penchiez vers CSR ou SSR, assurez-vous de rendre les pixels importants dès que possible et de minimiser l'écart entre ce rendu et Time To Interactive. Envisagez de pré-rendre si vos pages ne changent pas beaucoup et différez le démarrage des frameworks si vous le pouvez. Diffusez du HTML en morceaux avec un rendu côté serveur et mettez en œuvre une hydratation progressive pour le rendu côté client - et hydratez-vous sur la visibilité, l'interaction ou pendant les temps d'inactivité pour tirer le meilleur parti des deux mondes.

Un tableau comparant les options de rendu côté client et côté serveur
Le spectre d'options pour le rendu côté client par rapport au rendu côté serveur. Consultez également la conférence de Jason et Houssein à Google I/O sur les implications de performance de l'architecture d'application. (Source de l'image : Jason Miller) ( Grand aperçu )
Un exemple de site Web d'AirBnB montrant sans hydratation progressive à gauche et avec hydratation progressive à droite
AirBnB a expérimenté l'hydratation progressive ; ils reportent les composants inutiles, chargent l'interaction de l'utilisateur (défilement) ou pendant le temps d'inactivité et les tests montrent que cela peut améliorer le TTI. ( Grand aperçu )
  1. Combien pouvons-nous servir statiquement ?
    Que vous travailliez sur une grande application ou sur un petit site, il vaut la peine de considérer quel contenu pourrait être servi statiquement à partir d'un CDN (c'est-à-dire JAM Stack), plutôt que d'être généré dynamiquement à la volée. Même si vous avez des milliers de produits et des centaines de filtres avec de nombreuses options de personnalisation, vous souhaiterez peut-être toujours servir vos pages de destination critiques de manière statique et dissocier ces pages du cadre de votre choix.

    Il existe de nombreux générateurs de sites statiques et les pages qu'ils génèrent sont souvent très rapides. Plus nous pouvons pré-construire de contenu à l'avance au lieu de générer des pages vues sur un serveur ou un client au moment de la demande, meilleures seront les performances que nous obtiendrons.

    Dans Construire des sites Web statiques partiellement hydratés et progressivement améliorés, Markus Oberlehner montre comment créer des sites Web avec un générateur de site statique et un SPA, tout en réalisant une amélioration progressive et une taille de bundle JavaScript minimale. Markus utilise Eleventy et Preact comme outils et montre comment configurer les outils, ajouter une hydratation partielle, une hydratation paresseuse, un fichier d'entrée client, configurer Babel pour Preact et regrouper Preact avec Rollup - du début à la fin.

    Avec JAMStack utilisé sur de grands sites ces jours-ci, une nouvelle considération de performance est apparue : le temps de construction . En fait, créer même des milliers de pages avec chaque nouveau déploiement peut prendre quelques minutes, il est donc prometteur de voir des versions incrémentielles dans Gatsby qui améliorent les temps de construction de 60 fois , avec une intégration dans des solutions CMS populaires comme WordPress, Contentful, Drupal, Netlify CMS et d'autres.

    Un organigramme montrant l'utilisateur 1 en haut à gauche et l'utilisateur 2 en bas à gauche montrant le processus de régénération d'état incrémentielle
    Régénération statique incrémentale avec Next.js. (Crédit image: Prisma.io) ( Grand aperçu )

    De plus, Next.js a annoncé une génération statique anticipée et incrémentielle, ce qui nous permet d'ajouter de nouvelles pages statiques au moment de l'exécution et de mettre à jour les pages existantes après leur création, en les restituant en arrière-plan au fur et à mesure que le trafic arrive. .

    Besoin d'une approche encore plus légère ? Dans son exposé sur Eleventy, Alpine et Tailwind : vers un Jamstack léger, Nicola Goutay explique les différences entre la RSE, la SSR et tout ce qui se trouve entre les deux, et montre comment utiliser une approche plus légère — avec un référentiel GitHub qui montre l'approche en pratique.

  2. Envisagez d'utiliser le modèle PRPL et l'architecture du shell d'application.
    Différents frameworks auront des effets différents sur les performances et nécessiteront différentes stratégies d'optimisation. Vous devez donc comprendre clairement tous les rouages ​​​​du framework sur lequel vous comptez. Lors de la création d'une application Web, examinez le modèle PRPL et l'architecture du shell de l'application. L'idée est assez simple : poussez le code minimal nécessaire pour devenir interactif pour que la route initiale soit rendue rapidement, puis utilisez le service worker pour la mise en cache et la pré-mise en cache des ressources, puis chargez les routes dont vous avez besoin, de manière asynchrone.
Modèle PRPL dans l'architecture du shell de l'application
PRPL signifie Pousser les ressources critiques, Rendre la route initiale, Pré-cacher les routes restantes et Lazy-charger les routes restantes à la demande.
Architecture de shell d'application
Un shell d'application est le code HTML, CSS et JavaScript minimal qui alimente une interface utilisateur.
  1. Avez-vous optimisé les performances de vos API ?
    Les API sont des canaux de communication permettant à une application d'exposer des données à des applications internes et tierces via des points de terminaison . Lors de la conception et de la construction d'une API, nous avons besoin d'un protocole raisonnable pour permettre la communication entre le serveur et les requêtes tierces. Le transfert d'état représentatif ( REST ) est un choix logique bien établi : il définit un ensemble de contraintes que les développeurs suivent pour rendre le contenu accessible de manière performante, fiable et évolutive. Les services Web conformes aux contraintes REST sont appelés services Web RESTful .

    Comme pour les bonnes vieilles requêtes HTTP, lorsque les données sont récupérées à partir d'une API, tout retard dans la réponse du serveur se propagera à l'utilisateur final, retardant ainsi le rendu . Lorsqu'une ressource souhaite récupérer des données à partir d'une API, elle devra demander les données au point de terminaison correspondant. Un composant qui restitue des données à partir de plusieurs ressources, comme un article avec des commentaires et des photos d'auteur dans chaque commentaire, peut nécessiter plusieurs allers-retours vers le serveur pour récupérer toutes les données avant de pouvoir être rendus. De plus, la quantité de données renvoyées via REST est souvent supérieure à ce qui est nécessaire pour rendre ce composant.

    Si de nombreuses ressources nécessitent des données d'une API, l'API peut devenir un goulot d'étranglement des performances. GraphQL fournit une solution performante à ces problèmes. En soi, GraphQL est un langage de requête pour votre API et un runtime côté serveur pour exécuter des requêtes en utilisant un système de type que vous définissez pour vos données. Contrairement à REST, GraphQL peut récupérer toutes les données en une seule requête , et la réponse sera exactement ce qui est requis, sans sur -extraction ou sous -extraction de données comme cela se produit généralement avec REST.

    De plus, parce que GraphQL utilise un schéma (métadonnées qui indiquent comment les données sont structurées), il peut déjà organiser les données dans la structure préférée, donc, par exemple, avec GraphQL, nous pourrions supprimer le code JavaScript utilisé pour gérer la gestion de l'état, produire un code d'application plus propre qui s'exécute plus rapidement sur le client.

    Si vous souhaitez démarrer avec GraphQL ou rencontrez des problèmes de performances, ces articles peuvent vous être très utiles :

    • A GraphQL Primer : Pourquoi nous avons besoin d'un nouveau type d'API par Eric Baer,
    • A GraphQL Primer: The Evolution Of API Design par Eric Baer,
    • Conception d'un serveur GraphQL pour des performances optimales par Leonardo Losoviz,
    • Les performances de GraphQL expliquées par Wojciech Trocki.
Deux exemples d'interfaces mobiles pour les messages en utilisant Redux/REST (à gauche) et Apollo/GraphQL (à droite)
Une différence entre REST et GraphQL, illustrée via une conversation entre Redux + REST à gauche, un Apollo + GraphQL à droite. (Source de l'image : Hacker Noon) ( Grand aperçu )
  1. Allez-vous utiliser AMP ou Instant Articles ?
    Selon les priorités et la stratégie de votre organisation, vous voudrez peut-être envisager d'utiliser l'AMP de Google ou les Instant Articles de Facebook ou Apple News d'Apple. Vous pouvez obtenir de bonnes performances sans eux, mais AMP fournit un cadre de performances solide avec un réseau de diffusion de contenu (CDN) gratuit , tandis que les articles instantanés augmenteront votre visibilité et vos performances sur Facebook.

    L'avantage apparemment évident de ces technologies pour les utilisateurs est la garantie de performances , de sorte qu'ils peuvent même parfois préférer les liens AMP-/Apple News/Instant Pages aux pages "régulières" et potentiellement gonflées. Pour les sites Web riches en contenu qui traitent beaucoup de contenu tiers, ces options pourraient potentiellement aider à accélérer considérablement les temps de rendu.

    À moins qu'ils ne le fassent pas. Selon Tim Kadlec, par exemple, "les documents AMP ont tendance à être plus rapides que leurs homologues, mais ils ne signifient pas nécessairement qu'une page est performante. AMP n'est pas ce qui fait la plus grande différence du point de vue des performances".

    Un avantage pour le propriétaire du site Web est évident : la possibilité de découvrir ces formats sur leurs plateformes respectives et une visibilité accrue dans les moteurs de recherche.

    Eh bien, du moins c'est comme ça avant. Étant donné que l'AMP n'est plus une exigence pour Top Stories , les éditeurs pourraient plutôt s'éloigner de l'AMP pour une pile traditionnelle ( merci, Barry ! ).

    Néanmoins, vous pouvez également créer des AMP Web progressifs en réutilisant les AMP comme source de données pour votre PWA. Inconvénient? De toute évidence, une présence dans un jardin clos met les développeurs en mesure de produire et de maintenir une version distincte de leur contenu, et dans le cas d'Instant Articles et d'Apple News sans URL réelles (merci Addy, Jeremy !) .

  2. Choisissez judicieusement votre CDN.
    Comme mentionné ci-dessus, en fonction de la quantité de données dynamiques dont vous disposez, vous pourrez peut-être "sous-traiter" une partie du contenu à un générateur de site statique, en le poussant vers un CDN et en servant une version statique à partir de celui-ci, évitant ainsi les demandes au serveur. En fait, certains de ces générateurs sont en fait des compilateurs de sites Web avec de nombreuses optimisations automatisées prêtes à l'emploi. À mesure que les compilateurs ajoutent des optimisations au fil du temps, la sortie compilée devient plus petite et plus rapide au fil du temps.

    Notez que les CDN peuvent également servir (et décharger) du contenu dynamique. Il n'est donc pas nécessaire de restreindre votre CDN à des ressources statiques. Vérifiez à nouveau si votre CDN effectue la compression et la conversion (par exemple, l'optimisation des images et le redimensionnement à la périphérie), s'il prend en charge les travailleurs des serveurs, les tests A/B, ainsi que les inclusions côté périphérie, qui assemblent les parties statiques et dynamiques des pages. à la périphérie du CDN (c'est-à-dire le serveur le plus proche de l'utilisateur) et d'autres tâches. Vérifiez également si votre CDN prend en charge HTTP sur QUIC (HTTP/3).

    Katie Hempenius a écrit un guide fantastique sur les CDN qui fournit des informations sur la façon de choisir un bon CDN , comment l'affiner et toutes les petites choses à garder à l'esprit lors de l'évaluation d'un. En général, c'est une bonne idée de mettre en cache le contenu de manière aussi agressive que possible et d'activer les fonctionnalités de performance CDN telles que Brotli, TLS 1.3, HTTP/2 et HTTP/3.

    Remarque : d'après les recherches de Patrick Meenan et Andy Davies, la priorisation HTTP/2 est effectivement cassée sur de nombreux CDN, soyez donc prudent lorsque vous choisissez un CDN. Patrick a plus de détails dans son exposé sur la priorisation HTTP/2 ( merci, Barry ! ).

    Aperçu CDNPerf des noms CDN et de la vitesse de requête en ms
    CDNPerf mesure la vitesse des requêtes pour les CDN en rassemblant et en analysant 300 millions de tests chaque jour. ( Grand aperçu )

    Lors du choix d'un CDN, vous pouvez utiliser ces sites de comparaison avec un aperçu détaillé de leurs fonctionnalités :

    • Comparaison CDN, une matrice de comparaison CDN pour Cloudfront, Aazure, KeyCDN, Fastly, Verizon, Stackpach, Akamai et bien d'autres.
    • CDN Perf mesure la vitesse des requêtes pour les CDN en rassemblant et en analysant 300 millions de tests chaque jour, avec tous les résultats basés sur les données RUM des utilisateurs du monde entier. Vérifiez également la comparaison des performances DNS et la comparaison des performances du cloud.
    • CDN Planet Guides fournit une vue d'ensemble des CDN pour des sujets spécifiques, tels que Serve Stale, Purge, Origin Shield, Prefetch et Compression.
    • Web Almanac : CDN Adoption and Usage fournit des informations sur les principaux fournisseurs de CDN, leur gestion RTT et TLS, le temps de négociation TLS, l'adoption HTTP/2 et autres. (Malheureusement, les données ne datent que de 2019).

Table des matières

  1. Se préparer : planification et métriques
  2. Fixer des objectifs réalistes
  3. Définir l'environnement
  4. Optimisations des actifs
  5. Construire des optimisations
  6. Optimisations de livraison
  7. Mise en réseau, HTTP/2, HTTP/3
  8. Test et surveillance
  9. Victoires rapides
  10. Tout sur une seule page
  11. Télécharger la liste de contrôle (PDF, pages Apple, MS Word)
  12. Abonnez-vous à notre newsletter par e-mail pour ne pas manquer les prochains guides.