Manifiesto por una Única Página Web (Single Page Interface)

Actualización: 15 de julio 2011

spiral Los origenes de la tecnología web

Cuando Tim Berners Lee inventó la web buscaba un sistema para poder publicar y visualizar documentación científica de forma remota, que fuera atractiva visualmente, fácil de codificar y fácil de usar para un no informático.

En un documento científico es imprescindible la referencia a otros documentos citados con el fin de que el lector opcionalmente pueda profundizar en el tema que se trata.

Por estas razones el Word Wide Web se concibió como un sistema de páginas (documentos) e hiperenlaces.

Inicialmente la web era un mundo de páginas estáticas y enlaces pero pronto la generación de páginas dinámicas y en general el uso de la web como soporte para el diseño de aplicaciones basadas en web lo complicó todo.

spiral La llegada de las aplicaciones web

Durante años ha existido un esfuerzo de adaptar el paradigma de páginas y navegación entre páginas al desarrollo de aplicaciones, aplicaciones en las que el concepto de página, como documento estático idéntico para todo el mundo tal y como lo concibió Berners no existe. Diferentes paradigmas de desarrollo de aplicaciones web se han ido sucediendo:

  • Model 1: la traslación directa del modelo original de páginas e hiperenlaces en donde las páginas son generada dinámicamente.
  • Model 2 o MVC: la navegación entre páginas generadas ya no es directa sino que es intermediada por un controlador que decide cual es la siguiente página dependiendo de las operaciones que se hayan realizado en el proceso de transición.
  • MVC basado en componentes (¿Model 3?): es la sofisticación del Model 2 en donde se simula la forma de trabajar en el escritorio, basado en componentes y eventos, de tal manera que una acción del usuario supone la regeneración de la página cambiando parcialmente una parte de la misma de acuerdo con la acción. La página y la transición entre páginas ahora es gestionada por componentes que saben qué cambios han de realizarse en la regeneración de la página de acuerdo al evento, simulando un comportamiento similar a los sistemas de componentes GUI de la programación de escritorio.

En años recientes se ha ido introduciendo la técnica AJAX, dicha técnica con la ayuda de JavaScript permite el cambio parcial de la página obteniendo nuevos datos del servidor sin llegar recargarse ésta. Aunque la práctica del cambio parcial de una página web es muy anterior a la introducción del componente XMLHttpRequest en Internet Explorer (base de la programación AJAX), ha sido el uso de este componente el que ha favorecido un uso masivo de la misma.

Hoy millones de sitios web y aplicaciones web usan AJAX para proporcionar una mejor experiencia al usuario gracias a una mayor inmediatez y transparencia evitando parcialmente las molestas recargas de páginas.

Sin embargo a pesar del uso masivo de AJAX podemos decir que hoy día la web sigue un modelo que podríamos calificar de "Model 2 (MVC) enriquecido con AJAX", en donde el llamado aquí Model 3 tiene cada vez menos sentido, pues la introducción de AJAX hace en gran parte innecesaria la gestión de páginas basada en componentes. Como habitualmente el uso de AJAX tiende a estar ligado a componentes (no necesariamente presentes en el Model 2) podríamos resumir que el estado del arte actual viene a ser un Model 3.5, en donde la navegación de páginas se consigue evitar parcialmente en el caso de transiciones de estado menores, las cuales se realizan utilizando AJAX y JavaScript.

spiral ¿Qué inconvenientes tiene la navegación y el desarrollo basado en páginas?

Todo programador web sabe lo problemática que es la navegación por páginas en una aplicación web, aparte del derroche de ancho de banda y de tiempo de proceso en regenerar la página completa están los problemas con el cacheado no deseado, el back-forward, los inconvenientes del "form auto fill" habitual en los navegadores etc. No es raro ver aplicaciones web que ocultan los menues y botones del navegador o que usan frames o iframes (por ejemplo en bancos) para evitar la problemática de los botones Atrás/Adelante (Back/Forward).

La programación basada en páginas tiende a forzar una forma de programar extraña, repetitiva (plagada de includes) e ineficiente (tanto en ancho de banda como en potencia de cálculo) que no existe en el ámbito del escritorio en donde no existe esa imposición.

spiral ¿Qué es lo que impide un uso intensivo de AJAX?

En el ámbito del desarrollo web se suelen distinguir dos tipos de soluciones: aplicaciones web y sitios web.

En el primer caso AJAX tiende a utilizarse cada vez más de forma intensiva debido a que este tipo de aplicaciones no tiene algunos de los requisitos de los sitios web, es en los sitios web en donde un uso intensivo de AJAX puede suponer un problema.

En los sitios web el usuario está acostumbrado al concepto de página, ligados a las páginas existen algunos requisitos básicos de cualquier sitio web tal y como:

  1. Memorización de páginas favoritas (bookmarking): cada página web tiene un único URL, dicho URL es por tanto "memorizable" como favorito. Como AJAX tiende a cambiar parcialmente las páginas se pierde la posibilidad de guardar favoritos.
  2. Search Engine Optimization (SEO): la compatibilidad SEO es un deber de cualquier sitio web, cualquiera puede entender esto. Los actuales robots indexadores de páginas ven la web como Web 1.0, es decir, el código JavaScript es totalmente ignorado tal que cualquier cambio parcial de página hecho via AJAX cargando datos del servidor no es conocido por los robots indexadores que atraviesan el sitio web porque dicha acción no se realiza.
  3. Servicios basados en visitas de páginas: por ejemplo anuncios y monitorización de visitas tal y como Google Analytics están basados en el número de veces que una página ha sido cargada. Por tanto los cambios parciales de páginas hechos por AJAX no cuentan.
  4. Necesidad ocasional de ventanas emergentes (pop-ups)

Estos requisitos hacen que el uso intensivo de AJAX esté desaconsejado en sitios web de gran público. Sin embargo la diferencia entre aplicación web y sitio web es cada vez más sutil, de hecho cualquier sitio web es hoy día una aplicación web.

spiral ¿Debemos renunciar a sitios web intensivos en AJAX?

NO.

Hay soluciones técnicas a los requisitos anteriormente mencionados.

spiral ¿Es posible el desarrollo de sitios web basados en una Única Página Web (SPI)?

¡SI!

Es el momento de realizar esta transición en las que todos, programadores y usuarios saldremos ganando. Tenemos la tecnología y los navegadores ya están a la altura para conseguir este objetivo.

Para ello es preciso compatibilizar el funcionamiento de la técnica Single Page Interface (SPI) con los requisitos mencionados anteriormente de cualquier sitio web.

spiral Adiós a las páginas bienvenidos los estados

Si en una aplicación web sin JavaScript la sucesión de estados equivale al de páginas, en una aplicación SPI cualquier cambio parcial de la página supone un estado (o estado de "la página"). Entre los estados hay que distinguir dos categorías de estados:

  • Fundamentales
  • Secundarios

La diferenciación entre ambos tipos de estados es importante, porque los estados fundamentales serán páginas web cuando sea necesario, serán aquellos estados que merezca la pena que sean vistos también como páginas web. La distinción entre estados fundamentales y secundarios dependerá de cada sitio web.

Para entender ambos tipos de estados es conveniente considerar un ejemplo real: la validación de un usuario a través de login y password.

En una aplicación clásica existirían dos páginas, la propia del login la cual se recargará cuando el login es incorrecto mostrando además algún mensaje de error, y la página de entrada correcta mostrando al usuario las posibles opciones.

En una web SPI tanto el estado donde se muestra el login inicial como el estado de entrada correcta mostrando las opciones podrían considerarse los estados fundamentales, los estados en donde se muestran los mensajes de error de login mostrando de nuevo el formulario del login podrían considerarse estados secundarios.

En el caso de un sitio web basado en páginas que se quiere convertir en una web SPI, los estados fundamentales normalmente serán los equivalentes a las páginas y los secundarios cuando a partir de un estado fundamental (la antigua "página") se producen cambios menores que no merecen la pena (por ejemplo) ser memorizados como favoritos o ser procesados por un crawler.

spiral Single Page Interface y Bookmarking

Diferentes páginas tienen diferentes URLs, si se sigue la ruta SPI ¿cómo cambiar el estado y la vez la URL para poder ser guardada como favorita sin recargar la página?.

Hay un truco, y es a través de la referencia del URL ("hash fragment", shebang o hashbang), la parte final del URL tras el carácter #, que sirve para situarse en un punto concreto de la página (a través de un <a name="ref"></a>). Un cambio en esa parte del URL (si existe) no provoca la recarga de la página, por lo que al mismo tiempo que cambiamos de estado fundamental de la página podemos cambiar la referencia del URL a través del objeto JavaScript window.location sin provocar una recarga. Como el URL cambia al mismo tiempo que el estado fundamental, el usuario puede memorizar en cualquier momento dicho URL como "favorito" en su navegador.

Cuando dicho usuario quiere volver en otro momento al estado memorizado como favorito directamente, el estado objetivo está presente en la referencia del URL, se producirá una solicitud al servidor, sin embargo dicha referencia por desgracia no es enviada al servidor porque se considera que no forma parte del URL desde el punto de vista de las comunicaciones HTTP, por ello es preciso un proceso post-carga.

El servidor devolverá una página inicial en el que no ha considerado el estado requerido sin embargo el objeto window.location contiene la URL completa de la página cargada incluyendo la referencia. Si nada más cargar la página se detecta la presencia de una referencia de estado, vía JavaScript y window.location es posible reescribir la URL y parametrizarla de forma normal para que vuelva a hacerse una nueva request al servidor para que sirva la página directamente en el estado requerido.

Otra opción, mejor que el uso de hashbangs, surge con la llegada de HTML 5, la HTML 5 History API.

spiral Single Page Interface y Search Engine Optimización (SEO)

La forma más sencilla de conseguir que nuestro sitio web sea procesable por los motores de búsqueda es ofrecer dos modos de navegación diferentes, a los usuarios de la web como SPI, y a los robots indexadores como páginas.

El siguiente ejemplo de enlace muestra esta idea:

<a href="URL página" onclick="return false">…</a>

Este enlace no hará nada en un navegador con JavaScript activado porque la navegación está desactivada a través del "return false" del atributo onclick y sin embargo un robot indexador ignorará el atributo onclick pues el código JavaScript es ignorado, y considerará el URL especificado como una página a procesar.

En el ámbito de una aplicación SPI, los URLs usados para navegación de estados/páginas deberán contener el estado destino, el mismo tipo de URL que usamos en bookmarks (utilizando una referencia para indicar el estado) o directamente indicando el estado como un parámetro, esta última opción es la preferida pues evita una solicitud al servidor, por supuesto siempre es posible utilizar "pretty URLs" para este fin.

Actualmente Google ya procesa "AJAX URLs", es decir, URLs conteniendo el estado objetivo en la referencia de la URL siguiendo #! como se especifica en Making AJAX Applications Crawlable, en este caso el sitio web/aplicación debe devolver la página solicitada en este caso a través de un parámetro _escaped_fragment_.

Al mismo tiempo el framework SPI puede añadir código específico al onclick antes del return false o asociar un "event listener" al enlace registrándolo a través de addEventListener o attachEvent dependiendo del navegador, dicho event listener podrá estar vinculada a una acción que se comunique con el servidor via AJAX para efectuar el cambio de estado. Cuando se pulse el enlace dicho cambio de estado no será una carga de una nueva página pues el atributo onclick="... return false" impide el comportamiento por defecto del enlace.

La técnica descrita es la más sencilla e inmediata a través de enlaces visibles compatibles con robots y con SPI, siempre es posible separar ambas funcionalidades utilizando enlaces ocultos para el usuario pero visibles para los robots junto con otro tipo de elementos "pulsables" para efectuar las transiciones de estado SPI a través de JavaScript, los cuales serán invisibles para los robots.

Es fundamental que el framework web servidor tenga la capacidad de generar la página web en el estado requerido como HTML en tiempo de carga, pues lo normal es que la transición de estados tras la carga se realice a través de JavaScript con cambios parciales de página. Esta dualidad entre renderización parcial de estados via JavaScript y como HTML en carga directa de estado son requisitos imprescindibles para conseguir un sitio web SPI y a la vez capaz de simular páginas.

spiral SPI y los botones Atrás/Adelante

Los botones Atrás/Adelante son una fuente de problemas en sitios web basados en páginas y deberían ser evitados lo más posible. A pesar de que los usuarios finales están acostumbrados a evitar los botones Atrás/Adelante cuando están enviando un formulario de datos (porque conlleva el riesgo de comprar dos veces el mismo producto), el uso de los botones Atrás/Adelante es enormemente popular.

Aparentemente el paradigma SPI rompe la tradicional forma de navegar en un sitio web, porque en teoría los botones Atrás/Adelante no tienen sentido en SPI (no hay páginas) y los navegadores web no proporcionan un buen control de estos botones.

Esto no es totalmente cierto, el comportamiento de los botones Atrás/Adelante puede ser simulado, en vez de navegación por páginas, Atrás/Adelante (y la navegación en general por la historial del navegador) puede ser usado para cambiar el estado actual al previo/siguiente estado. En este caso un código JavaScript puede detectar cuando la parte "referencia" de la URL cambia y solicita a la aplicación que cambie el estado al especificado en la URL. Debido a que el navegador no cambia la página, tu aplicación es ahora totalmente responsable del comportamiento del Atrás/Adelante evitando los típicos problemas del uso de Atrás/Adelante cuando se envía un formulario de datos, ahora en SPI no hay tal formulario y no hay navegación por páginas no controlada por la aplicación/sitio web.

spiral SPI y los servicios basados en visitas a páginas

Los servicios de anuncios o los contadores de visitas a páginas están basados en cargas de páginas. En ambos casos es posible usar elementos ocultos <iframe> conteniendo una página web con los scripts requeridos por dichos servicios.

En el caso de los servicios de anuncios tal y como Google AdSense la inserción dinámica del <iframe> supondrá la carga de los anuncios por lo que cada cambio de estado puede suponer una nueva carga o inserción dinámica del <iframe>. Google AdSense parece detectar cuando el script de AdSense es ejecutado dentro de un <iframe> y tiene en cuenta el contenido del la página contenedora. Puede ser conveniente añadir algún tipo de parámetro que identifique el estado fundamental que está cargando el <iframe>.

En el caso de los scripts de visitas, podemos utilizarlos como monitorización de visitas a estados fundamentales de nuestra sitio web SPI. En este caso el <iframe> oculto contendrá una página web normal que simplemente contiene los scripts de control de visitas, a través de un parámetro podremos indicar al script qué estado fundamental estamos visitando. Dicho <iframe> es conveniente que sea un elemento global que es introducido en la página una sola vez. Cuando un estado fundamental es cargado a través de una URL, el <iframe> de control de visitas convendrá que tenga como parámetro la información del estado siendo cargado. Tras la carga inicial cualquier cambio de estado podremos notificarlo cambiando la URL via JavaScript de acuerdo con el nuevo estado, dicho cambio provocará una recarga del <iframe> de visitas memorizando dicha visita al estado.

spiral SPI y las ventanas pop-up

La creación de una nueva ventana supone claramente una ruptura con el modelo SPI, pero no hay que ser fundamentalista, si el estado de dicha ventana no interfiere en el estado de la página que la creó, nada hay de malo en el uso de ventanas pop-up como páginas normales.

El problema surge cuando las acciones realizadas en una página "pop-up" influyen en la página padre, ya sea dicha página/ventana modal o no modal, la coordinación entre páginas es complicada. Por ejemplo no hay un estándar web para gestionar páginas web modales respecto a otra página, pues el concepto de página tradicionalmente ha sido siempre el de un elemento autónomo y por tanto su ciclo de vida es difícilmente coordinable desde otra página.

Este problema desde hace tiempo tiene solución en SPI y consiste en la simulación de ventanas modales o no modales dentro de la misma página web sin necesidad de crear nuevas páginas. En el caso de las ventanas no modales cualquier elemento HTML con posicionamiento absoluto pasa a ser una "ventana no modal" y la modalidad se consigue a través del adecuado uso del posicionamiento absoluto, el control del z-index y la opacidad respecto a las capas ("layers") inferiores. Estas soluciones son las deseadas en un ambiente SPI.

Con un poco de esfuerzo, incluso el estado en el que se muestra una ventana modal puede ser un estado fundamental y por tanto procesable por los buscadores de páginas.

spiral Un cambio cultural del programador web

La mayoría de los programadores (y frameworks web) piensan en una web basada en páginas, la eliminación de las páginas supone un cambio radical en el modo de hacer sitios y aplicaciones web. Este cambio ya no es tan radical gracias a que la popularidad de AJAX hemos reducido el número de páginas de nuestros sitios web y en resumen nos ha acercado poco a poco a este "nuevo" modelo de programación SPI.

En la nueva web SPI desparece el tag <form> y en general la necesidad de la sesión usada como coordinadora de datos entre secuencias de páginas, debido a que el protagonista pasa a ser únicamente la página cliente con algún tipo de simetría en el servidor (la página en el servidor). De hecho, la eliminación de la necesidad de coordinar páginas a través de la sesión elimina otra fuente de problemas tal y como es la práctica de algunos usuarios de abrir varias ventanas con la misma página en aplicaciones web que suelen corromper la sesión y la aplicación en general.

La forma de programar SPI es basada en eventos de forma totalmente similar a como se hace en el escritorio en donde la gran mayoría de las aplicaciones suelen ejecutarse dentro de la misma ventana principal y cuando existen ventanas hija, éstas son plenamente controladas por la ventana principal y verdaderamente modales.

Siguiendo la evolución de paradigmas de desarrollo web, podríamos denominar Model 4 a esta "nueva" forma de construir sitios web.

spiral Un cambio cultural del usuario?

No mucho, a través del soporte de favoritos y la simulación del funcionamiento de los botones Atrás/Adelante, los usuarios finales apenas van a apreciar la diferencia entre un sitio web SPI y el mismo basado en páginas, es más lo que percibirán es que el sitio SPI responde con mucha más prontitud y se eliminan los típicos parpadeos y el "scroll" de cambio de página.

spiral Viabilidad técnica hoy

Este manifiesto no es una declaración de intenciones sino la expresión de la voluntad de promover una "nueva" forma de construir sitios web que es ya real. Las consideraciones técnicas anteriores han tenido siempre el framework web Java ItsNat como base tecnológica en el desarrollo de sitios web SPI. A pesar de que ItsNat fue concebido desde el primer día pensando en este tipo de aplicaciones, las técnicas anteriormente mencionadas pueden ser desarrolladas en otros framework web, o bien dichos frameworks podrían evolucionar hacia la posibilidad de realización de este tipo de sitios web SPI con requerimientos de simulación de páginas.

Algunas características deseables de los sitios web SPI para que puedan ser substitutivos de los sitios webs tradicionales basados en páginas, tal y como la simulación de páginas a través de estados fundamentales en carga, sólo son posibles en frameworks web céntricos en el servidor, en donde la renderización HTML se realiza en el servidor en tiempo de carga. Es la posibilidad de renderización de estados fundamentales como HTML en tiempo de carga y a la vez por inserción parcial a través de JavaScript, las características clave de un framework apto para la realización de sitios web SPI. Los frameworks céntricos en el cliente pueden tener un papel muy relevante para la realización de los llamados estados secundarios en este documento.

spiral Ejemplo real

La web Innowhere.com/jnieasy realizada con ItsNat en el servidor es un buen ejemplo de sitio web SPI porque resume las características exigidas a una web SPI, de acuerdo con este documento, para poder ser substituta de forma satisfactoria de una web tradicional. De hecho la nueva versión SPI reemplaza sin cambiar significativamente estética y funcionalidad, la versión anterior basada en páginas.

Características:

  • Single Page Interface: los botones Atrás y adelante son simulados cambiando al estado visitado previo o siguiente.
  • Los estados fundamentales pueden ser memorizados como Favoritos (bookmarks)
  • SEO compatible: los estados fundamentales son accesibles por navegación por páginas si desactiváramos JavaScript en el navegador, incluso una ventana modal
  • Compatible con el sistema de "AJAX URLs" de Google usando el formato #!, la página puede ser también solicitada usando el parámetro _escaped_fragment_ de acuerdo con la convención de Google. Por ejemplo este estado es procesado por Google solicitando este URL.
  • Funciona con JavaScript desactivado.
  • Muestra un banner con publicidad de Google AdSense
  • A pesar de ser SPI, la navegación por los estados fundamentales es monitorizado por Google Analytics a través de un <iframe> oculto cuyo URL cambia indicando el estado visitado
  • Usa simulada ventana modal evita crear una nueva página, esta ventana también es accesible directamente a través de un URL y por tanto el contenido es SEO compatible.

spiral El Manifiesto en otras lenguas

Inglés

Ucraniano gracias a Mario Pozner

Ruso gracias a Andrey Geonya, puede estar ligeramente desactualizado porque este manifiesto está "vivo".

Serbo-Croatian thanks to Jovana Milutinovich

spiral Enlaces al manifiesto

Noticia en JavaHispano.org

Noticia en DZone

Noticia en TheServerSide.com

Discusión en YCombinator.com

Autor del manifiesto: Jose María Arranz Santamaría