“All’epoca bastava un solo file…”
Il PHP con cui avevo avuto a che fare all’università era davvero comodo. In un unico file index.php potevi scrivere i tag HTML, aprire in mezzo <?php ?> e inserirci anche il codice per interrogare il database. Non esisteva una vera separazione tra frontend e backend. Bastava dichiarare una variabile per poterla usare ovunque nell’HTML, e praticamente non c’erano errori dovuti alla comunicazione dei dati.
Ma nel momento in cui, sul lavoro, sono passato a uno stack con Vue.js sul frontend e Spring Boot sul backend, è iniziato l’inferno.
“Ho avviato il server Spring in locale, ho aperto anche la schermata di Vue, allora perché i dati non arrivano?”
La console degli strumenti di sviluppo di Chrome era tappezzata di messaggi d’errore rossi.
Access to XMLHttpRequest at ... has been blocked by CORS policy
Che cos’è esattamente questo “CORS” che continua a bloccare i miei dati? E perché abbiamo abbandonato il metodo comodo di un tempo, in cui bastava un solo file, per separarci volontariamente in frontend e backend?

Chi deve cucinare? (SSR vs CSR)
Per capire questo cambiamento, bisogna prima capire chi prepara il “piatto” chiamato pagina web, cioè l’HTML. Ed è proprio qui che sta la differenza tra SSR (Server Side Rendering) e CSR (Client Side Rendering).
1. SSR: un pranzo già pronto (PHP, JSP)
- Come funziona: il server (la cucina) prepara riso, contorni e zuppa, li sistema con cura in un portapranzo (HTML) e lo spedisce.
- Client (browser): deve solo sollevare il coperchio del portapranzo e mostrarne il contenuto.
- Vantaggi: la prima schermata si carica in fretta. I motori di ricerca (SEO) leggono facilmente il contenuto.
- Svantaggi: anche per cambiare un solo contorno bisogna ricevere di nuovo l’intero portapranzo. (Sfarfallio della schermata)
2. CSR: un meal kit consegnato a casa (React, Vue)
- Come funziona: il server non cucina. Invia soltanto gli ingredienti (dati JSON) e la ricetta (JavaScript).
- Client (browser): con gli ingredienti ricevuti cucina direttamente sul mio computer (nel browser) e costruisce la schermata.
- Vantaggi: si può sostituire un contorno alla volta, quindi i cambi di schermata sono fluidissimi (sembra un’app). Il carico sul server diminuisce.
- Svantaggi: all’inizio bisogna scaricare la ricetta (i file JS), quindi il caricamento iniziale è lento.
[Tip] CSR e SPA non sono esattamente la stessa cosa
Spesso i due termini vengono usati come se fossero sinonimi, ma a rigore non lo sono.
- CSR (Client Side Rendering): è il “come” (How). Indica il modo in cui il browser disegna la schermata.
- SPA (Single Page Application): è la “forma” (What). Indica un’applicazione composta da una sola pagina.
Di solito usiamo la CSR per costruire una SPA. In altre parole, siccome vogliamo evitare lo sfarfallio dovuto ai ricaricamenti completi usando una sola pagina (SPA), scegliamo un approccio in cui è il browser stesso a ridisegnare le parti necessarie (CSR).
Il motivo per cui usiamo Vue.js o React è l’esperienza utente. Per far sì che un sito web si comporti in modo fluido come un’app per smartphone, abbiamo spostato l’atto del “cucinare” dal server al browser.

CORS, il vigilante che blocca gli ospiti indesiderati
Separando frontend (Vue) e backend (Spring), ci siamo ritrovati di fatto con “due case”.
- Casa del frontend:
localhost:8080(server Vue) - Casa del backend:
localhost:3000(server Spring)
Ed è proprio qui che nasce il problema. Per motivi di sicurezza, il browser web segue una regola di base: “non fidarti troppo facilmente di risorse che arrivano da un’altra Origin”. Questa è la SOP, la Same Origin Policy.
Immagina questo scenario. Io sono connesso a Naver, e da un sito creato da un hacker parte di nascosto una richiesta al server di Naver che dice: “dammi i dati personali di questo utente”. Se il browser non bloccasse una cosa del genere, tutte le mie informazioni verrebbero esposte.
Ecco perché il browser blocca per impostazione predefinita le richieste quando l’origine, cioè dominio o porta, è diversa. Ma per lo sviluppo noi abbiamo volutamente separato le porte. Vogliamo solo usare i nostri dati, e invece il browser, come un vigilante, ci dice: “La tua porta non corrisponde. Accesso negato.” Questa è la vera natura di un errore CORS, cioè Cross-Origin Resource Sharing.
[Code Verification] Rilasciare un lasciapassare
Il modo per risolvere il problema, in realtà, è semplice. Il server, cioè il backend, deve soltanto scrivere un lasciapassare per il browser, il vigilante, dicendo: “Questa persona è un ospite che ho invitato io. Lascialo entrare.”
In Spring Boot, questo lasciapassare può essere rilasciato tramite un semplice file di configurazione.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 1. Per tutti i percorsi API
.allowedOrigins("http://localhost:8080") // 2. Consenti le richieste da questo origin
.allowedMethods("GET", "POST", "PUT", "DELETE") // 3. Consenti questi tipi di richieste
.allowCredentials(true); // 4. Cookie e credenziali sono consentiti
}
}
Analisi:
allowedOrigins: è la parte più importante. Se qui scrivi l’indirizzo del server frontend (localhost:8080), il server Spring mette nell’header della risposta il timbroAccess-Control-Allow-Origin: http://localhost:8080prima di inviarla.- Il browser controlla questo timbro e, pensando “Ah, il padrone del server ha dato il permesso”, passa i dati al frontend.
Una cosa importante: non bisogna aprire tutto con allowedOrigins("*") solo per pigrizia. Sarebbe come lasciare la porta di casa spalancata con un cartello che dice: “Benvenuti, ladri”.
Consiglio pratico: quando usare cosa?
Quindi significa che la CSR, cioè Vue o React, è sempre la risposta giusta? No. Nella pratica bisogna scegliere in base all’obiettivo.
- Pagine di amministrazione (Admin), dashboard:
- Consigliato: CSR (Vue, React)
- Motivo: ci sono molte interazioni con i dati e non serve comparire sui motori di ricerca. Conta una reattività scattante, come in un’app.
- Siti di notizie, blog, home page di e-commerce:
- Consigliato: SSR (Next.js, Nuxt.js)
- Motivo: devono farsi trovare bene nelle ricerche su Google (SEO), e quando arriva un cliente il contenuto deve apparire subito, invece di una schermata bianca.
- Piccoli progetti personali:
- Consigliato: Thymeleaf (SSR integrato in Spring Boot)
- Motivo: se sviluppi da solo, non ha senso faticare per separare frontend e backend e configurare CORS. Sviluppare tutto in un unico progetto, come ai tempi di PHP, garantisce la massima produttività.
In chiusura: oltre il confine
La vecchia “grande famiglia sotto un unico tetto” dei tempi di PHP era comoda, ma più tutto diventava complesso, più era difficile da gestire. Il modello attuale, con “due famiglie separate” tra frontend e backend, è più fastidioso a causa della comunicazione e del CORS, ma permette a ciascuno di concentrarsi meglio sul proprio ruolo.
Perciò, la prossima volta che ti imbatterai in un errore CORS, prova a non reagire solo con frustrazione. Il browser non ti sta tormentando: sta semplicemente eseguendo un controllo rigoroso per proteggere la tua casa, cioè il tuo server.
Ora il passaggio tra frontend e backend è aperto. I dati possono andare e venire. Ma dove vengono davvero conservati questi dati sul server? Un tempo bastava lanciare una query e recuperarli. In Spring, invece, con cose come JPA ed Entity, sembra quasi che non ti lascino più scrivere SQL direttamente.
La prossima volta vedremo come il “metodo da manuale” della progettazione di database, la normalizzazione, possa diventare un ostacolo nella pratica e perché JPA cerchi con tanta insistenza di nascondere SQL.


