2012-04-20 39 views
48

Mis amigos y yo estamos trabajando en un sitio web en el que nos gustaría almacenar en caché ciertas imágenes para poder mostrarlas más rápido en el futuro. Tengo dos preguntas principales:Cómo almacenar en caché una imagen en Javascript

  1. ¿Cómo se almacena una imagen en caché?
  2. ¿Cómo se usa una imagen una vez que se ha almacenado? (Y sólo para verificar, si una imagen se almacena en caché en la página A, es posible llamarlo desde la memoria caché para usarlo en la página B, ¿verdad?)

Además, es posible establecer cuando la versión en caché de la imagen caducará?

Se agradecería mucho que se incluyera un ejemplo y/o un enlace a una página que describa esto más detalladamente.

Estamos bien usando Javascript sin procesar o la versión jQuery.

+10

usted no lo hace. El navegador lo hace. – Pointy

+0

¿el caché del navegador genera imágenes automáticamente? –

+6

@Logan: Sí, el navegador guarda en caché las imágenes automáticamente, siempre que el servidor envíe los encabezados necesarios para indicarle al navegador que es seguro almacenarlo en caché. (Estos encabezados también le pueden indicar al navegador el tiempo de caducidad, que es parte de su pregunta.) – icktoofay

Respuesta

92

Una vez que una imagen se ha cargado de alguna manera en el navegador, estará en la memoria caché del navegador y se cargará mucho más rápido la próxima vez que se use ya sea en la página actual o en cualquier otra página tan larga como la imagen se utiliza antes de que caduque desde la memoria caché del navegador.

Por lo tanto, para precachear imágenes, todo lo que tiene que hacer es cargarlas en el navegador. Si desea precachear un grupo de imágenes, probablemente sea mejor hacerlo con javascript, ya que generalmente no retendrá la carga de la página cuando se hace desde JavaScript. Puede hacerlo de esta manera:

function preloadImages(array) { 
    if (!preloadImages.list) { 
     preloadImages.list = []; 
    } 
    var list = preloadImages.list; 
    for (var i = 0; i < array.length; i++) { 
     var img = new Image(); 
     img.onload = function() { 
      var index = list.indexOf(this); 
      if (index !== -1) { 
       // remove image from the array once it's loaded 
       // for memory consumption reasons 
       list.splice(index, 1); 
      } 
     } 
     list.push(img); 
     img.src = array[i]; 
    } 
} 

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"]); 

Esta función se puede llamar tantas veces como desee y cada vez, se acaba de añadir más imágenes a la precache.

Una vez que las imágenes se han precargado de esta forma mediante javascript, el navegador las tendrá en su caché y podrá consultar las URL normales en otros lugares (en sus páginas web) y el navegador buscará esa URL desde su caché en lugar de a través de la red.

Finalmente, con el tiempo, la memoria caché del navegador puede llenarse y arrojar las cosas más antiguas que no se han utilizado en un momento. Por lo tanto, con el tiempo, las imágenes se eliminarán de la memoria caché, pero deben permanecer allí por un tiempo (dependiendo de qué tan grande es la caché y cuánto se hace otra exploración). Cada vez que las imágenes se precargan de nuevo o se usan en una página web, se actualiza automáticamente su posición en el caché del navegador, por lo que es menos probable que se eliminen del caché.

El caché del navegador tiene una página cruzada, por lo que funciona para cualquier página cargada en el navegador. Por lo tanto, puede precachear en un lugar en su sitio y la memoria caché del navegador funcionará para todas las demás páginas de su sitio.


Cuando precaching que el anterior, las imágenes se cargan de forma asíncrona para que no se bloquee la carga o la visualización de la página. Pero, si su página tiene muchas imágenes propias, estas imágenes precacheadas pueden competir por el ancho de banda o las conexiones con las imágenes que se muestran en su página. Normalmente, esto no es un problema notable, pero en una conexión lenta, este precaching podría ralentizar la carga de la página principal. Si fue correcto cargar las imágenes de precarga al último, podría usar una versión de la función que esperaría para iniciar la precarga hasta que todos los demás recursos de la página ya estuvieran cargados.

function preloadImages(array, waitForOtherResources, timeout) { 
    var loaded = false, list = preloadImages.list, imgs = array.slice(0), t = timeout || 15*1000, timer; 
    if (!preloadImages.list) { 
     preloadImages.list = []; 
    } 
    if (!waitForOtherResources || document.readyState === 'complete') { 
     loadNow(); 
    } else { 
     window.addEventListener("load", function() { 
      clearTimeout(timer); 
      loadNow(); 
     }); 
     // in case window.addEventListener doesn't get called (sometimes some resource gets stuck) 
     // then preload the images anyway after some timeout time 
     timer = setTimeout(loadNow, t); 
    } 

    function loadNow() { 
     if (!loaded) { 
      loaded = true; 
      for (var i = 0; i < imgs.length; i++) { 
       var img = new Image(); 
       img.onload = img.onerror = img.onabort = function() { 
        var index = list.indexOf(this); 
        if (index !== -1) { 
         // remove image from the array once it's loaded 
         // for memory consumption reasons 
         list.splice(index, 1); 
        } 
       } 
       list.push(img); 
       img.src = imgs[i]; 
      } 
     } 
    } 
} 

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"], true); 
preloadImages(["url99.jpg", "url98.jpg"], true); 
+0

En este ejemplo, está creando un nuevo objeto de imagen para cada url. Si configura la variable img fuera del ciclo y simplemente actualiza el src, debería tener el mismo efecto y reducir los recursos – cadlac

+0

@cadlac - Pero para estar seguro de que el navegador realmente descargaría y almacenaría en caché cada imagen, tendría que espere hasta que una imagen termine de descargarse antes de establecer una nueva propiedad .src. De lo contrario, el navegador podría detener la descarga previa y nunca almacenarla en la memoria caché. – jfriend00

+0

Parece que funciona en las versiones más nuevas de navegadores sin esperar, pero usted hace un buen punto. Tendré que probarlo en algunos navegadores más antiguos para ver si es compatible :) – cadlac

10

como @Pointy dijo que no almacena imágenes en caché con javascript, el navegador hace eso. así que esto puede ser lo que estás pidiendo y puede que no sea ... pero puedes precargar imágenes usando javascript. Al colocar todas las imágenes que desea precargar en una matriz y poner todas las imágenes de esa matriz en elementos de img ocultos, precarga (o almacena en caché) las imágenes.

var images = [ 
'/path/to/image1.png', 
'/path/to/image2.png' 
]; 

$(images).each(function() { 
var image = $('<img />').attr('src', this); 
}); 
+2

¿sería posible precargar una imagen en una página (sin mostrarla) y luego mostrarla en la página siguiente? –

+1

que yo sepa si precarga una imagen en una página, se ingresará en la memoria caché de los navegadores y luego se mostrará más rápido en cualquier otra página. si esto está mal, alguien por favor corrígeme. –

2

Hay algunas cosas que usted puede buscar en:

precarga sus imágenes
marcar un tiempo de caché en un archivo .htaccess
tamaño archivos de imágenes y base64 codifican.

precarga: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

Almacenamiento en caché: http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html

Hay un par de pensamientos diferentes para la codificación base64, algunos dicen que las peticiones http empantanan ancho de banda, mientras que otros dicen que la "percibida" de carga es mejor. Dejaré esto en el aire.

0

Sí, el navegador almacena en caché las imágenes automáticamente.

Puede, sin embargo, configurar una caché de imagen para que caduque. Echa un vistazo a esta pila de desbordamiento preguntas y respuestas:

Cache Expiration On Static Images

1

Tengo un similar answer de precarga asíncrona imágenes a través de JS. Cargarlos dinámicamente es lo mismo que cargarlos normalmente. ellos guardarán en caché.

En cuanto al almacenamiento en caché, no puede controlar el navegador, pero puede configurarlo a través del servidor. si necesita cargar un recurso realmente nuevo bajo demanda, puede usar el cache buster technique para forzar la carga de un recurso nuevo.

1

A pesar de que su pregunta dice "usando javascript", puede utilizar el atributo prefetch de una etiqueta de enlace para precargar cualquier activo. Al escribir estas líneas (Agosto 10, 2016) no se apoya en Safari, pero es más o menos en todas partes:

<link rel="prefetch" href="(url)">

Más información sobre el apoyo aquí: http://caniuse.com/#search=prefetch

Tenga en cuenta que IE 9 , 10 no se enumeran en la matriz caniuse porque Microsoft ha suspendido el soporte para ellos.

Así que si estás realmente atascado en el uso de JavaScript, se puede usar jQuery para añadir dinámicamente estos elementos a su página, así ;-)

+0

¡Agradable agradable bonito agradable! –

1

que utilizan una técnica similar a LazyLoad imágenes, pero no puede dejar de Observe que Javascript no tiene acceso al caché del navegador en la primera carga.

Mi ejemplo:

He una bandera que gira en mi página de inicio con 4 imágenes del deslizador espere 2 segundos, que el javascript carga la siguiente imagen, espera 2 segundos, etc.

Estas imágenes tienen direcciones URL únicas que cambian cada vez que las modifico, por lo que obtienen encabezados de almacenamiento en memoria caché que se almacenarán en caché en el navegador durante un año.

max-age: 31536000, public 

Ahora, cuando abra Chrome Devtools y asegúrese de opción 'Desactivar caché' no está activo y carga la página por primera vez (después de borrar la memoria caché) todas las imágenes conseguir traer y tener un estado 200. Después de un ciclo completo de todas las imágenes en el banner, las solicitudes de red se detienen y se utilizan las imágenes en caché.

Ahora cuando realizo una actualización regular o voy a una subpágina y hago clic atrás, las imágenes que están en la caché parecen ser ignoradas. Esperaría ver un mensaje gris "desde el caché de disco" en la pestaña Red de Chrome devtools. En cambio, veo que las solicitudes pasan cada dos segundos con un círculo de estado verde en lugar de gris, veo que se transfieren datos, por lo que me da la impresión de que no se accede a la caché desde javascript. Simplemente recupera la imagen cada vez que se carga la página.

De modo que cada solicitud a la página de inicio desencadena 4 solicitudes independientemente de la política de almacenamiento en caché de la imagen.

Teniendo en cuenta lo anterior juntos y el nuevo estándar http2 que la mayoría de los servidores web y navegadores soportan ahora, creo que es mejor dejar de usar lazyloading ya que http2 cargará todas las imágenes casi simultáneamente.

Si esto es un error en Chrome Devtools, realmente sorprende que nadie haya notado esto todavía. ;)

Si esto es cierto, el uso de lazyloading solo aumenta el uso de ancho de banda.

Corrígeme si me equivoco. :)

0

Siempre prefiero usar el ejemplo mencionado en Konva JS: Image Events para cargar imágenes.

  1. Usted necesita tener una lista de URL de imagen como objeto o matriz, por ejemplo:

    var sources = { lion: '/assets/lion.png', monkey: '/assets/monkey.png' };

  2. Definir la definición de funciones, donde recibe lista de URL de imagen y una función de devolución de llamada en su lista de argumentos, por lo que cuando se termine de cargar la imagen se puede empezar excution en tu página web:

function loadImages(sources, callback) { 
 
       var images = {}; 
 
       var loadedImages = 0; 
 
       var numImages = 0; 
 
       for (var src in sources) { 
 
        numImages++; 
 
       } 
 
       for (var src in sources) { 
 
        images[src] = new Image(); 
 
        images[src].onload = function() { 
 
         if (++loadedImages >= numImages) { 
 
          callback(images); 
 
         } 
 
        }; 
 
        images[src].src = sources[src]; 
 
       } 
 
      }

  1. Por último, es necesario llamar a la función. Se le puede llamar por ejemplo de jQuery 's Documento listo

$(document).ready(function(){ loadImages(sources, buildStage); });

Cuestiones relacionadas