Next.js for SDET

57Next.js for SDET

What you will master here

  • App Router vs Pages Router
  • Server Components, Client Components, "use client"
  • Data fetching: server fetch, ISR, SSG, SSR, dynamic
  • Route handlers + Server Actions
  • Middleware
  • Testing approach: unit (Vitest) + integration + E2E (Playwright)
  • SDET-specific gotchas (hydration, caching, streaming)

57.1 App Router vs Pages Router

App Router (default since 13)Pages Router (legacy)
File-based: app/users/[id]/page.tsxFile-based: pages/users/[id].tsx
Server Components by defaultClient Components by default
Streaming + SuspenseSSR/SSG/ISR via getServerSideProps etc.
Route handlers (route.ts)API routes (pages/api/*.ts)
Server Actions

57.2 Server vs Client Components

// app/page.tsx — Server Component by default
async function Home() {
  const users = await fetch('https://api/users').then(r => r.json());
  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

// app/Cart.tsx — Client Component (interactive)
'use client';
import { useState } from 'react';
export function Cart() {
  const [items, setItems] = useState<Item[]>([]);
  return <button onClick={() => setItems([...items, newItem])}>Add</button>;
}

Server Components never ship JS to the browser. They reduce bundle size dramatically. They can't use useState, useEffect, browser-only APIs.

57.3 Data fetching modes

ModeWhenHow
Static (SSG)Build-time HTML, fastestDefault if no dynamic data
ISRStatic but revalidate every N secondsfetch(url, { next: { revalidate: 60 } })
SSRPer-request server renderfetch(url, { cache: 'no-store' }) or dynamic = 'force-dynamic'
ClientFetch in useEffect / SWR / TanStack QueryuseEffect / useSWR

57.4 Route handlers

// app/api/users/route.ts
export async function GET() {
  const users = await db.user.findMany();
  return Response.json(users);
}
export async function POST(req: Request) {
  const body = await req.json();
  const u = await db.user.create({ data: body });
  return Response.json(u, { status: 201 });
}

57.5 Server Actions

// app/actions.ts
'use server';
export async function createOrder(formData: FormData) {
  const sku = formData.get('sku') as string;
  const order = await db.order.create({ data: { sku }});
  return order.id;
}

// app/CartForm.tsx
import { createOrder } from './actions';
export default function CartForm() {
  return (
    <form action={createOrder}>
      <input name="sku" />
      <button>Buy</button>
    </form>
  );
}

Server Actions are RPC-like functions you can call from client components or use as form actions. No need to write a route + client fetch.

57.6 Middleware

// middleware.ts
import { NextResponse } from 'next/server';

export function middleware(req) {
  if (!req.cookies.get('token')) {
    return NextResponse.redirect(new URL('/login', req.url));
  }
}
export const config = { matcher: ['/dashboard/:path*'] };

57.7 Testing Next.js apps

LayerTool
Pure logic (utils, hooks)Vitest
UI componentsVitest + RTL OR Playwright CT
Route handlers / APIVitest hitting the function, or Playwright request to dev server
Server ActionsIntegration: spin Next dev server, call action via form submission
E2E (full app)Playwright with the dev server running
// playwright.config.ts — boot Next in CI
webServer: {
  command: 'npm run start',
  url: 'http://localhost:3000',
  reuseExistingServer: !process.env.CI,
  timeout: 120_000,
},

57.8 SDET gotchas

Module 61 — Next.js Q&A

Server vs Client Components — fundamental difference?
Server Components render on the server only — no JS shipped to browser. They can read databases/files directly. Client Components render on both (initial SSR + hydration on client) and can use state/effects/browser APIs. Mark with 'use client' at top of file.
SSG vs SSR vs ISR?
SSG: build-time static, fastest. SSR: per-request server render, fresh but slower. ISR: static cached, revalidates every N seconds (best of both). Set per fetch or per route segment.
What's a Server Action?
A function marked 'use server' that runs on the server. Callable from client components or HTML forms. Removes the need for a separate API route + client fetch.
How do you handle auth in Next.js middleware?
Edge middleware in middleware.ts inspects the request, checks a cookie/header, and either continues, rewrites, or redirects. Runs before any page/route handler. Use a matcher to limit which paths it applies to.
What's a hydration mismatch?
Server HTML differs from the client's first render. React logs a warning, may re-render the affected subtree (visible flicker). Causes: new Date(), random ids, browser-only APIs in render, timezone differences.
How do you E2E-test a Next.js app?
Playwright with webServer config booting next start (or next dev locally). Visit pages, assert by role/text. For data-dependent tests, seed via Server Action or API route.
What's the App Router fetch cache behaviour?
By default, fetch in Server Components is cached forever (treated like SSG). Add { cache: 'no-store' } for dynamic, or { next: { revalidate: 60 } } for ISR. Forgetting → stale data bug.
How do you stream a slow part of the page?
Wrap a slow component in <Suspense fallback={...}>. Next streams the shell + fallback immediately, then sends the real content when ready. Tests should wait on the loaded state, not initial.