# Errori di build comuni nell’App Router e la loro causa

Cinque errori di build ricorrenti nell’App Router, la causa reale e la correzione: window is not defined, hook senza use client, hydration.

> Pagina: https://ui.eneawork.it/blog/nextjs-errori-build-comuni
> Markdown: https://ui.eneawork.it/blog/nextjs-errori-build-comuni.md

*2026-11-01*

Gli errori di build nell’App Router hanno quasi sempre tre cause: un modulo Node importato nel browser, un hook dentro un server component, un valore non serializzabile passato a un client component. Il messaggio nomina il file, la causa è nel confine.

## I cinque che si vedono di più

## Il primo: window is not defined

Il modulo che tocca window viene valutato quando il server importa il componente. La correzione è spostare l’accesso dentro useEffect, oppure caricare il componente solo sul client. La diagnosi completa è in finestra non definita in Next.js.

## Il terzo: la direttiva nel posto sbagliato

"use client" vale per il file e per tutto ciò che importa. In cima al layout radice rende client l’intero albero; sul componente foglia limita il confine. La mappa dei due mondi è in server-only e client-only.

# riproduci la build prima del push npx tsc --noEmit && npm run build 2>&1 | tail -n 40

## Il quinto: hydration

Il markup del server e quello del client devono coincidere al primo render. Date.now(), Math.random(), localStorage e il fuso orario del browser producono differenze. La correzione è un render iniziale identico, con l’aggiornamento in useEffect. I casi sono in hydration failed: UI iniziale diversa.

Su un catalogo di 111.985 componenti e 1.556 blocchi, misurato il 1 novembre 2026 su ui.eneawork.it, la build tratta ogni pagina come un confine: un errore in un solo client component ferma tutto il deploy. Non esiste una build parziale.

## Dove guardare nel codice

Tre record utili quando l’errore è a runtime invece che in build: le error page, i pattern di gestione errore, e i blocchi form quando l’errore nasce da un handler.

Un 404 dopo il deploy non è un errore di build ma si confonde facilmente: la sequenza è in 404 dopo il deploy. La scelta tra action e route che evita metà di questi errori è in Route Handler o Server Action. Il confronto tra framework con lo stesso albero di build è in Astro vs Next.js.

## Il limite da mettere in conto

Nessuno di questi errori si riproduce in sviluppo con lo stesso ordine di valutazione della build. Un npm run build locale prima del push è l’unico test che li anticipa.

Leggi il primo errore, non l’ultimo. La build si ferma al primo confine rotto, e i successivi sono conseguenze.

## FAQ

### Perché la build fallisce e lo sviluppo no?

Perché la build valuta tutti i moduli con regole più rigide e senza window. Un modulo che funziona nel browser può non avere senso sul server: il confine è il problema, non il comando.

### window is not defined si risolve con typeof?

È una toppa: typeof window evita l’errore ma non evita il markup diverso tra server e client. Meglio useEffect o dynamic con ssr: false.

### Dove va "use client"?

Sul componente più basso che ha stato, eventi o hook. Metterlo in alto rende client tutto il sottoalbero e perdi il rendering server.

### Posso passare una funzione a un client component?

No, le funzioni non sono serializzabili. Passa un dato e gestisci l’azione con una Server Action, oppure definisci la funzione dentro il client component.

### Come evito gli errori di hydration?

Rendendo il primo render identico sui due lati: niente data corrente, niente valori casuali, niente accesso a localStorage durante il render. Aggiorna dopo il montaggio.
