# Single-page application

In informatica con Single-page application (in italiano: applicazione su singola pagina) o in sigla SPA si intende un'applicazione web o un sito web che può essere usato o consultato su una singola pagina web con l'obiettivo di fornire una esperienza utente più fluida e simile alle applicazioni desktop dei sistemi operativi tradizionali.
In un'applicazione su singola pagina tutto il codice necessario (HTML, JavaScript e CSS) è recuperato in un singolo caricamento della pagina o le risorse appropriate sono caricate dinamicamente e aggiunte alla pagina quando necessario, di solito in risposta ad azioni dell'utente.
La pagina non si ricarica in nessun punto del processo, né lascia il controllo in un'altra pagina, sebbene moderne tecnologie web come la API pushState di HTML5 può fornire la percezione e la navigabilità in pagine logiche separate nell'applicazione. L'interazione con una applicazione a singola pagina spesso coinvolge una comunicazione dinamica con il web server.

## Approcci tecnici

Sono disponibili varie tecniche che consentono al browser di conservare una singola pagina anche quando l'applicazione richiede la comunicazione con il server.

### Framework JavaScript

I framework e le librerie JavaScript del browser Web, come AngularJS, Ember.js, ExtJS, Knockout.js , Meteor.js, React, Vue.js e Svelte hanno adottato i principi SPA. A parte ExtJS, tutti questi sono open source.
* AngularJS è un framework completamente lato client. Il modello di AngularJS si basa sull'associazione dati dell'interfaccia utente bidirezionale. Il data binding è un modo automatico per aggiornare la vista ogni volta che il modello cambia, così come aggiornare il modello ogni volta che la vista cambia. Il modello HTML viene compilato nel browser. La fase di compilazione crea HTML puro, che il browser restituisce nella visualizzazione in tempo reale. Il passaggio viene ripetuto per le successive visualizzazioni di pagina. Nella tradizionale programmazione HTML lato server, concetti come controller e modello interagiscono all'interno di un processo server per produrre nuove visualizzazioni HTML. Nel framework AngularJS, il controller e gli stati del modello vengono mantenuti all'interno del browser client. Pertanto, le nuove pagine possono essere generate senza alcuna interazione con un server.
* Ember.js è un framework per applicazioni JavaScript Web lato client basato sul modello di architettura del software MVC (model – view – controller). Consente agli sviluppatori di creare applicazioni scalabili a pagina singola incorporando idiomi e le migliori pratiche comuni in un framework che fornisce un ricco modello di oggetti, data binding dichiarativa a due vie, proprietà calcolate, modelli di aggiornamento automatico basati su Handlebars.js e un router per gestione dello stato dell'applicazione.Schermata di ExtJs
* ExtJS è anche un framework lato client che consente di creare applicazioni MVC. Ha un proprio sistema di eventi, gestione di finestre e layout, gestione dello stato (stores) e vari componenti dell'interfaccia utente (griglie, finestre di dialogo, elementi del modulo, ecc.). Ha un proprio sistema di classi con caricatore dinamico o statico. L'applicazione costruita con ExtJS può esistere da sola (con lo stato nel browser) o con il server (ad esempio con l'API REST che viene utilizzata per riempire i suoi archivi interni). ExtJS ha solo funzionalità integrate per utilizzare localStorage, quindi le applicazioni più grandi richiedono un server per memorizzare lo stato.
* Knockout.js è un framework lato client che utilizza modelli basati sul pattern Model-View-ViewModel .
* Meteor.js è un framework JavaScript full-stack (client-server) progettato esclusivamente per SPA. Presenta un data binding più semplice rispetto ad Angular, Ember o ReactJS, e utilizza il protocollo Distribuzione Dati e un modello di pubblicazione-sottoscrizione per propagare automaticamente le modifiche ai dati ai client in tempo reale senza richiedere allo sviluppatore di scrivere alcun codice di sincronizzazione. La reattività dello stack completo garantisce che tutti i livelli, dal database ai modelli, si aggiornino automaticamente quando necessario. I pacchetti dell'ecosistema come Server Side Rendering risolvono il problema dell'ottimizzazione dei motori di ricerca.
* React è una libreria JavaScript per la creazione di interfacce utente . È gestito da Facebook, Instagram e una comunità di singoli sviluppatori e aziende. React utilizza un nuovo linguaggio che è un mix di JS e HTML. Diverse aziende utilizzano React con Redux (libreria JavaScript) che aggiunge funzionalità di gestione dello stato, che (con molte altre librerie) consente agli sviluppatori di creare applicazioni complesse.
* Vue.js è un framework JavaScript per la creazione di interfacce utente. Gli sviluppatori di Vue forniscono anche Vuex per la gestione dello stato.
* Svelte è un framework per la creazione di interfacce utente che compila il codice Svelte per manipolazioni DOM JavaScript, evitando la necessità di raggruppare un framework al client e consentendo una sintassi di sviluppo dell'applicazione più semplice.

### Ajax

A partire dal 2006, la tecnica più importante utilizzata è stata l'Ajax. Ajax prevede l'utilizzo di richieste asincrone a un server per dati XML o JSON, come XMLHttpRequest di JavaScript o il più moderno fetch (dal 2017) o l'oggetto ActiveX deprecato. In contrasto con l'approccio dichiarativo della maggior parte dei framework SPA, con Ajax il sito Web utilizza direttamente JavaScript o una libreria JavaScript come jQuery per manipolare il DOM e modificare gli elementi HTML. Ajax è stato ulteriormente reso popolare da librerie come jQuery, che fornisce una sintassi più semplice e normalizza il comportamento Ajax su diversi browser che storicamente avevano comportamenti diversi.

### WebSocket

I WebSocket sono una tecnologia di comunicazione client-server bidirezionale in tempo reale che fa parte della specifica HTML5. Per la comunicazione in tempo reale, il loro utilizzo è superiore ad Ajax in termini di prestazioni e semplicità.

### Trasporto dei dati (XML, JSON e AJAX)

Le richieste al server in genere danno come risultato la restituzione di dati non elaborati (ad es. XML o JSON) o di nuovo HTML. Nel caso in cui l'HTML venga restituito dal server, JavaScript sul client aggiorna un'area parziale del DOM (Document Object Model). Quando vengono restituiti dati grezzi, spesso viene utilizzato un processo JavaScript XML / (XSL) lato client (e nel caso di JSON un modello) per tradurre i dati grezzi in HTML, che viene quindi utilizzato per aggiornare un'area parziale del DOM.

### Eventi inviati dal server

Gli eventi inviati dal server (SSE) sono una tecnica con cui i server possono avviare la trasmissione dei dati ai client del browser. Una volta stabilita una connessione iniziale, un flusso di eventi rimane aperto fino a quando non viene chiuso dal client. Gli SSE vengono inviati tramite HTTP tradizionale e dispongono di una varietà di funzionalità che ai WebSocket mancano, come la riconnessione automatica, eventi ID e la capacità di inviare eventi arbitrari.

### Plugin del browser

Era possibile ottenere chiamate asincrone al server anche utilizzando tecnologie di plug-in del browser come Silverlight, Flash o applet Java, ora deprecati.

### Architettura del server
#### Architettura del server sottile

Una SPA sposta la logica dal server al client, con il ruolo del server web che si evolve in una pura API di dati o servizio web. Questo cambiamento architettonico è stato, in alcuni ambienti, chiamato "architettura server sottile" per evidenziare che la complessità è stata spostata dal server al client.

#### Architettura spessa con stato del server

Il server mantiene lo stato necessario in memoria dello stato client della pagina. In questo modo, quando una qualsiasi richiesta colpisce il server (solitamente azioni dell'utente), il server invia l'HTML e/o il JavaScript appropriato con le modifiche concrete per portare il client al nuovo stato desiderato (solitamente aggiungendo/cancellando/aggiornando una parte del client DOM). Allo stesso tempo, lo stato nel server viene aggiornato. La maggior parte della logica viene eseguita sul server e di solito anche l'HTML viene visualizzato sul server. In un certo senso il server simula un browser Web, riceve eventi ed esegue modifiche delta nello stato del server che vengono propagate automaticamente al client.
Questo approccio richiede più memoria ed elaborazione del server, ma il vantaggio è un modello di sviluppo semplificato perché l'applicazione è completamente codificata nel server e i dati e lo stato dell'interfaccia utente nel server sono condivisi nello stesso spazio.

#### Architettura spessa del server senza stato

Questa è una variante dell'approccio del server "stateful". La pagina client invia i dati che rappresentano il suo stato corrente al server, solitamente tramite richieste Ajax. Utilizzando questi dati, il server è in grado di ricostruire lo stato client della parte della pagina che deve essere modificata e può generare i dati o il codice necessari (ad esempio JSON o JavaScript), che viene restituito al client per portarlo in un nuovo stato, di solito modificando il DOM della pagina in base all'azione del client che ha fatto la richiesta.
Questo approccio richiede l'invio di più dati al server e potrebbe richiedere più risorse per ricostruire parzialmente o completamente lo stato della pagina client nel server. Allo stesso tempo, questo approccio è più facilmente scalabile perché non ci sono dati di pagina per client conservati nel server, quindi le richieste Ajax possono essere inviate a diversi nodi del server senza necessità di condivisione dei dati di sessione o affinità del server.

## Esecuzione in locale

Alcuni SPA possono essere eseguiti da un file locale utilizzando lo schema URI del file. Ciò offre agli utenti la possibilità di scaricare la SPA da un server ed eseguire il file da un dispositivo di archiviazione locale, senza dipendere dalla connettività del server. Se tale SPA desidera archiviare e aggiornare i dati, deve utilizzare Web Storage basato su browser. Queste applicazioni beneficiano di HTML5.

## Sfide con il modello SPA

Poiché la SPA è un'evoluzione rispetto al modello di ridisegno delle pagine senza stato per cui i browser erano stati originariamente progettati, sono emerse alcune nuove sfide. Possibili soluzioni (di varia complessità, completezza e controllo dell'autore) includono:
* Librerie JavaScript lato client.
* Framework Web lato server specializzati nel modello SPA.
* L'evoluzione dei browser e la specifica HTML5, progettata per il modello SPA.

## Critiche

Ai siti web a pagina singola sono state mosse diverse critiche:
* I siti Web a pagina singola sono progettati attorno a un argomento o tema centrale, quindi possono indicizzare solo una singola frase.
* Se un visitatore ha bisogno di saperne di più su un prodotto, un servizio o un contenuto visualizzato sul sito, sarà difficile per un sito Web a pagina singola mostrare più contenuti necessari all'approfondimento di uno o più argomenti.
* Un sito Web a pagina singola ha un solo set di metadati, quindi fornisce solo un tag H1 e un solo tag "description". Non è quindi possibile effettuare il siloing ossia suddividere in sezioni tematiche sulla base delle parole chiave il sito web.
* Avere molti contenuti su una sola pagina significa che essa può diventare pesante e richiederà più tempo per caricarsi rispetto a un sito Web con più pagine.
* La SEO favorisce i siti web con un numero alto di collegamenti, sia interni che esterni. I siti Web a pagina singola hanno una capacità limitata di includere molti collegamenti interni.
* Non funzionano di default i pulsanti "avanti" o "indietro" del browser. Ciò presenta un impedimento all'usabilità quando un utente preme il pulsante Indietro, aspettandosi lo stato della schermata precedente all'interno della SPA, invece viene e presentata la pagina precedente nella cronologia del browser, non dello stesso sito web (come accadeva con i siti fatti in Adobe Flash). La soluzione tradizionale per le SPA è stata quella di modificare l'identificatore del frammento hash dell'URL del browser in base allo stato corrente dello schermo. Ciò può essere ottenuto con JavaScript e fa sì che gli eventi della cronologia degli URL vengano creati all'interno del browser. Finché SPA è in grado di ripristinare lo stesso stato dello schermo dalle informazioni contenute nell'hash dell'URL, viene mantenuto il comportamento del pulsante Indietro previsto. Per risolvere ulteriormente questo problema, la specifica HTML5 ha introdotto pushState e replaceState fornendo accesso programmatico all'URL effettivo e alla cronologia del browser
* Gli strumenti di analisi come Google Analytics fanno molto affidamento sul caricamento di intere nuove pagine nel browser. Le SPA non funzionano in questo modo. Dopo il caricamento della prima pagina, tutte le successive modifiche alla pagina e al contenuto vengono gestite internamente dall'applicazione, che dovrebbe semplicemente chiamare una funzione per aggiornare il pacchetto di analisi. Non riuscendo a chiamare tale funzione, il browser non attiva mai un nuovo caricamento della pagina, non viene aggiunto nulla alla cronologia del browser e lo strumento di analisi non ha idea di chi sta facendo cosa sul sito. È possibile aggiungere eventi di caricamento della pagina a una SPA utilizzando l'API HTML5 "History"; questo aiuterà a integrare l'analisi. La difficoltà sta nel gestirlo e nell'assicurarsi che tutto venga tracciato accuratamente: ciò comporta il controllo di rapporti mancanti e doppie voci. Alcuni framework forniscono integrazioni di analisi open source indirizzate alla maggior parte dei principali fornitori di analisi. Gli sviluppatori possono integrarli nell'applicazione e assicurarsi che tutto funzioni correttamente, ma non è necessario eseguire tutto da zero.