Slik deaktiverer du gjengivelse på serversiden (SSR) i Next.js

Finn ut hvordan du deaktiverer SSR i Next.js og bruker den til å erstatte Create React-appen eller andre tilpassede verktøy.

Next.js er mitt absolutte favorittverktøy for å utvikle React-applikasjoner. Det gir deg en utvikleropplevelse i klassen. Den har også massevis av nyttige funksjoner for å være mer produktive og optimalisere appene dine i produksjon:

  • Statisk og tjenergjengivelse
  • Støtte for TypeScript
  • Flere inngangspunkter
  • Kløyving og trerysting

Tidligere ønsket jeg imidlertid ikke å bruke den for alle mine React-apper. Next.js fungerer ikke uten server-side rendering (SSR) som standard. Jeg foretrakk å bruke en ikke-SSR-løsning som Create React App, når appen min ikke krevde SSR, fordi SSR hadde forårsaket meg så mange unødvendige problemer.

Så en dag la Tanner Linsley, forfatteren av React Query, ut på Twitter at han brukte Next.js uten SSR som erstatning for Create React-appen:

Jeg ble overveldet! Etter litt research klarte jeg dette selv. 🤯

Hvorfor deaktivere SSR i Next.js?

SSR for React-apper er nødvendig i noen få tilfeller:

  • Appens innhold må rangeres høyt i søkeresultatene (SEO).
  • Du trenger forhåndsvisninger på sosiale medier (Facebook, Twitter, Slack osv.).
  • Du trenger de ekstra hastighetsoptimaliseringene det kan gi brukerne dine.

Bruk av SSR har imidlertid flere avveininger og utfordringer:

  • Du trenger et komplisert vertsmiljø. Du kan ikke bare laste opp appen din til en server eller et CDN. Du trenger Node.js-servere som utfører gjengivelsen på serversiden. Dette øker kompleksiteten og koster også mer.
  • Du må sørge for at koden fungerer både på nettleseren og på serveren (Node.js). Dette gjør feilsøking vanskeligere og begrenser deg i noen tilfeller. Du kan for eksempel ikke bruke localStorage til å lagre autorisasjonsinformasjon, men du må sende den i en informasjonskapsel og bruke et informasjonskapselbibliotek som fungerer på serveren og nettleseren.
  • Det påvirker applikasjonsarkitekturen din. For eksempel må gjengivelse på tjenersiden gjøres i én enkelt gjengivelse, så du må hente alle dataene for siden på et enkelt sted (som getInitialProps ). Dette kravet kompliserer datahenting med biblioteker som Redux eller React Query og fører ofte til duplikatkode.

Hvis du ikke trenger SSR, er disse avveiningene ikke verdt det. I utgangspunktet bør du vurdere å deaktivere SSR for alle apper der brukergrensesnittet er bak en pålogging.

Hvordan kan du deaktivere SSR i Next.js?

La oss gå gjennom trinnene for å deaktivere SSR for en fersk Next.js-applikasjon (opprettet med npx create-next-app ).

Trinn 1:Omskriv alle forespørsler til pages/index.js

Next.js støtter å legge til omdirigeringer. Opprett en fil med navnet next.config.js til roten til prosjektet ditt. Legg til følgende konfigurasjon der:

module.exports = {
  target: "serverless",
  async rewrites() {
    return [
      // Rewrite everything to `pages/index`
      {
        source: "/:any*",
        destination: "/",
      },
    ];
  },
};

Disse viderekoblingene fungerer bare i utviklingsmiljøet. I produksjon må du ha en proxy-server som NGINX eller bruke vertsplattformens muligheter (f.eks. Netlifys omdirigeringer) for å utføre disse viderekoblingene.

Trinn 2:Deaktiver SSR for sideinnhold

For å deaktivere SSR for sideinnhold, må vi legge til følgende kode til pages/_app.js :

import '../styles/globals.css'

function SafeHydrate({ children }) {
  return (
    <div suppressHydrationWarning>
      {typeof window === 'undefined' ? null : children}
    </div>
  )
}

function MyApp({ Component, pageProps }) {
  return <SafeHydrate><Component {...pageProps} /></SafeHydrate>
}

export default MyApp

I koden ovenfor pakker vi sideinnholdet vårt til en komponent kalt SafeHydrate som lar oss forhindre at sideinnholdet gjengis på serveren. La oss gå gjennom hva som skjer i koden ovenfor.

Med Next.js kan du sjekke om vi er på serveren ved å sjekke om window objektet er undefined .

if(typeof window === 'undefined') {
  // This code will only execute on the server 
  // and not in the browser
}

Vi kan imidlertid ikke bare pakke inn koden vår i denne if -uttalelse direkte. Hvis du prøver det, vil du legge merke til at React vil produsere en irriterende advarsel om hydreringsmismatch i konsollen:Warning: Expected server HTML to contain a matching <div> in <div>. Dette skjer hvis serverens HTML er forskjellig fra det nettleseren gjengir.

I vårt tilfelle er det trygt å ignorere denne advarselen. For å holde det ryddig, ønsker vi å skjule advarselen fullstendig fra konsollen. Dette kan gjøres ved å gjengi en div med prop suppressHydrationWarning . For bedre lesbarhet lager vi en egen SafeHydrate komponent for dette og pakk inn sidekomponenten vår i den.

Trinn 3:Sjekk at alt fungerer med npm run dev

Kjør nå npm run dev i terminalen din. Etter at serveren kjører på http://localhost:3000/ bør du kunne gå til en hvilken som helst URL (som http://localhost:3000/some/random/path) og se innholdet til index.js der.

Suksess! 🎉

Trinn 4:Bygg produksjonspakker med next export

Vi ønsker å distribuere appen vår som en statisk pakke som kan serveres uten en Node.js-server. For dette tilbyr Next.js kommandoen next export . Det vil lage en statisk versjon av appen din i out katalog.

For å bruke kommandoen, oppdater "build"-skriptet i package.json som dette:

"scripts": {
  ...
  "build": "next build && next export"
  ...
}

Kjør nå npm run build . Når du ser meldingen Export successful , Gratulerer! Du har nå en fungerende statisk Next.js-app i out katalog. 🎉

Du kan sjekke hele eksempelappen fra dette Github-repositoriet

Merknader om ruting og andre avanserte funksjoner

Ruting

Next.js støtter ikke dynamisk ruting hvis du ikke har en server som kjører. Du trenger en ruter som react-router . Oppsettet er det samme som med andre verktøy som Create React App.

Oppdatering av <title> og andre <head> Tagger

Du trenger ikke legge til noe som react-helmet for oppdatering av head , Next.js <Head /> komponenten vil fungere.

Å ha flere separate sider

Hvis du vil, kan du fortsatt bruke Next.js-sider for å ha flere forskjellige sider som separate inngangspunkter for appen din. Dette vil gjøre pakkene dine per rute mindre og øke hastigheten på utviklingsmiljøet ditt fordi bare en del av appen vil bli bygget når du gjør endringer.

For eksempel hvis du har en side /accounts du kan lage en fil pages/account.js og legg til en tilsvarende omskriving:

module.exports = {
  target: "serverless",
  async rewrites() {
    return [
      // Rewrite everything under `/account/ to `pages/account`
      {
        source: "/account/:any*",
        destination: "/account",
      },
      // Rewrite everything else to `pages/index`
      {
        source: "/:any*",
        destination: "/",
      },
    ];
  },
};

Hvordan er dette forskjellig fra å bruke Next.js getStaticProps med getStaticPaths ?

Bruker getStaticProps med getStaticPaths lar deg gjøre Static Site Generation (SSG). Dette betyr at alle sidene i appen din genereres som individuelle .html -filer når du kjører npm run build .

SSG er kjempebra, men har en enkelt stor begrensning:Du må vite alle banene appen din har på forhånd . Dette er ikke mulig med mange apper som har tonnevis av brukerspesifikke stier som /my-payments/123121521241 .

Med tilnærmingen som er beskrevet i denne artikkelen, kan du bruke en dynamisk ruter som react-router med Next.js akkurat som du ville gjort med Create React-appen eller en hvilken som helst tradisjonell enkeltside-app.

Ytterligere ressurser:

  • Denne fantastiske hovedsaken av @tannerlinsley