– Var raskere å lage API med Next.js enn Express

Hvordan sette opp API-er i Next.js og hvordan lagre tilstand med URL-er, i ukas ForrigeUke.

Marcus Haaland forklarer deg hvordan du bygger API-er i Next.js. 📸: kode24 / Bekk
Marcus Haaland forklarer deg hvordan du bygger API-er i Next.js. 📸: kode24 / Bekk Vis mer

Dette var uka for selektiv versjonering og slettede løfter — og 1705 ting som skjedde i frontendverdenen!

Next.js for API

Jeg var ganske blown away da jeg hørte at en luring av en kollega hadde brukt Next.js — ikke for grensesnittet — men for å sette opp et API.

Før du tenker at det er overkill å bruke et rammeverk for bare en brøkdel av funksjonaliteten, så kan jeg si hvorfor valget falt dit:

Det viste seg at med Vercels enkle oppsett, var det raskere å bruke Next.js for hans mål, enn å spinne opp en simplere Express-server.

Lee Robinson har nå hosta opp en ny guide for hvordan du også kan bygge API-er med Next.js. Du kan sjekke ut posten for detaljene, men mest interessant syns jeg det var å høre om når det er lurt og ikke.

Robinson gir deg fire grunner til hvorfor du kan ønske å bruke API via Next.js (da også med et tilhørende grensesnitt):

  • du har flere klienter, som en React- nettside og React Native-app, og vil bruke samme API
  • du har en eksisterende backend, og ønsker å transformere dataene på veien
  • du har webhooks du vil konsumere
  • du vil legge til autentisering

Helt enkelt kan et endepunkt i Next.js se slik ut:

// app/api/users/route.ts

export async function GET(request: Request) {
  // 👇 Her henter du for eksempel data fra databasen din
  const users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
  ];
  
  return new Response(JSON.stringify(users), {
    status: 200,
    headers: { 'Content-Type': 'application/json' }
  });
}

Så kan du kalle API-et med en GET til /api/users.

Det er også tilfeller du ikke trenger å lage API-er i Next.js. Om alle dataene er kun brukt i Next-appen din, trenger du ikke eksponere API-et — og kan heller ta i bruk React serverkomponenter.

Det kan se slik ut:

// app/users/page.tsx

export default async function UsersPage() {
 // 👇 Denne fetchen kjører på serveren
  const res = await fetch('https://api.example.com/users');
 const data = await res.json();
 
 return (
    <ul>
      {data.map((user: any) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );

En annen måte å kommunisere med serveren på er ved hjelp av Server Actions. Robinson forklarer at Server Actions er som automatisk genererte API-ruter for POST-requests, som kan bli kalt fra klienten. Selv om det skjer en request, definerer du ikke ruta manuelt. URL-pathen er nemlig autogenerert og kryptert, så du kan ikke aksessere ruta via /api/users i nettleseren.

Rent praktisk definerer du en funksjon med “use server”- direktivet:

// actions.ts
"use server";

import { getCurrentUser } from "@/data/auth"; // Henter innlogget bruker
import { db } from "@/lib/db"; // Simulert database

export async function updateUser(name: string) {
  const user = await getCurrentUser();
  if (!user) {
    throw new Error("Du må være innlogget for å oppdatere brukeren din.");
  }

  await db.user.update({
    where: { id: user.id },
    data: { name },
  });
}

Så kan du kalle funksjonen i klienten, uten å trenge å definere rute:

// updateUser.tsx
"use client";

import { updateUser } from "@/actions"; // Importer Server Action

export default function UpdateUserForm() {
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    try {
      const message = await updateUser(name);
    } catch (error) {
      alert("Noe gikk galt!");
    }

Så hvor passer server actions inn sammen med RSC og API-ruter?

  • React Server Components brukes hovedsakelig til lesing av data direkte fra databasen eller et API. De kjører på serveren, og sender kun det nødvendige til klienten — uten ekstra nettverkskall fra klienten.
  • Server Actions brukes for mutasjoner (oppretting, oppdatering, sletting) direkte fra klienten, men uten at du manuelt definerer API-endepunkter. De er enklere enn tradisjonelle API-ruter, siden du kan importere dem direkte i komponentene.
  • Next.js API Routes brukes når du trenger mer komplekse API-er, hvis flere klienter skal bruke API-et, eller hvis du trenger spesialtilpasninger for sikkerhet, caching eller annen middleware.

Om du lurer mer på sikkerhet rundt disse valgene, ta en titt her.

URL som state-verktøy

Likt som at det fins mange valg for å kommunisere med serveren, er det også mange valg for state i klienten. Der tror jeg URL-er er et ofte oversett verktøy.

“Vil jeg at brukeren skal beholde samme innhold etter refresh av siden?”, er spørsmålet Sahaj Jain oppfordrer deg til å stille når du lurer på hvilket tilstandsverktøy du vil bruke.

Om du ønsker at en modal skal forbli åpen etter refresh, kan du ikke bare ty til useState, for da vil tilstanden forsvinne med arbeidsminnet. På den andre siden høres en database-oppføring ut som et overkill for en modal, for ikke å snakke om tregt. Men en URL vil la deg persistere innholdet på tvers av økter, og lar brukeren også dele tilstanden med andre. Og det kan til og med være raskere enn localstorage.

Det kan se slik ut:

eksempelside.no/dashboard?modal=open

For utvikleren kan bruk av URL også forenkle koden, ved at tilstanden er global, så du slipper å prop-drille eller ta i bruk andre verktøy for verdier som gjør dataene tilgjengelig.

Før har det vært en utfordring med typesikring for URL-parametere, men nå har det blitt til salgspunktene for visse verktøy, som TanStack Router.

Men la meg gi deg en liten advarsel, før URL-ene dine ender opp slik:

eksempelside.no/dashboard?modal=open&darkmode=true&username=ola&pw=123

Ta også en titt på når du ikke bør bruke URL-er for state.

Det var alt for denne gang. Håper du får en solrik uke! 👋