Banner

Ultima revisión 20/12/2014

Mejorar la navegacion a través del almacenamiento local (localStorage y sessionStorage)

Hoy os voy a hablar de una de las cosas más interesantes que yo veo de HTML5 y que, no es ni más ni menos que, el almacenamiento local en el navegador. Esta característica de HTML5 no tiene nada que ver con el concepto de Cookie aunque, se puede confundir con cierta facilidad. Por ello, lo primero que debemos aclarar es cómo definimos los conceptos de LocalStorage, SessionStorage y en qué se diferencian a las Cookies.

Tipos de almacenamiento Web

Bien, existen 3 tipos de almacenamiento Web hasta el momento que son localStorage, sessionStorage y Cookies. Como algunos ya sabréis, las Cookies se caracterizan porque tienen una limitación de espacio de 4KB, pueden ser activadas o desactivadas por los usuarios, tienen caducidad y aumentan el peso de las peticiones ya que, toda la información contenida en ellas, se envía al servidor para ser analizada y, seguidamente, traer de vuelta al navegador cliente.

LocalStorage

LocalStorage, como su propio nombre indica, es únicamente un almacenamiento local. Lo que sucede es que, este espacio de memoria reservado, es persistente entre las diferentes pestañas incluso si se cierra el navegador. Es por ello que hay que tener cuidado con la información que guarda en ella. El cómo podemos utilizar JavaScript para guardar información en los navegadores de los usuarios viene definido en las especificaciones de la W3C y en la WHATWG, aunque, en este artículo, vamos a dar algunas bases para ello.

LocalStorage posee una capacidad de entre 2.5MB y 5.0MB dependiendo del navegador, no tiene caducidad alguna, es compatible en casi todos los navegadores y no aumenta el peso de cada petición ya que, toda la información contenida en ella, es únicamente "visible" desde del entorno local. Fuera del entorno local es como si no existiese. La compatibilidad de localStorage con los navegadores se expone a continuación:

Chrome Firefox (Gecko) IE Opera Safari (Webkit)
4+ 3.5+ 8+ 10.50+ 4

Uso de localStorage

LocalStorage tiene 3 métodos que son para establecer, recuperar y eliminar las variables almacenadas en este espacio de memoria:

/* Establecer un nuevo valor */
localStorage.setItem('variable', 'valor');

/* Recuperar el valor de una variable */
var var1 = localStorage.getItem('variable');

/* Eliminar variable de localStorage */
localStorage.removeItem('variable');

SessionStorage

SessionStorage es exáctamente igual a localStorage en prácticamente todo con la salvedad de que no tiene un almacenamiento persistente, es decir, que en cuanto cerremos el navegador, automáticamente se eliminará. La compatibilidad de sessionStaorage con los diferentes navegadores cambia en función de la versión:

Chrome Firefox (Gecko) IE Opera Safari (Webkit)
5+ 2+ 8+ 10.50+ 4

Uso de SessionStorage

SessionStorage tiene 3 métodos que son para establecer, recuperar y eliminar las variables almacenadas en este espacio de memoria:

/* Establecer un nuevo valor */
sessionStorage.setItem('variable', 'valor');

/* Recuperar el valor de una variable */
var var1 = sessionStorage.getItem('variable');

/* Eliminar variable de localStorage */
sessionStorage.removeItem('variable');

Mejorar la navegación a través del WebStorage

Llegados a este punto ahora viene la gran pregunta, que seguro os hacéis, de cómo mejorar la navegación entre páginas...

Básicamente se trata de utilizar esta característica de HTML5 para evitar llamadas innecesarias de Ajax guardando la información más utilizada en localStorage y, así, ahorrar tiempos de carga innecesarios. Veámoslo con el siguiente ejemplo:

// Primero definimos una función que insertará en la sección HEAD el contenido CSS y JS del localStorage
function insertToHead(url){
    var CSS = localStorage.getItem('CSS');
    var JS  = localStorage.getItem('JS');

    var head = document.getElementsByTagName("head")[0];

    // Insertamos los estilos CSS
    var style = document.createElement('style');
    style.type = 'text/css';
    if (style.styleSheet){
        style.styleSheet.cssText = CSS;
    } else {
        style.appendChild(document.createTextNode(CSS));
    }
    head.appendChild(style);

    // Insertamos el Javascript
    var newScript = document.createElement('script');
    newScript.type = 'text/javascript';
    newScript.textContent = JS
    head.appendChild(newScript);
}

// Función para recuperar los parámetros desde la URL.
function gup(param){
    param = param.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
    var regexS = "[\\?&]"+param+"=([^&#]*)";
    var regex = new RegExp( regexS );
    var results = regex.exec( window.location.href );
    if( results == null )
        return null;
    else
        return results[1];
}

// Ahora hay que saber si el navegador admite el uso de localStorage
if (window.localStorage) {
    // Si es así, preguntamos si la variable CSS de localStorage es NULL.
    // Si es NULL o recibimos el parámetro clear=true desde la URL, entonces cargamos desde fichero.
    if(localStorage.getItem('CSS') == null || gup('clear') == 'true'){
        // Petición POST del CSS
        $.post( "css/styles.css", function( css_data ) {
            CSS = css_data;

            // Petición POST del JS
            $.post( "js/functions.js", function( js_data ) {
                JS = js_data;
                localStorage.setItem('CSS', CSS);
                localStorage.setItem('JS', JS);

                // Insertamos el contenido de los archivos en la página
                insertToHead();
            });
        });
    } else {
        // Si no es NULL, entoces, actualizamos nuestras variables y evitamos las llamadas Ajax.

        // Insertamos el contenido de los archivos en la página
        insertToHead();
    }

} else {
    // Si no admite el uso de localStorage cargamos los archivos en cada petición.

    //Este mensaje se puede omitir o eliminar
    console.log('Este navegador no soporta el uso de LocalStorage');

    // Insertamos el CSS
    var fileref=document.createElement("link");
    fileref.setAttribute("rel", "stylesheet");
    fileref.setAttribute("type", "text/css");
    fileref.setAttribute("href", 'css/styles.css');
    document.getElementsByTagName("head")[0].appendChild(fileref);

    // Insertamos el Javascript
    var fileref=document.createElement('script');
    fileref.setAttribute("type","text/javascript");
    fileref.setAttribute("src", 'js/functions.js');
    document.getElementsByTagName("head")[0].appendChild(fileref);
}

Con esta metodología podemos ahorrar entre 300ms y 1000ms en el proceso de carga dependiendo del navegador ya que, a efectos de velocidad, el localStorage se comporta como una caché.

Observaciones a tener en cuenta

Esta solución no es óptima si se desea trabajar bajo las especificaciones SEO aunque es muy práctica si se desea trabajar con plantillas, webs de uso interno o web accesibles.

Al utilizar localStorage, una vez guardada la información en ella, ya no se borrará nunca a no ser que nosotros la borremos a conciencia a través de Javascript. Es por ello que si cambiamos algo del CSS o del JS y no indicamos que se vuelva a cargar, los cambios realizados no se verán aplicados. Para evitar este comportamiento, se ha introducido el parámetro clear=true, que forzará la actualización de localStorage y, así, conseguiremos ver aplicados todos los cambios que realicemos en los ficheros.

También podéis probar a cambiar localStorage por sessionStorage y todo seguirá funcionando correctamente aunque, eso si, sin almacenado persisente.