Fermer

septembre 24, 2021

Leçons apprises Reconstruire un grand site Web de commerce électronique avec Next.js (étude de cas) —


Résumé rapide ↬

Chez Unplatform, Jonne et son équipe sont passés d'une plate-forme de commerce électronique intégrée plus traditionnelle à une plate-forme sans tête qui utilise Next.js pour le front-end. Dans cet article, il partage les leçons les plus importantes qu'ils ont apprises lors de la reconstruction d'un grand site de commerce électronique avec Next.js.

Dans notre entreprise, Unplatformnous construisons des sites de commerce électronique depuis des décennies. Au cours de ces années, nous avons vu la pile technologique évoluer des pages rendues par le serveur avec quelques JavaScript et CSS mineurs à des applications JavaScript complètes.

La plate-forme que nous utilisions pour nos sites de commerce électronique était basée sur ASP.NET et à l'époque. les visiteurs ont commencé à s'attendre à plus d'interaction, nous avons ajouté React pour le front-end. Bien que le mélange des concepts d'un framework web de serveur comme ASP.NET avec un framework web côté client comme React ait rendu les choses plus compliquées, nous étions plutôt satisfaits de la solution. C'était jusqu'à ce que nous passions à la production avec notre client le plus achalandé. À partir du moment où nous avons mis en ligne, nous avons rencontré des problèmes de performances . Core Web Vitals sont importants, encore plus dans le commerce électronique. Dans cette étude de Deloitte : Les millisecondes font des millionsles enquêteurs ont analysé les données des sites mobiles de 37 marques différentes. En conséquence, ils ont constaté qu'une amélioration des performances de 0,1 seconde peut entraîner une augmentation de 10% de la conversion. un proxy inverse. Cela nous a même obligé à désactiver certaines parties des fonctionnalités du site. Nous avons fini par avoir une solution très compliquée et coûteuse qui, dans certains cas, ne servait que quelques pages de manière statique. Next.js est un framework Web basé sur React qui vous permet de générer des pages de manière statique, mais vous pouvez également toujours utiliser le rendu côté serveur, ce qui le rend idéal pour le commerce électronique. Il peut être hébergé sur un CDN comme Vercel ou Netlify, ce qui se traduit par une latence plus faible. Vercel et Netlify utilisent également des fonctions sans serveur pour le rendu côté serveur, qui est le moyen le plus efficace d'évoluer.

Défis

Développer avec Next.js est incroyable, mais il y a certainement des défis. L'expérience de développeur avec Next.js est quelque chose dont vous avez juste besoin de faire l'expérience. Le code que vous écrivez s'affiche instantanément dans votre navigateur et la productivité s'envole. C'est également un risque car vous pouvez facilement vous concentrer trop sur la productivité et négliger la maintenabilité de votre code. Au fil du temps, cela et la nature non typée de JavaScript peuvent entraîner la dégradation de votre base de code. Le nombre de bogues augmente et la productivité commence à baisser.

Cela peut également être difficile du côté d'exécution. Les moindres changements dans votre code peuvent entraîner une baisse des performances et d'autres éléments essentiels du Web. En outre, une utilisation imprudente du rendu côté serveur peut entraîner des coûts de service inattendus.

Regardons de plus près nos leçons apprises pour surmonter ces défis.

  1. Modularisez votre base de code
  2. Lint et formatez votre code
  3. Utilisez TypeScript
  4. Planifiez les performances et mesurez les performances
  5. Ajoutez des contrôles de performances à votre porte de qualité
  6. Ajoutez des tests automatisés
  7. Gérez vos dépendances de manière agressive
  8. Utilisez un service d'agrégation de journaux
  9. Fonctionnalité de réécriture de Next.js Active l'adoption incrémentielle

Plus après le saut ! Continuez à lire ci-dessous ↓

Leçon apprise : Modularisez votre base de code

Les frameworks frontaux comme Next.js facilitent grandement la mise en route de nos jours. Vous venez d'exécuter npx create-next-app et vous pouvez commencer à coder. Mais si vous ne faites pas attention et commencez à taper du code sans penser à la conception, vous pourriez vous retrouver avec une grosse boule de boue.

Lorsque vous exécutez npx create-next-appvous aurez une structure de dossiers comme celle-ci (c'est également ainsi que la plupart des exemples sont structurés) :

/public
  logo.gif
/src
  /lib
    /crochets
      useForm.js
  /api
     contenu.js
  /Composants
     En-tête.js
     Layout.js
  /pages
     Index.js

Nous avons commencé par utiliser la même structure. Nous avions des sous-dossiers dans le dossier des composants pour les composants plus gros, mais la plupart des composants se trouvaient dans le dossier des composants racine. Il n'y a rien de mal avec cette approche et c'est bien pour les petits projets. Cependant, au fur et à mesure que notre projet grandissait, il est devenu plus difficile de raisonner sur les composants et leur utilisation. Nous avons même trouvé des composants qui n'étaient plus du tout utilisés ! Cela favorise également une grosse boule de boue, car il n'y a pas d'indication claire sur le code qui devrait dépendre de quel autre code.

Pour résoudre ce problème, nous avons décidé de refactoriser la base de code et de regrouper le code par modules fonctionnels (un peu comme les modules NPM) au lieu de concepts techniques :

/src
  /modules
    /catalogue
      /Composants
        productblock.js
    /vérifier
      /api
        cartservice.js
      /Composants
        panier.js

Dans ce petit exemple, il y a un module de paiement et un module de catalogue. Regrouper le code de cette manière permet une meilleure découverte : en regardant simplement la structure des dossiers, vous savez exactement quel type de fonctionnalité se trouve dans la base de code et où la trouver. Cela rend également beaucoup plus facile de raisonner sur les dépendances . Dans la situation précédente, il y avait beaucoup de dépendances entre les composants. Nous avons eu des demandes d'extraction de modifications dans la caisse qui ont également eu un impact sur les composants du catalogue. Cela a augmenté le nombre de conflits de fusion et rendu plus difficile les modifications. directionnel) et introduire un niveau « projet » qui relie tout ensemble :

/src
  /modules
    /commun
      /atomes
      /lib
    /catalogue
      /Composants
        productblock.js
    /vérifier
      /api
        cartservice.js
      /Composants
        panier.js
    /chercher
  /projet
    /disposition
      /Composants
    /modèles
      productdetail.js
      panier.js
  /pages
    panier.js

Un aperçu visuel de cette solution :

Un aperçu d'un exemple de projet modularisé

Un aperçu d'un exemple de projet modularisé (Large preview)

Le niveau projet contient le code pour la mise en page du site e-commerce et les modèles de pages. Dans Next.js, un composant de page est une convention et aboutit à une page physique. D'après notre expérience, ces pages ont souvent besoin de réutiliser la même implémentation et c'est pourquoi nous avons introduit le concept de « modèles de page ». Les modèles de page utilisent les composants des différents modules, par exemple, le modèle de page de détail du produit utilisera des composants du catalogue pour afficher les informations sur le produit, mais également un composant d'ajout au panier du module de paiement.

Nous avons également un point commun. module, car il y a encore du code qui doit être réutilisé par les modules fonctionnels. Il contient des atomes simples qui sont des composants React utilisés pour fournir un aspect et une sensation cohérents. Il contient également du code d'infrastructure, pensez à certains crochets de réaction génériques ou au code client GraphQL.

Avertissement : Assurez-vous que le code dans le module commun est stable et réfléchissez toujours à deux fois avant d'ajouter du code ici, afin d'éviter l'enchevêtrement de code.

Micro Front-Ends

Dans des solutions encore plus grandes ou lorsque vous travaillez avec différentes équipes, il peut être judicieux de diviser encore plus l'application en micro-frontends. En bref, cela signifie diviser encore plus l'application en plusieurs applications physiques hébergées indépendamment sur différentes URL. Par exemple : checkout.mydomain.com et catalog.mydomain.com. Ceux-ci sont ensuite intégrés par une autre application qui agit comme un proxy.

La fonctionnalité de réécriture de Next.js est idéale pour cela et son utilisation comme celle-ci est prise en charge par ce que l'on appelle Multi Zones.

 Un exemple de configuration multizone

Un exemple de configuration multizone (Large preview)

L'avantage des multi-zones est que chaque zone gère ses propres dépendances. Cela facilite également l'évolution incrémentielle de la base de code : si une nouvelle version de Next.js ou de React sort, vous pouvez mettre à niveau les zones une par une au lieu d'avoir à mettre à niveau l'intégralité de la base de code en une seule fois. Dans une organisation multi-équipes, cela peut réduire considérablement les dépendances entre les équipes.

Autres lectures

Leçon apprise : Lint And Format Your Code

C'est quelque chose que nous avons appris dans un projet précédent : si vous travaillez dans le même base de code avec plusieurs personnes et n'utilisez pas de formateur, votre code deviendra bientôt très incohérent. Même si vous utilisez des conventions de codage et effectuez des révisions, vous commencerez bientôt à remarquer les différents styles de codage, donnant une impression désordonnée du code.

Un linter vérifiera votre code pour les problèmes potentiels et un formateur s'assurera que le le code est formaté de manière cohérente. Nous utilisons ESLint & plus joli et pensons qu'ils sont géniaux. Vous n'avez pas à penser au style de codage, ce qui réduit la charge cognitive pendant le développement.

Heureusement, Next.js 11 prend désormais en charge ESLint prêt à l'emploi (https://nextjs.org/blog/next -11), ce qui le rend très facile à configurer en exécutant npx next lint. Cela vous fait gagner beaucoup de temps car il est livré avec une configuration par défaut pour Next.js. Par exemple, il est déjà configuré avec une extension ESLint pour React. Mieux encore, il est livré avec une nouvelle extension spécifique à Next.js qui détectera même les problèmes avec votre code qui pourraient potentiellement avoir un impact sur le Core Web Vitals de votre application ! Dans un paragraphe ultérieur, nous parlerons des portes de qualité qui peuvent vous aider à éviter de pousser du code vers un produit qui endommage accidentellement vos Core Web Vitals. Cette extension vous donne des commentaires beaucoup plus rapidement, ce qui en fait un excellent ajout. . De plus, dans certains cas, nous avons rencontré des bogues en raison de types d'accessoires manquants ou incorrects transmis aux composants.

TypeScript est un sur-ensemble de JavaScript et ajoute des types, ce qui permet à un compilateur de vérifier statiquement votre code, un peu comme un linter sous stéroïdes.

Au début du projet, nous ne voyions pas vraiment l'intérêt d'ajouter du TypeScript. Nous avons pensé que c'était juste une abstraction inutile. Cependant, un de nos collègues a eu de bonnes expériences avec TypeScript et nous a convaincus de l'essayer. Heureusement, Next.js offre une excellente prise en charge de TypeScript et TypeScript vous permet de l'ajouter à votre solution de manière incrémentielle. Cela signifie que vous n'avez pas besoin de réécrire ou de convertir l'intégralité de votre base de code en une seule fois, mais vous pouvez commencer à l'utiliser immédiatement et convertir lentement le reste de la base de code.

Une fois que nous avons commencé à migrer les composants vers TypeScript, nous avons immédiatement trouvé des problèmes. avec des valeurs erronées transmises aux composants et aux fonctions. De plus, la boucle de rétroaction des développeurs s'est raccourcie et vous êtes averti des problèmes avant d'exécuter l'application dans le navigateur. Un autre grand avantage que nous avons trouvé est qu'il facilite beaucoup la refactorisation du code : il est plus facile de voir où le code est utilisé et vous repérez immédiatement les accessoires et le code des composants inutilisés. En bref, les avantages de TypeScript :

  1. Réduit le nombre de bogues
  2. Facilite la refactorisation de votre code
  3. Le code devient plus facile à lire

Autres lectures

Leçon apprise : Planifier les performances et mesurer Performance

Next.js prend en charge différents types de pré-rendu : génération statique et rendu côté serveur. Pour de meilleures performances, il est recommandé d'utiliser la génération statique, qui se produit pendant le temps de construction, mais ce n'est pas toujours possible. Pensez aux pages de détails sur les produits qui contiennent des informations sur les stocks. Ce type d'informations change souvent et l'exécution d'un build à chaque fois ne s'adapte pas bien. Heureusement, Next.js prend également en charge un mode appelé Incremental Static Regeneration (ISR), qui génère toujours la page de manière statique, mais en génère une nouvelle en arrière-plan toutes les x secondes. Nous avons appris que ce modèle fonctionne très bien pour les applications plus importantes. Les performances sont toujours excellentes, cela nécessite moins de temps CPU que le rendu côté serveur et cela réduit les temps de construction : les pages ne sont générées qu'à la première requête. Pour chaque page que vous ajoutez, vous devez penser au type de rendu nécessaire. Tout d'abord, voyez si vous pouvez utiliser la génération statique ; sinon, optez pour la régénération statique incrémentielle, et si cela n'est pas non plus possible, vous pouvez toujours utiliser le rendu côté serveur.

Next.js détermine automatiquement le type de rendu en fonction de l'absence de getServerSideProps et les méthodes getInitialProps sur la page. Il est facile de faire une erreur, ce qui pourrait entraîner le rendu de la page sur le serveur au lieu d'être générée de manière statique. La sortie d'un build Next.js montre exactement quelle page utilise quel type de rendu, alors assurez-vous de vérifier cela. Il permet également de surveiller la production et de suivre les performances des pages et le temps CPU impliqué. La plupart des hébergeurs vous facturent en fonction du temps CPU, ce qui permet d'éviter les mauvaises surprises. Je décrirai comment nous surveillons cela dans la Leçon apprise : utilisez un paragraphe de service d'agrégation de journaux.

Taille de l'ensemble

Pour obtenir de bonnes performances, il est essentiel de minimiser la taille de l'ensemble. Next.js a beaucoup de fonctionnalités prêtes à l'emploi qui aident, par ex. fractionnement automatique du code. Cela garantira que seuls les JavaScript et CSS requis sont chargés pour chaque page. Il génère également différents bundles pour le client et pour le serveur. Cependant, il est important de garder un œil sur ces derniers. Par exemple, si vous importez des modules JavaScript dans le mauvais sens, le JavaScript du serveur peut se retrouver dans le bundle client, augmentant considérablement la taille du bundle client et nuisant aux performances. L'ajout de dépendances NPM peut également avoir un impact considérable sur la taille du bundle.

Heureusement, Next.js est livré avec un analyseur de bundles qui vous donne un aperçu du code qui occupe quelle partie des bundles.

 L'analyseur de bundles Webpack vous indique la taille. des packages de votre bundle

L'analyseur de bundles webpack vous montre la taille des packages de votre bundle (Large preview)

Autres lectures

Leçon apprise : ajouter des contrôles de performances à votre porte de qualité

L'un des grands avantages de l'utilisation de Next.js est la possibilité de générer des pages de manière statique et de pouvoir déployer l'application à la périphérie ( CDN), ce qui devrait se traduire par d'excellentes performances et Web Vitals. Nous avons appris que, même avec une excellente technologie comme Next.js, obtenir et conserver un excellent score de phare est vraiment difficile. Il est arrivé un certain nombre de fois qu'après le déploiement de certains changements dans la production, le score du phare a considérablement diminué. Pour reprendre le contrôle, nous avons ajouté des tests phares automatiques à notre portail qualité. Avec cette action Github, vous pouvez ajouter automatiquement des tests de phare à vos demandes d'extraction . Nous utilisons Vercel et chaque fois qu'une demande d'extraction est créée, Vercel la déploie sur une URL d'aperçu et nous utilisons l'action Github pour exécuter des tests phares sur ce déploiement.

Un exemple des résultats phares sur une demande d'extraction Github[19659033]Un exemple des résultats du phare sur une demande d'extraction Github (<a href= Grand aperçu)

Si vous ne souhaitez pas configurer vous-même l'action GitHub, ou si vous souhaitez aller encore plus loin, vous pouvez également envisager un service de surveillance des performances tiers comme DebugBear. Vercel propose également une fonctionnalité d'analysequi mesure les principaux Web Vitals de votre déploiement de production. Vercel Analytics collecte en fait les mesures des appareils de vos visiteurs, donc ces scores sont vraiment ce que vos visiteurs vivent. Au moment de la rédaction de cet article, Vercel Analytics ne fonctionne que sur les déploiements de production.

Leçon apprise : ajouter des tests automatisés

Lorsque la base de code s'agrandit, il devient plus difficile de déterminer si les modifications de votre code ont pu rompre les fonctionnalités existantes. D'après notre expérience, il est essentiel d'avoir un bon ensemble de tests de bout en bout comme filet de sécurité. Même si vous avez un petit projet, cela peut vous rendre la vie tellement plus facile lorsque vous avez au moins quelques tests de fumée de base. Nous utilisons Cypress pour cela et nous l'adorons. La combinaison de l'utilisation de Netlify ou de Vercel pour déployer automatiquement votre pull request sur un environnement temporaire et l'exécution de vos tests E2E est inestimable.

Nous utilisons cypress-io/GitHub-action pour exécuter automatiquement les tests cypress contre nos demandes de tirage. Selon le type de logiciel que vous construisez, il peut être utile d'avoir également des tests plus granulaires à l'aide d'Enzyme ou de JEST. Le compromis est que ceux-ci sont plus étroitement couplés à votre code et nécessitent plus de maintenance. )

Leçon apprise : Gérer vos dépendances de manière agressive NPM a rendu l'ajout de packages si facile et il semble y avoir un package pour tout de nos jours. Avec le recul, souvent, lorsque nous avons introduit un nouveau bogue ou subi une baisse des performances, cela avait quelque chose à voir avec un package NPM nouveau ou mis à jour.

Avant d'installer un package, vous devez donc toujours vous poser les questions suivantes :[19659084]Quelle est la qualité du package ?

  • Que signifie l'ajout de ce package pour la taille de mon bundle ?
  • Ce package est-il vraiment nécessaire ou existe-t-il des alternatives ?
  • Le package est-il toujours activement maintenu ?
  • Pour gardez la taille du bundle petite et pour minimiser l'effort nécessaire pour maintenir ces dépendances, il est important de garder le nombre de dépendances aussi petit que possible. Votre futur moi vous en remerciera lors de la maintenance du logiciel.

    Astuce : L'extension Import Cost VSCode affiche automatiquement la taille des packages importés.[19659090] Suivez les versions de Next.js

    Il est important de rester à jour avec Next.js et React. Non seulement cela vous donnera accès à de nouvelles fonctionnalités, mais les nouvelles versions incluront également des corrections de bogues et des correctifs pour les problèmes de sécurité potentiels. Heureusement, Next.js rend la mise à niveau incroyablement facile en fournissant des Codemods (https://nextjs.org/docs/advanced-features/codemods. Ce sont des transformations de code automatiques qui mettent automatiquement à jour votre code.

    Mise à jour. Dépendances

    Pour la même raison, il est important de garder les versions Next.js et React actuelles ; il est également important de mettre à jour les autres dépendances. Le dependabot de Github (https://github.com/dependabot ) peut vraiment aider ici. Il créera automatiquement des Pull Requests avec des dépendances mises à jour. Cependant, la mise à jour des dépendances peut potentiellement casser des choses, donc avoir des tests automatisés de bout en bout ici peut vraiment vous sauver la vie.

    Leçon apprise : Utiliser un journal Service d'agrégation

    Pour s'assurer que l'application se comporte correctement et pour détecter les problèmes de manière préventive, nous avons constaté qu'il est absolument nécessaire de configurer un service d'agrégation de journaux. Vercel vous permet de vous connecter et de consulter les journaux, mais ceux-ci sont diffusés en flux réel -temps et ne sont pas persistants. Il ne prend pas non plus en charge la configuration des alertes et des notifications.

    Certaines exceptions peuvent mettre longtemps à apparaître. Par exemple, nous avions configuré Stale-While-Revalidate pour une page particulière. À un moment donné, nous avons remarqué que les pages n'étaient pas actualisées et que les anciennes données étaient servies. Après avoir vérifié la journalisation Vercel, nous avons constaté qu'une exception se produisait lors du rendu en arrière-plan de la page. En utilisant un service d'agrégation de journaux et en configurant une alerte pour les exceptions, nous aurions pu le détecter beaucoup plus tôt.

    Les services d'agrégation de journaux peuvent également être utiles pour surveiller les limites des plans tarifaires de Vercel. La page d'utilisation de Vercel vous donne également des informations à ce sujet, mais l'utilisation d'un service d'agrégation de journaux vous permet d'ajouter des notifications lorsque vous atteignez un certain seuil. Mieux vaut prévenir que guérir, en particulier en matière de facturation.

    Vercel propose un certain nombre d'intégrations prêtes à l'emploi avec des services d'agrégation de journaux, notamment Datadog, Logtail, Logalert, Sentry, etc.

    Affichage le journal des requêtes Next.js dans Datadog

    Affichage du journal des requêtes Next.js dans Datadog ( Grand aperçu)

    Autres lectures

    Leçon apprise : la fonctionnalité de réécriture de Next.js permet une adoption incrémentielle

    À moins que le site Web actuel ne pose de graves problèmes, peu de clients seront ravis de réécrire l'intégralité du site Web. Mais que se passerait-il si vous pouviez commencer par reconstruire uniquement les pages les plus importantes en termes de Web Vitals ? C'est exactement ce que nous avons fait pour un autre client. Au lieu de reconstruire l'intégralité du site, nous ne reconstruisons que les pages les plus importantes pour le référencement et la conversion. Dans ce cas, les pages de détail du produit et de catégorie. En les reconstruisant avec Next.js, les performances ont considérablement augmenté.

    La fonctionnalité de réécriture de Next.js est idéale pour cela. Nous avons construit un nouveau front-end Next.js qui contient les pages du catalogue et l'avons déployé sur le CDN. Toutes les autres pages existantes sont réécrites par Next.js sur le site Web existant. De cette façon, vous pouvez commencer à profiter des avantages d'un site Next.js sans effort ni risque. en faisant des tests de performance sérieux, nous avons été ravis des résultats. Non seulement les temps de réponse des pages et Web Vitals étaient bien meilleurs qu'auparavant, mais les coûts d'exploitation étaient également une fraction de ce qu'ils étaient auparavant. Next.js et JAMStack vous permettent généralement d'évoluer de la manière la plus rentable.

    Passer d'une architecture plus orientée back-end à quelque chose comme Next.js est un grand pas. La courbe d'apprentissage peut être assez raide, et au départ, certains membres de l'équipe se sentaient vraiment en dehors de leur zone de confort. Les petits ajustements que nous avons faits, les leçons apprises de cet article, ont vraiment aidé avec cela. De plus, l'expérience de développement avec Next.js donne un incroyable coup de pouce à la productivité. Le cycle de rétroaction des développeurs est incroyablement court !

    Autres lectures

    Smashing Editorial" width="35" height="46" loading="lazy" decoding="async(vf, il)




    Source link