Andrea Casarin

Andrea Casarin

Published on: 10/2/2018, 6:15:04 PM - Reading time: 12 minutes

Applicazioni web a pagina singola, un manifesto

Le applicazioni web a pagina singola (SPA o interfacce web a pagina singola SPI) sono ormai diventate una realtà e hanno superato, grazie agli avanzamenti delle tecnologie web, quasi tutte le problematiche iniziali. Tuttavia non sono ancora così diffuse, soprattutto da questa parte dell’oceano. Ho avuto il piacere di leggere un “vecchio” manifesto che rappresenta il movimento agli albori delle SPI e ho pensato di riproporlo, tradotto in italiano. Eccolo.

Manifesto applicazioni web a pagina singola

Photo by Danika Perkinson.

Manifesto dell’interfaccia a pagina singola

Origini della tecnologia web

Quando Tim Berners Lee ha inventato il web, stava cercando un sistema per pubblicare documenti scientifici accessibili da remoto, attraenti dal punto di vista estetico, semplici da codificare e di facile utilizzo anche per un non tecnico.

In un documento scientifico, le citazioni esterne verso altri documenti sono indispensabili in modo che il lettore, se lo desidera, possa approfondire maggiormente il tema in questione.

Per queste ragioni il World Wide Web è stato concepito come un sistema basato su una pagina (documento) con collegamenti ipertestuali.

Inizialmente il web era un mondo fatto di pagine statiche e link, ma presto la generazione di pagine dinamiche e in generale l’uso del web a servizio di applicazioni web-based ha notevolmente complicato le cose.

L’arrivo delle applicazioni web

Per tanti anni sono stati messi in campo molti sforzi per adattare il paradigma web di pagine e link al campo dello sviluppo di applicazioni. In un’applicazione web infatti la visione di Berners circa documenti statici e link non esiste.

Sono stati fatti diversi tentativi di approccio legato allo sviluppo di applicazioni:

  • Modello 1: traduzione diretta dei modelli originali di pagine e link, dove le pagine sono generate dinamicamente;
  • Modello 2 o MVC: qui i link non puntano direttamente a una pagina già decisa a priori, ma un controller decide quale sarà la pagina successiva in base alle operazioni eseguite nella fase di transizione di pagina;
  • Modello MVC basato sui componenti (Modello 3?): sofisticata versione del Modello 2 che simula come funziona un’applicazione desktop. Si basa su componenti ed eventi: qualsiasi azione dell’utente implica la completa ricostruzione e il ricaricamento della pagina, andando a modificare parzialmente alcune parti a seconda dell’azione eseguita. La pagina e la pagina di transizione sono gestite da componenti che cambiano in base all’evento, simulando il funzionamento dei componenti della programmazione GUI desktop.

In periodi più recenti è stata introdotta la tecnica AJAX, che con l’aiuto del JavaScript consente parziali cambiamenti nelle pagine sino a ottenere nuovi dati dal server senza necessità di ricaricamento. Nonostante la tecnica di parziale cambio pagina sia di molto antecedente all’introduzione dell’XMLHttpRequest (base della programmazione AJAX) in Internet Explorer, questa è stata la sua spinta verso il successo.

Adesso milioni di siti web e di web application usano AJAX per fornire una migliore esperienza all’utente grazie a un’interfaccia più responsive che permette di evitare parzialmente il fastidioso ricaricamento delle pagine.

Nonostante l’uso massiccio di AJAX, ci sentiamo di affermare che il web segue un modello di sviluppo che potremmo chiamare “Modello 2 (MVC) arricchito con AJAX”. Quando si usa AJAX, parlare di “Modello 3” non ha così senso perché AJAX riduce di molto il bisogno della gestione di pagine basata sui componenti (non necessariamente presenti nel Modello 2), e per questo possiamo classificare l’attuale stato dell’arte dello sviluppo web come Modello 3,5. In questo modello la navigazione della pagina è parzialmente evitata nel caso di transizioni di minor stato eseguite da AJAX e JavaScript.

Quali sono gli svantaggi della navigazione e dello sviluppo basati su pagine?

Ogni sviluppatore web conosce le problematiche relative alla navigazione di pagine nelle applicazioni web. Oltre alla perdita di larghezza di banda e il tempo per il processo di ricostruzione di intere pagine, ulteriori difficoltà sono date da cache indesiderate, pulsanti di indietro/avanti, moduli disincronizzati a causa della funzione “auto-riempimento” di alcuni browser, e via dicendo. Non è così raro vedere applicazioni web che nascondono i menù e i bottoni del browser o usano frame o iframe (è il caso delle banche) per evitare criticità legate ai bottoni indietro/avanti.

Lo sviluppo basato su pagine web impone uno stile di programmazione strano, ripetitivo (con molte inclusioni) e inefficiente (sia per la larghezza di banda che per la potenza di calcolo), che non si verifica nello sviluppo desktop.

Cosa impedisce l’uso intensivo di AJAX?

Nel settore dello sviluppo web siamo abituati a distinguere due tipi di soluzioni: applicazioni web e siti web.

Nel primo caso l’applicazione AJAX è sempre più usata poiché non condivide alcuni requisiti imposti per i siti web. Nei siti web infatti l’uso intensivo di AJAX comporta dei problemi.

In siti web pubblici gli utenti sono abituati al concetto di pagina, e legati alla pagina ci sono una serie di requisiti e servizi che si trovano in ogni sito web, come:

  • Bookmarking: ogni pagina web ha URL differenti, e queste URL possono essere salvate come segnalibro. Poiché AJAX può cambiare parzialmente la pagina l’URL è la stessa, e l’utente non può salvare come segnalibro una vista concreta della pagina stessa;
  • Search Engine Optimization (SEO): ogni sito web aspira a essere perfettamente indicizzato dai motori di ricerca come Google. I crawlers di oggi vedono il web come web 1.0 e ciò significa che il codice JavaScript è totalmente ignorato. Quindi qualsiasi modifica parziale eseguita tramite AJAX caricata dal server non viene eseguita e non viene indicizzata dai crawler;
  • Servizi basati sulle visualizzazioni di pagina: in servizi pubblicitari come Google Adsense e nelle visualizzazioni di pagina monitorate con Google Analytics, il numero di pagine caricate è estremamente importante. Ogni cambiamento anche parziale fatto con AJAX non viene contato come nuova visita;
  • Finestre pop-up.

A causa di questi requisiti, l’uso massivo di AJAX non è consigliato nei siti web.

A ogni modo la differenza tra “sito web” e “applicazione web” sta diventando sempre più piccola perché ormai quasi ogni sito web è una sorta di web application…

Dovremmo rinunciare all’uso intensivo delle applicazioni AJAX?

No.

Ci sono soluzioni tecniche per ognuno dei requisiti elencati sopra.

È possibile lo sviluppo di siti web a pagina singola (SPI)?

Sì!

È il momento giusto per iniziare la transizione: ne guadagneranno sia gli sviluppatori che gli utenti. Abbiamo la tecnologia e i moderni browser sono sufficientemente qualificati per permetterci di ottenere questo obiettivo.

Per avere successo in questo “nuovo” metodo di sviluppo web dobbiamo soddisfare tutti i precedenti requisiti di ogni sito web.

Arrivederci pagine, benvenuti stati

In un’applicazione web senza JavaScript la sequenza di stato equivale alle pagine, e in un’applicazione SPI anche il più piccolo cambiamento implica un nuovo “stato” della pagina. Possiamo distinguere due categorie di stati:

  • Stati fondamentali
  • Stati secondari

La differenza tra uno stato e l’altro è molto importante, poiché gli stati fondamentali diventeranno pagine in caso di bisogno. La differenziazione tra fondamentale e secondario dipende dal sito web.

Per meglio capire i due stati possiamo analizzare un caso vero: la convalida di login.

In un’applicazione basata sul concetto classico di pagina, tipicamente il login è costruito usando due pagine, una per lo username e la password e l’altra che mostra le opzioni utente quando la convalida è corretta. La pagina di login verrà ricaricata mostrando alcuni messaggi di errore accanto al modulo di accesso quando l’utente compila il form con i dati sbagliati.

In un sito web a pagina singola, il login iniziale e la pagina di opzioni utente possono essere considerati gli stati fondamentali, e i messaggi di errore accanto al login gli stati secondari.

Facciamo un altro esempio, quello di un sito web basato su pagine da convertire in SPI. In questo caso gli stati fondamentali saranno le pagine e gli stati secondari quelle pagine con modifiche minori, non abbastanza importanti per il bookmarking o per essere analizzate dai crawler.

Interfaccia di pagina singola e bookmarking

Pagine differenti hanno URL differenti. Seguendo la direzione delle SPI come possiamo cambiare uno stato e allo stesso tempo l’URL senza ricaricare per far sì che gli utenti possano salvare il nuovo stato nei preferiti del browser?

C’è un trucchetto che si avvale della parte “àncora” dell’URL (“frammento hash”, “shebang” o “hashbang”). Si tratta dell’ultima parte che, se presente, segue il carattere #. L’àncora, anche conosciuta come collegamento interno alla pagina, è usata per scrollare la pagina in un esatto punto specifico con il contrassegno <a name=”ref”></a>. L’àncora, se modificata, non ricarica la pagina, quindi se il riferimento URL viene cambiato utilizzando il windows.location accanto allo stato della pagina (in questo caso il nuovo stato è “fondamentale”) con JavaScript e AJAX, non viene eseguito alcun ricaricamento. Poiché la URL e lo stato fondamentale sono stati modificati, l’utente può salvare come segnalibro la URL, che contiene le nuove informazioni di stato.

Quando l’utente vuole tornare indietro alla pagina salvata nei preferiti, lo stato di destinazione viene specificato nella parte “àncora” della URL e il server verrà sottoposto a richiesta. Purtroppo la parte di riferimento non viene inviata al server perché essa non ha nulla a che vedere con la posizione remota in HTTP, quindi avremo bisogno di un processo di post-caricamento.

Il server restituirà una pagina iniziale in cui lo stato di destinazione non è specificato, a ogni modo l’oggetto window.location contiene la URL originale inclusa l’àncora. Quando carichiamo la pagina di destinazione possiamo rilevare con JavaScript se windows.location contiene un’àncora e se questa àncora ha le informazioni richieste sullo stato di destinazione. Se è vero possiamo riscrivere la URL aggiungendo alcuni parametri normali per specificare lo stato di destinazione da caricare. Siccome la URL è effettivamente cambiata, viene eseguita una nuova richiesta al server; questa volta lo stato da caricare si trova in un parametro e il server restituisce una nuova pagina con lo stato richiesto.

Un’altra opzione, migliore delle àncore, arriverà con l’avvento dell’HTML5, l’HTML5 History API.

Interfaccia di pagina singola e Search Engine Optimization (SEO)

Il modo più semplice per far sì che il nostro sito web sia processato dai motori di ricerca è quello di offrire due differenti modi di navigazione: SPI per gli utenti e pagine per i web crawlers.

Il prossimo esempio mostra un link con questa idea:

<a href=”URL page” onclick=”return false”>…</a>

Questo link non genererà alcuna azione in un browser con JavaScript abilitato perché la navigazione è disabilitata dal “return false” sull’attributo “onclick”, ma quando un bot indicizza questo link ignora l’attributo perché il codice JavaScript non viene eseguito ed elaborerà la specifica URL come pagina successiva da processare.

Nel campo delle applicazioni SPI, le URL usate per la navigazione di pagina/stato devono contenere uno stato di destinazione, lo stesso tipo di URL usato nel bookmarking SPI che utilizza le àncore per indicare lo stato di destinazione, oppure il target viene scritto direttamente come un normale parametro, quest’ultima opzione è preferibile poiché evita una richiesta al server, ovviamente è possibile utilizzare anche URL “parlanti”.

Attualmente Google esegue già la scansione delle URL AJAX, ovvero delle URL che contengono lo stato di destinazione nella parte di riferimento che segue il carattere #! come specificato in Making AJAX Applications Crawlable, in questo caso il sito web/l’applicazione web deve restituire la pagina prevista richiesta con il parametro _escaped_fragment_.

Allo stesso tempo il framework web SPI può aggiungere un codice specifico al gestore di onclick prima di restituire “false” o può associare un processo in ascolto al link utilizzato per la navigazione della pagina/stato, registrato con addEventListener o attachEvent a seconda del browser. Questo processo eseguirà alcune azioni per comandare il server, solitamente usando AJAX, per cambiare lo stato della pagina. Quando il link viene cliccato, questa modifica di stato non è una nuova pagina perché l’attributo onclick=”… return false” evita il comportamento predefinito.

La tecnica descritta è la più semplice e immediata se si utilizzano link visibili compatibili con i bot e con SPI. Puoi sempre separare entrambe le funzioni, per esempio usando link nascosti per gli utenti ma non per i bot insieme ad altri elementi cliccabili per modificare gli stati SPI, servendoti di JavaScript invisibile per i robot.

La caratteristica più importante di un framework con funzionalità SPI è la generazione di pagine come HTML con lo stato richiesto sul tempo di caricamento e allo stesso tempo la modifica di stato deve essere eseguita con JavaScript e l’aggiornamento parziale della pagina. Questi requisiti sono fondamentali per fornire SPI e simulazione di pagina.

SPI e i bottoni indietro/avanti

I bottoni indietro/avanti rappresentano una fonte di problemi per i tradizionali siti web basati sulle pagine e dovrebbero essere proibiti il prima possibile. Nonostante gli utenti siano abituati a evitare i bottoni Indietro e Avanti quando compilano e inviano un form con i propri dati (perché questo comporta il rischio di comprare due volte lo stesso biglietto aereo o il medesimo libro), l’uso dei pulsanti Indietro/Avanti è molto diffuso.

Apparentemente il paradigma SPI rompe il tradizionale modo di navigare un sito web, perché in teoria i bottoni Indietro/Avanti non hanno senso in SPI (non vi sono pagine) e i browser non forniscono un buon controllo di questi comandi.

Non è però del tutto vero. Il comportamento Indietro/Avanti può essere simulato al posto della navigazione di pagina (e della cronologia in generale) Indietro/Avanti e può essere usato per cambiare lo stato corrente al precedente/futuro stato. In questo caso un codice JavaScript può individuare quando la parte “àncora” di una URL cambia e richiede all’applicazione di cambiare lo stato. Poiché il browser non cambia la pagina, la tua applicazione è pienamente responsabile del comportamento Indietro/Avanti, evitando i tipici problemi di inaspettato utilizzo di Indietro/Avanti quando l’utente invia un modulo. Ora in SPI non esiste tale modulo e non c’è navigazione di pagine fuori controllo dell’applicazione/sito web.

SPI e servizi basati sulle visualizzazioni di pagina

Servizi pubblicitari e contatori di pagine viste si basano sul numero di pagine caricate. In entrambi i casi puoi usare elementi iframe nascosti che contengono una pagina web vuota con gli scripts richiesti per eseguire questi servizi.

Nel caso di servizi pubblicitari come Google Adsense, l’inserimento dinamico di iframe implica il caricamento di nuovi annunci, per questo motivo ogni cambiamento di stato può comportare un nuovo caricamento dell’iframe con l’annuncio. Google Adsense sembra essere in grado di rilevare quando lo script è eseguito dentro un iframe a tiene conto del contenuto della pagina contenitrice. Potrebbe essere una buona scelta inserire un parametro che identifichi lo stato fondamentale che sta caricando l’iframe.

Nel caso del contatore di visite, possiamo usarle per monitorare le visite utente agli stati fondamentali del nostro sito web SPI. In questo caso aggiungiamo un iframe nascosto contenente una pagina web vuota con lo script di monitoraggio. Con un semplice parametro possiamo indicare quale stato fondamentale è stato visitato. Il nostro iframe dovrebbe essere globale (sempre lo stesso nella pagina). Quando la pagina viene caricata per la prima volta, lo stato fondamentale che viene caricato (specificato nella URL) dovrebbe essere indicato all’iframe con un parametro. Dopo il caricamento della pagina, ogni cambiamento di stato fondamentale dovrebbe essere notificato all’iframe modificando la URL via JavaScript secondo il nuovo stato fondamentale: questa URL comporterà un nuovo caricamento dell’iframe (che indicherà una nuova visita).

SPI e finestre pop-up

Quando viene creata una nuova finestra, il modello SPI viene compromesso. Il fondamentalismo non va bene, non ci sono problemi se lo stato di questa nuova finestra non ha niente a che vedere con lo stato della finestra genitore, in questo caso le finestre pop-up vanno bene.

Il problema si presenta quando qualsiasi azione messa in pratica sulla finestra pop-up (modale o non modale) ha una qualsiasi influenza sulla finestra genitore, e allora la coordinazione tra le pagine diventa complicata. Per esempio non c’è alcuno standard web per creare finestre modali perché il concetto di pagina è per tradizione sempre stato un elemento indipendente e perciò il suo ciclo di vita diventa difficile da coordinare da un’altra pagina.

Fortunatamente il problema può essere risolto da qualche tempo in SPI: puoi simulare finestre modali o non modali dentro la stessa pagina web, senza che alcuna finestra reale venga creata. Nel caso di finestre non modali, ogni elemento HTML con posizione assoluta può essere una “finestra non modale” e puoi creare finestre modali usando posizioni assolute, controllando lo z-index e l’opacità di elementi “sovrapposti” della pagina (“livelli modali”). Queste soluzioni sono valide in un contesto SPI.

Con un piccolo sforzo, anche lo stato che mostra una finestra modale può essere uno stato fondamentale e perciò navigabile dai bots dei motori di ricerca.

Un cambiamento culturale per gli sviluppatori web

Molti web developers (e web frameworks) pensano al web come basato sulle pagine. La riduzione a una singola pagina implica un cambiamento di mentalità davvero importante su come noi creiamo siti web e applicazioni web. Tuttavia questo cambiamento non è poi così radicale grazie ad AJAX che oggi è molto usato e ha ridotto il numero di pagine tipico dei siti web. In sostanza ci ha portati vicino al “nuovo” modello di sviluppo SPI.

Nel nuovo web SPI il tag <form> scompare e in generale scompare il bisogno di sessione utilizzata come gestore di dati che seguono sequenze di pagine. Ora la protagonista è la pagina lato client, con alcune simmetrie nel server (la pagina nel server). Infatti, poiché ci liberiamo dalla coordinazione di pagine con le sessioni, evitiamo una serie di problemi come la cattiva pratica di alcuni utenti che aprono diverse finestre con la stessa pagina. Questa pratica solitamente compromette la sessione e l’applicazione in generale.

La programmazione SPI è basata su eventi allo stesso modo del desktop, perché nel desktop molte delle applicazioni vengono eseguite nella stessa finestra e quando esistono finestre “figlio” queste sono completamente gestite dalla finestra principale e realmente modali.

Seguendo il paradigma evolutivo dello sviluppo web, questo “nuovo” approccio potrebbe essere chiamato Model 4.

Un cambiamento culturale per gli utenti?

Non molto. Con i segnalibri e la simulazione Indietro/Avanti gli utenti finali non differenziano tra un sito web SPI e lo stesso sito a pagine. Inoltre il sito SPI sarà più responsivo e verrà rimosso il tipico lampeggio e lo scorrimento della pagina di navigazione.

Fattibilità tecnica oggi

Questo manifesto non è una dichiarazione di intenti, ma l’espressione del desiderio di promuovere un “nuovo” modo di costruire siti web già reali. Lo studio tecnico di cui sopra ha sempre avuto il web framework Java ItsNat come la tecnologia base dello sviluppo di siti web SPI. Nonostante ItsNat sia stato concepito sin dal primo giorno per questo tipo di applicazioni/siti, le tecniche precedenti possono essere applicate ad altri framework web, o questi framework possono evolversi per fornire servizi per siti web SPI con requisiti di simulazione di pagina.

Alcuni requisiti di questi siti web SPI per poter sostituire i tradizionali siti web a pagine, come la simulazione di pagina di stati fondamentali sul tempo di caricamento, sono possibili esclusivamente con framework web centrici perché il rendering HTML deve avvenire sul server in fase di caricamento. L’HTML renderizzato in fase di caricamento e lo stesso inserito dinamicamente con JavaScript sono le chiavi caratteristiche di un web framework pronto a costruire siti web SPI. I framework client centrici potrebbero avere un maggior ruolo per la realizzazione dei cosiddetti stati secondari.

Il manifesto in lingua originale

Note: questa traduzione potrebbe non essere aggiornata poiché questo manifesto è “vivo”.

http://itsnat.sourceforge.net/php/spim/spi_manifesto_en.php