2011-02-24 9 views
7

Estoy construyendo un sitio web móvil que utiliza la biblioteca jquery principal y algunos js propios. Nuestro sitio web es demasiado grande y tiene demasiados datos como para ser una simple aplicación web en línea o fuera de línea. Necesitamos conectividad web.¿Cómo almacena en caché javascript en iphone Safari usando html5 localStorage?

Estoy tratando de mejorar el rendimiento de almacenamiento en caché para el almacenamiento en caché de una gran cantidad de Javascript para un sitio móvil. Es bien sabido que el almacenamiento en caché en el safari del iPhone está limitado a archivos de 15-25 kb de tamaño, y nuestro js minificado es de alrededor de 125 kb.

He pensado en usar el manifiesto de caché, pero esto tiene la desventaja de que el navegador solicita el caché-manifiesto con cada carga de página, y como no estamos usando una sola aplicación web, esto agrega solicitudes adicionales a el servidor.

¿Podemos almacenar en caché el javascript en localStorage (disponible en el safari móvil y en el navegador de Android) y luego ejecutarlo desde allí?

+0

Sólo puede guardar cadenas en 'localStorage', y' eval() 'ing no es una buena práctica. De todos modos, podrías intentar crear un archivo JavaScript diseñado para iPhone para reducirlo. (jQuery es menos de 125 kb minificado, así que supongo que debe ser posible) – pimvdb

+0

Sé que eval no es una buena práctica, pero el aumento de rendimiento que brinda esta técnica es sustancial. La mayoría de los js simplemente no están guardados en la caché de un safari móvil porque es demasiado grande. – Sean

+0

"Es bien sabido que el almacenamiento en caché en el safari del iPhone está limitado a archivos de 15-25kb de tamaño" - [tal vez no más] (http://www.yuiblog.com/blog/2010/06/28/mobile) -browser-cache-limits /) –

Respuesta

18

Sí, puedes. (Lo siento por responder a mi propia pregunta, pensé que esta era una solución interesante)

Encontré un esquema de un ejemplo de código aquí en la diapositiva # 12.

http://www.slideshare.net/jedisct1/abusing-javascript-to-speedup-mobile-web-sites

He implementado esto en http://m.bbref.com/ (todavía en fase beta)

Tienes que usar el control de versiones de la url script para limpiar la caché cuando se crea una nueva versión, pero esto funciona para las páginas con localStorage y también funcionará cuando localStorage no esté disponible. He agregado un código de depuración al pie de página para mostrar de dónde se carga el js.

He dividido esto en una secuencia de comandos para el encabezado y uno del pie de página. Estos aparecen en línea.

En la cabecera (lo he puesto aquí como usamos Modernizr añadir algunas clases a la etiqueta html y quiero que los que estaban allí lo más rápido posible para fines de representación. Podían trasladar a pie de página.

<script type="text/javascript"> 
// .001 is the current js version 
// this script assumes it is in the root web directory. 
var js_file = "site_lib.001.js"; 
// vars to store where the file is loaded from. 
var _mob_load_js = false; 
var _mob_ajax_load_js = false; 
{ 
    // if we have localStorage and the files exists there get it. 
    if(window.localStorage && window.localStorage[js_file]) { 
      // eval the js file. 
      try{ 
       window.eval(window.localStorage[js_file]); 

       // successfully eval'ed the code, so 
       // we don't need to download it later. 
      _mob_load_js = true; 
      } catch (e) { _mob_load_js = false; } 
    } 
    else if (window.localStorage) { 
     // We have localStorage, but no cached file, so we 
     // load the file via ajax, eval it and then store 
     // the file in localStorage 

     // To remove previous versions, I remove all of our localStorage, 
     // This is extreme if we store other vars there. 
     window.localStorage.clear(); 
     // standard ajax request. 
     var xhr = new XMLHttpRequest(); 
     xhr.onreadystatechange = function() { 
     if (xhr.readyState == 4) { 
      // eval the js 
      try { 
       window.eval(xhr.responseText); 
       // successfully eval'ed the code, so 
       // we don't need to download it later. 
      _mob_ajax_load_js = true; 
      } catch (e) { _mob_ajax_load_js = false; } 

     try { 
       // store the js. 
      window.localStorage[js_file] = xhr.responseText; 
     } catch (e) {} 
     } 
     else { 
     return; 
     } 
    }; 
    xhr.open("GET",js_file,true); 
    xhr.send(); 
    } 
}; 
</script> 

y en el pie de página (por razones de rendimiento). pongo el método de carga estándar. tenga en cuenta que los navegadores que utilizan esta rama toda caché propiamente siempre y cuando tenga expira cabeceras establecidos.

<div id="sr_external_script"></div> 
<script type="text/javascript"> 
// We haven't loaded the js yet, so we create a script 
// tag and get the script the old fashioned way 
if (!_mob_load_js && !_mob_ajax_load_js) { 
    var script=document.createElement("script"); 
    script.type="text/javascript"; 
    script.src=js_file; 
    document.getElementById("sr_external_script").appendChild(script); 
    // add a note to the footer 
    document.write('<div>loaded from server and not stored</div>'); 
} 
else if (!_mob_load_js) { 
    // add a note to the footer 
    document.write('<div>loaded via ajax and stored in localStorage</div>'); 
} 
else { 
    // add a note to the footer 
    document.write('<div>loaded from localStorage</div>'); 
} 
</script> 

he confirmado en Chrome y safari que el js se carga desde localStorage y el la funcionalidad del sitio funciona como se esperaba y no se realiza ninguna solicitud al servidor. Y he confirmado que cuando se ejecuta en IE o Firefox carga el script como se encuentra en el pie de página.

Nota: Agregué código para ajustar las evaluaciones en la captura de intentos, ya que tenía un problema en Firefox.

+4

No hay necesidad de disculparse por responder su propia pregunta. La faq específicamente permite esto siempre y cuando la pregunta se formule correctamente como una pregunta. – user113716

2

Además, también me encontré con este gestor de comandos llamado basket.js, podría hacer exactamente lo que está buscando.

+0

Gracias, voy a ver eso. Optimizaría mucho el código anterior. – Sean

0

Tuve una pregunta similar y también creé una pequeña biblioteca para eso. Puede encontrarlo en https://github.com/webpgr/cached-webpgr.js

Lo he creado porque basket.js tiene cierta dependencia y proporciona mucha más funcionalidad que la que necesito. Puedes consultar mi código en Github, estoy seguro de que podrás comprenderlo todo bastante rápido. Pero si solo quieres continuar y usarlo aquí hay un ejemplo completo de cómo usarlo.

La biblioteca completa:

function _cacheScript(c,d,e){var a=new XMLHttpRequest;a.onreadystatechange=function(){4==a.readyState&&(200==a.status?localStorage.setItem(c,JSON.stringify({content:a.responseText,version:d})):console.warn("error loading "+e))};a.open("GET",e,!0);a.send()}function _loadScript(c,d,e,a){var b=document.createElement("script");b.readyState?b.onreadystatechange=function(){if("loaded"==b.readyState||"complete"==b.readyState)b.onreadystatechange=null,_cacheScript(d,e,c),a&&a()}:b.onload=function(){_cacheScript(d,e,c);a&&a()};b.setAttribute("src",c);document.getElementsByTagName("head")[0].appendChild(b)}function _injectScript(c,d,e,a){var b=document.createElement("script");b.type="text/javascript";c=JSON.parse(c);var f=document.createTextNode(c.content);b.appendChild(f);document.getElementsByTagName("head")[0].appendChild(b);c.version!=e&&localStorage.removeItem(d);a&&a()}function requireScript(c,d,e,a){var b=localStorage.getItem(c);null==b?_loadScript(e,c,d,a):_injectScript(b,c,d,a)}; 

Llamada la biblioteca

requireScript('jquery', '1.11.2', 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function(){ 
    requireScript('examplejs', '0.0.3', 'example.js'); 
}); 
Cuestiones relacionadas