Next.js 16: every shiny update you'll have to stomach
Next.js 16 just landed and, surprise, you don't get a vote. The official docs pile every change into the upgrade guide, so either you read it or you get blindsided. Spare me the marketing fluff: here’s what you actually have to deal with to stay relevant.
Environment: no more excuses
Still running Node 18? Tough. Next.js 16 requires Node 20.9 or higher, TypeScript 5.1+, and modern browsers (Chrome/Edge/Firefox 111+, Safari 16.4+). If your fleet can’t keep up, you’re stuck on 15 with the security holes that come with it. No negotiating.
Turbopack is the baseline
Forget the --turbopack flag. The engine is on by default in dev and build, with config promoted to the root (turbopack instead of experimental.turbopack). Clinging to a custom webpack? The build now fails loudly so you stop ignoring it. Sure, you can pass --webpack to delay the inevitable, but Turbopack is the sanctioned path, now with dev disk caching and no more tilde imports for Sass.
HTTP APIs go fully async
Next.js 15 left a legacy sync escape hatch for cookies, headers, draftMode, params, and searchParams. That’s gone: everything is async now, including opengraph-image, twitter-image, icon, and apple-icon. Still using the old signatures? Get ready to sprinkle await everywhere. Bonus: next typegen now emits helpers (PageProps, LayoutProps, RouteContext) so you don’t drown in types.
React side: 19.2 and a stabilized compiler
Next.js 16 ships React 19.2 (canary) and its entourage: View Transitions, useEffectEvent, Activity. On top of that, the React Compiler graduates to a stable option (reactCompiler: true). Yes, it stretches build time because Babel still transpiles behind the curtain, but you get automatic memoization without hand-wiring memo calls.
Cache Components and smarter navigation
The ancient experimental_ppr flag is gone. Instead, Next.js introduces cacheComponents to enable the latest Partial Pre-Rendering iteration. SPA transitions now prefetch with more finesse: layout deduplication, incremental prefetching… More requests, far less payload. You wanted comfort? Done, and you don’t even change a line.
New cache APIs: revalidateTag, updateTag, refresh
The caching layer hits the gym:
revalidateTag(tag, cacheLife)accepts a duration profile so you can refresh calmly.updateTag(tag)brings read-your-writes to Server Actions without hacks.refresh()lets you rerender the client router right after a server action.cacheLifeandcacheTagfinally lose theunstable_scarlet letter.
Either you use the opportunity to clarify your revalidation strategy, or you keep duct-taping and pray state doesn’t implode.
middleware is dead, long live proxy
Files named middleware.{js,ts} turn into proxy. The runtime is locked to nodejs; edge is out (for now). Same story for options: skipMiddlewareUrlNormalize becomes skipProxyUrlNormalize. The docs hand-hold you through it, but yes, you’ll be batch-renaming files.
Images: time to tighten up
Sacred cow next/image takes several hits:
- Query strings on local images now demand
images.localPatterns.search. minimumCacheTTLdefaults to 4 h to calm obsessive revalidation.- Size
16vanishes fromimageSizes, the defaultqualitiesshrink to[75], and local IPs are blocked unless you setdangerouslyAllowLocalIP. - Redirects cap at 3 and
next/legacy/imagebows out. images.domainsis deprecated in favor ofremotePatterns.
If you left that config unattended, expect surprises in production.
DX: split dev/build output, DIY ESLint, scroll stays put
next dev and next build now write to separate folders (.next/dev for dev) and lock each other to stop double instances. Loading next.config is streamlined, so your fragile process.argv.includes('dev') hacks are done.
On linting, next lint is gone. You’re on the vanilla ESLint CLI (or Biome if you like pain), and you adopt the flat config that @next/eslint-plugin-next now enforces. And if you were forcing instant scroll, set data-scroll-behavior="smooth" on <html>—Next.js finally leaves your CSS alone.
Alpha extras and assorted scraps
- Build Adapters API (alpha): an experimental hook so your infra can meddle with the build pipeline.
- Modern Sass API via
sass-loaderv16. - AMP,
next lint,serverRuntimeConfig/publicRuntimeConfig, weirddevIndicators,experimental.dynamicIO, andunstable_rootParamsare gone.
You wanted a “full-stack framework”? Next.js 16 reminds you who’s in charge. Either you comply—npm install next@latest react@latest react-dom@latest, grab the @types if TypeScript is your jam, run npx @next/codemod@canary upgrade latest—or you sulk. See you at the next release.