Deze site draait op Next.js 16, net als de sites die we voor klanten bouwen. De meeste wijzigingen in versie 16 melden zich vanzelf: de build faalt en je weet waar je moet kijken. Een paar doen dat niet. Alles lijkt goed, tot iemand merkt dat iets anders werkt dan vorige week. Dit zijn de wijzigingen die ons tijd kostten, en een paar uit de upgrade-notities die op dezelfde manier verrassen.
1. next build controleert je code niet meer
In Next.js 15 draaide next build de linter mee. In 16 is next lint verwijderd en doet de build dat niet meer. Een lintfout die vroeg de build stopte, gaat nu ongemerkt naar productie.
De oplossing is kort: draai de linter zelf, vóór de build.
"scripts": {
"lint": "eslint",
"build": "next build"
}
npm run lint && npm run build
Next levert een codemod die de oude opzet omzet: npx @next/codemod@canary next-lint-to-eslint-cli .
2. setState in een effect is nu een error
Met de ESLint-configuratie van Next.js 16 (en eslint-plugin-react-hooks 7) is de regel react-hooks/set-state-in-effect een error. Dit patroon, dat jaren gewoon was, faalt nu de lint:
useEffect(() => {
if (window.matchMedia("(max-width: 640px)").matches) setDevice("mobiel");
}, []);
We liepen er deze week nog tegenaan, bij een fotogalerij die op een telefoon standaard de mobiele weergave moest tonen. Voor een waarde die alleen in de browser bestaat, zoals een mediaquery, is useSyncExternalStore het juiste gereedschap:
const NARROW = "(max-width: 640px)";
const onChange = (cb: () => void) => {
const m = window.matchMedia(NARROW);
m.addEventListener("change", cb);
return () => m.removeEventListener("change", cb);
};
const [chosen, setDevice] = useState<Device | null>(null);
const narrow = useSyncExternalStore(onChange, () => window.matchMedia(NARROW).matches, () => false);
const device = chosen ?? (narrow ? "mobiel" : "desktop");
De derde functie geeft de waarde voor de server: daar bestaat geen scherm. Kiest de bezoeker zelf, dan wint die keuze. Voor puur visuele dingen, zoals een teller of een animatie bij het scrollen, is de DOM direct aanpassen via een ref vaak beter dan state.
3. Soepel scrollen maakt elke paginawissel traag
Staat scroll-behavior: smooth in je CSS op <html>? Vroeger zette Next dat tijdens een navigatie even uit, zodat een nieuwe pagina direct bovenaan begon. In 16 doet Next dat niet meer. Elke klik op een link wordt dan een langzame scroll naar boven.
Wil je het oude gedrag terug, zet dan een attribuut op <html>:
<html lang="nl" data-scroll-behavior="smooth">
4. priority op een afbeelding is verouderd
<Image priority> werkt nog, maar is verouderd ten gunste van preload. De documentatie zegt er meteen bij dat je in de meeste gevallen beter loading="eager" of fetchPriority="high" gebruikt. Bij een gewone <img> is fetchPriority="high" hoe dan ook de manier om de grote afbeelding bovenaan voorrang te geven.
Ook goed om te weten
Deze drie kwamen we niet zelf tegen, maar ze staan in de upgrade-notities en je merkt ze pas als je goed kijkt:
- Afbeeldingskwaliteit.
images.qualitiesstaat standaard op alleen[75]. Eenquality={90}op een afbeelding wordt dan stil 75, de dichtstbijzijnde toegestane waarde. Wil je meer, zet de waarden dan innext.config. - Afbeeldingen langer in de cache.
images.minimumCacheTTLging van 60 seconden naar 4 uur. Verander je een afbeelding op de bron zonder de naam te wijzigen, dan kan de oude versie nog uren blijven staan. middlewareheet nuproxy. Het oude bestand werkt nog, maar is verouderd. Hernoemmiddleware.tsnaarproxy.tsen de functie naarproxy. Let op:proxydraait altijd op Node.js. Heb je de edge-runtime nodig, dan blijf je voorlopig bijmiddleware.
Laat je assistent eerst de meegeleverde documentatie lezen
Next.js 16 zet de documentatie in het pakket zelf, in node_modules/next/dist/docs/. De lijst met wijzigingen staat in 01-app/02-guides/upgrading/version-16.md. In onze Next-projecten staat in AGENTS.md dat Claude of Codex die docs leest voordat er code geschreven wordt. Een model kent vaak nog de oude versie van Next, en dan schrijft het met veel zelfvertrouwen code voor de vorige versie.
Een opdracht die daarbij helpt:
Lees node_modules/next/dist/docs/01-app/02-guides/upgrading/version-16.md en loop onze code na op alles wat daarin staat. Draai daarna npm run lint en npm run build en meld wat je aanpast.
Veelgemaakte fouten
Alleen op de build vertrouwen. Een groene build zegt in 16 niets meer over lintfouten.
De linter uitzetten omdat de nieuwe regel lastig is. De regel wijst meestal op een render te veel. useSyncExternalStore of een ref is bijna altijd de nette oplossing.
Een model laten upgraden zonder de docs. Dan krijg je code die in versie 15 klopte.
Bouw je sites met Claude of Codex en wil je ze via git live zetten? Lees van git push naar live of bekijk de webhosting.