Développeur FullStack & Devops

Notes et mémos techniques

Next.js

Next.js est devenu le leader incontesté 🎖 des webapp React type SSR ! Next.js 12 Canary est la version courante développée et maintenue par des équipes de Vercel (ex Zeit), la société qui a levé 102$ million en 2021 pour accélérer les développements.

D'un point de vue de développeur, ce qui rend l'usage de Next.js intuitif, réside dans le fait le routage est une correspondance entre un fichier JavaScript et une URL, le fichier /pages/toto.js générera automatiquement l'URL http://monsite/toto, et ce modèle supporte le routage dynamique (avec des variables dans l'URL).

Next.js est donc LE standard en 2022, mais un sérieux concurrent commence a émerger : Remix 💿, créé par les concepteurs de React Router (Michael Jackson & Ryan Florence et rejoints depuis peu Kent C. Dodds). Ecouter une discussion des créateurs de Remix (podcast 🔉).

Intérêts de Next.js

Les intérêts de Next.js par rapport à une solution classique à base d'API Back + React en front sont :

  • supporte différentes méthodes de rendu de pages (SSR, SSG et CSR) permettant d'optimiser le SEO. Le SSR est ce qui a fait le succès 🥂 de Next.js.
  • utilise un routage (routing) très intuitif et dynamique
  • support de > ES6 ainsi que typescript
  • guides d'upgrade assez clean pour migrer de version de Next.js et un codemod est également disponible pour automatiser en partie les migrations
  • learning curve plutot raide pour les développeurs React avec une prise en main rapide grâce à leurs super tutos 🚀

Routing

Pages

Une URL est crée automatiquement dès qu'on dépose un fichier JS ou JSX dans le dossier /pages/ (par convention). De plus Next.js supporte:

  • les nested routes : l'URL pages/toto/titi/tutu sera routée vers le fichier tutu.jsx pages/toto/titi/tutu.jsx
  • les Index routes : l'URL pages/toto/titi/tutu sera routée vers le fichier index suivant : pages/toto/titi/tutu/index.jsx
  • les routes dynamiques (depuis v9) : utilisation d'une variable d'URL /:toto pour etre routé vers /[toto].js (valable pour les dossiers aussi), et de catch all routes /[...toto].js

API

Il est possible depuis Next.js 10 de créer des API dans Next.js, pages/api sera mappé à /api/*.

⚠ Attention, cette solution est plutot limités comparée à des solutions robustes et pleines de fonctionnalités comme NestJS. D'après la doc le use case typique d'une API Next.js est de jouer un role de Proxy soit pour masquer des URL internes, soit pour utiliser des variables d'environements. J'ajouterai que c'est un très bon moyen de POCer 🏎 !

Public

Pour les éléments statiques (images, css, robots.txt, favicon.ico, et autres) il existe le dossier /public/ (anciennement /static/) réservé a cet effet.

Cycle de vie du Router

Le Router de Next.js propose un ensemble d'évènements qu'il est possible d'écouter :

  • routeChangeStart(url)
  • routeChangeComplete(url)
  • routeChangeError(err, url)
  • beforeHistoryChange(url)
  • hashChangeStart(url)
  • hashChangeComplete(url)

Navigation

La navigation est simplifiée par l'usage de :

  • composants Next.js Link du package next/link

  • un routage imperatif grâce au hook useRouter du package next/router qui nous retourne un objet router auxquels on peut associer l'objet URL et par exemple pour la fonction router.push on a les arguments :

    • la prop href permet au framework de faire le lien entre l'URL et les fichiers JS contenu dans le dossier pages
    • la prop as permet de créer et d'afficher dans le HTML résultant un href alias (ici le lien pointera vers /p/xxx), qu'il faudra traité coté back (méthode render de l'API next).
  • le shallow routing qui consiste à ne pas avoir a charger une nouvelle fois la page et byepasser toutes les méthodes de data fetching (getServerSideProps, getStaticProps, et getInitialProps) si on navigue sur la meme page.

Data fetching

La Next.js 9.3 a introduit 3 nouvelles fonctions async exporté de pages Next.js qui vont progressivement remplacer l'ancien getInitialProps:

getServerSideProps

getServerSideProps permet de générer la page en mode SSR coté serveur.

Le point intéressant à noter est que lors de l'utilisation de next/link or next/router pour la navigation, seul un appel d'API est émis pour récupérer la data sous forme de JSON. Cela permet de ne pas casser le flow de la SPA.

getStaticProps

getStaticProps implique la génération d'une page en mode SSG (comme avec Gatsby).

On utilise le SSG lorsque les données sont disponible lors du build et ne sont pas spécifique à un utilisateur (peuvent etre mis en cache).

getStaticPaths

getStaticPaths est utilisé dans le cas de pages utilisant getStaticProps (ci-dessus) et exploitant la fonctionnalité de Dynamic Routes pour générer toutes les pages avec toutes les combinaisons de routes lors de la build.

getInitialProps (à ne plus utiliser)

Depuis Next.js 9.3 il est recommandé de ne plus utiliser getInitialProps mais plutot getStaticProps ou getServerSideProps.

Styling

styled-jsx le CSS-in-JS de Next.js

Next.js a fait le choix d'embarquer styled-jsx qui est une des solution CSS-in-JS mais il existe de nombreuses solutions qu'il est possible d'utiliser avec Next.js (Styled Components ou Emotion), voir des exemples d'utilisations dans cette section exemple.

Le CSS-in-JS permet d'avoir des styles scopés au niveau du composant, des styles dynamiques fonction du code, et surtout d'appliquer les styles lors du rendu coté serveur.

L'utilisation est encore une fois très intuitive, car il suffit d'écrire ses styles directement dans des balises <style jsx>  à l’intérieur de ses composants en utilisant la syntaxe template strings:

<style global jsx>{`
    h1, a {
    font-family: "Arial";
  }
`}</style>

CSS classique

Il est cependant possible depuis Next.js 9.2 d'utiliser les CSS Modules 🎉 en important directement des .css (styles global) ou des .module.css pour des styles scopés au composant.

Squelettes de projets Next.JS

Un outil sympathique, qui fourni un squelette de projet Next.js/React/Redux est create-next-app, parfait pour voir rapidement les branchements entre ces outils :)

Concernant Material UI, il y a un exemple de projet Nexjs/MaterialUI ainsi qu'une doc SSR Material UI.

Divers et DX

Appels Ajax

Support de fetch par polyfill coté navigateur (depuis Next.js 9.1.7), et coté Nodejs(depuis Nexjs 9.4). Nous pouvons donc simplement utiliser fetch() partout dans notre code.

Variable d'environnements

Next 9.4 a simplifié et clarifié l'usage des variable d'environnements avec :

  • le support des fichiers .env
  • par défaut les vars d'env sont disponible uniquement coté serveur, mais s'ils sont prefixés par NEXT_PUBLIC_ il sont également disponibles dans le navigateur (plus besoin d'utiliser le next.config.js pour y définir les vars)

Chemins absolu pour les imports and aliases

Toujours depuis la 9.4 Next.js supporte désormais la personnalisation des chemins d'imports de modules dans le jsconfig.json (JS projects) ou le tsconfig.json (TS projects) :

  • les chemins absolu en ajoutant la clé "baseUrl": "." .
  • les alias de modules en ajoutant la clé "paths": {"@/design-system/*": ["components/design-system/*"]}
// tsconfig.json ou jsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/design-system/*": ["components/design-system/*"]
    }
  }
}

Debugging

La doc Next.js nous fourni (et c'est plutot rare pour le souligner) le .vscode/launch.json qui est la config de VSCode pour debugger un projet Next.js 😍🥳 🎉. Elle est un peu particulière parcequ'il faut pouvoir debugger coté client et serveur :

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev"
    },
    {
      "name": "Next.js: debug client-side",
      "type": "pwa-chrome",
      "request": "launch",
      "url": "http://localhost:3000"
    },
    {
      "name": "Next.js: debug full stack",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "console": "integratedTerminal",
      "serverReadyAction": {
        "pattern": "started server on .+, url: (https?://.+)",
        "uriFormat": "%s",
        "action": "debugWithChrome"
      }
    }
  ]
}
javascript
react
nextjs
gaphql
gatsby
jamstack
vercel
static
programmation
rédigé le 02/10/18, mis à jour le 22/02/22 par Behrouze
A proposCheat SheetsOutilsVidéos