web-dev-qa-db-fra.com

Comment mettre en cache une image en Javascript

Mes amis et moi travaillons sur un site Web sur lequel nous aimerions mettre certaines images en mémoire cache afin de les afficher plus rapidement. J'ai deux questions principales:

  1. Comment cachez-vous une image?
  2. Comment utilisez-vous une image une fois qu'elle a été mise en cache? (et juste pour vérifier, si une image est mise en cache sur la page A, il est possible de l'appeler depuis le cache pour l'utiliser à la page B, n'est-ce pas?)

Aussi, est-il possible de définir when la version en cache de l'image va expirer?

Nous vous serions reconnaissants d'inclure un exemple et/ou un lien vers une page décrivant ce sujet.

Nous acceptons soit le code Javascript brut, soit la version jQuery.

60
Logan Besecker

Une fois qu'une image a été chargée de quelque manière que ce soit dans le navigateur, elle se trouvera dans la mémoire cache du navigateur et se chargera beaucoup plus rapidement lors de son utilisation suivante, que cette utilisation soit dans la page en cours ou dans une autre page tant que l'image est affichée. utilisé avant son expiration dans le cache du navigateur.

Donc, pour mettre en cache des images, tout ce que vous avez à faire est de les charger dans le navigateur. Si vous souhaitez mettre en cache plusieurs images, il est probablement préférable de le faire avec javascript, car cela ne gênera généralement pas le chargement de la page lorsque javascript est effectué. Vous pouvez faire ça comme ça:

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"]);

Cette fonction peut être appelée autant de fois que vous le souhaitez et à chaque fois, elle ne fera qu'ajouter plus d'images au précachets.

Une fois que les images ont été préchargées de cette manière via JavaScript, le navigateur les aura dans son cache et vous pouvez simplement vous référer aux URL normales d’autres endroits (dans vos pages Web) et le navigateur extraira cette URL de son cache plutôt que réseau.

Finalement, au fil du temps, le cache du navigateur peut se remplir et jeter les éléments les plus anciens qui n’ont pas été utilisés depuis un certain temps. Ainsi, les images seront éventuellement vidées de la mémoire cache, mais elles devraient y rester pendant un certain temps (en fonction de la taille de la mémoire cache et du nombre de recherches effectuées). Chaque fois que les images sont préchargées ou utilisées dans une page Web, leur position dans le cache du navigateur est automatiquement actualisée, ce qui réduit leur probabilité de se vider du cache.

La mémoire cache du navigateur est inter-pages, ce qui fonctionne pour toutes les pages chargées dans le navigateur. Ainsi, vous pouvez précacheter à un endroit de votre site et le cache du navigateur fonctionnera pour toutes les autres pages de votre site.


Lors du précaching comme ci-dessus, les images sont chargées de manière asynchrone afin de ne pas bloquer le chargement ou l'affichage de votre page. Toutefois, si votre page contient de nombreuses images, ces images précachées peuvent entrer en concurrence pour la bande passante ou les connexions avec les images affichées dans votre page. Normalement, ce problème n’est pas perceptible, mais lors d’une connexion lente, cette mise en cache pourrait ralentir le chargement de la page principale. Si le dernier chargement des images de préchargement était correct, vous pouvez utiliser une version de la fonction qui attendrait de démarrer le préchargement après le chargement de toutes les autres ressources de la page.

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);
108
jfriend00

comme @Pointy dit que vous ne cachez pas les images avec javascript, le navigateur le fait. c'est peut-être ce que vous demandez et peut-être pas ... mais vous pouvez précharger des images à l'aide de javascript. En plaçant toutes les images que vous souhaitez précharger dans un tableau et en plaçant toutes les images de ce tableau dans des éléments img cachés, vous préchargez (ou mettez en cache) les images.

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

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

Il y a quelques choses que vous pouvez regarder:

Pré-chargement de vos images
Définition d’une heure de cache dans un fichier .htaccess
Taille du fichier des images et encodage base64. 

Préchargement: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

Mise en cache: http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html

Il y a deux idées différentes pour l'encodage en base64, certains disent que les requêtes http ralentissent la bande passante, alors que d'autres disent que le chargement "perçu" est meilleur. Je vais laisser ça en l'air.

2
Tim

J'utilise une technique similaire pour charger des images, mais je ne peux pas m'empêcher de remarquer que Javascript n'accède pas au cache du navigateur lors du premier chargement.

Mon exemple:

J'ai une bannière rotative sur ma page d'accueil avec 4 images, le curseur attend 2 secondes, puis le javascript charge l'image suivante, attend 2 secondes, etc.

Ces images ont des URL uniques qui changent chaque fois que je les modifie. Elles ont donc des en-têtes de mise en cache qui seront mises en cache dans le navigateur pendant un an.

max-age: 31536000, public

Maintenant, lorsque j'ouvre Chrome Devtools et que je m'assure que l'option 'Désactiver le cache' n'est pas active et que je charge la page pour la première fois (après avoir effacé le cache), toutes les images sont récupérées et ont un statut 200. Après un cycle complet de toutes les images dans la bannière, les demandes du réseau s’arrêtent et les images en cache sont utilisées. 

Désormais, lorsque je fais une actualisation régulière ou que je vais dans une sous-page et que je clique en arrière, les images contenues dans le cache semblent être ignorées. Je m'attendrais à voir un message gris "à partir du cache disque" dans l'onglet Réseau de Chrome devtools. Au lieu de cela, je vois les requêtes passer toutes les deux secondes avec un cercle d’état vert au lieu de gris, je vois les données transférées, donc j’ai l’impression que le cache n’est pas accessible du tout à partir de javascript. Il récupère simplement l'image chaque fois que la page est chargée.

Ainsi, chaque requête sur la page d'accueil déclenche 4 requêtes, quelle que soit la stratégie de mise en cache de l'image.

Compte tenu de ce qui précède et de la nouvelle norme http2 prise en charge par la plupart des serveurs Web et des navigateurs, je pense qu’il est préférable de cesser d’utiliser lazyloading, car http2 chargera toutes les images presque simultanément.

S'il s'agit d'un bogue dans Chrome Devtools, cela surprend vraiment personne n'a encore remarqué cela. ;)

Si cela est vrai, l'utilisation de lazyloading augmente uniquement l'utilisation de la bande passante.

Corrigez-moi si j'ai tort, s'il-vous plait. :)

1
Jean-Paul Ladage

J'ai une réponse similaire pour le préchargement asynchrone des images via JS. Les charger dynamiquement revient à les charger normalement. ils vont cacher.

quant à la mise en cache, vous ne pouvez pas contrôler le navigateur mais vous pouvez le configurer via le serveur. si vous avez besoin de charger une nouvelle ressource à la demande, vous pouvez utiliser la technique cache buster pour forcer le chargement d'une nouvelle ressource.

1
Joseph

Je préfère toujours utiliser l'exemple mentionné dans Konva JS: Image Events pour charger des images.

  1. Vous devez avoir une liste d’URL d’image sous forme d’objet ou de tableau, par exemple:

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

  2. Définissez la définition de la fonction, où elle reçoit la liste des URL de l’image et une fonction de rappel dans sa liste d’arguments. Ainsi, une fois le chargement de l’image terminé, vous pourrez commencer l’exécution sur votre page 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. Enfin, vous devez appeler la fonction. Vous pouvez l'appeler par exemple de jQuery's Document prêt

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

0
Mahdi Alkhatib

Oui, le navigateur met automatiquement les images en cache pour vous.

Cependant, vous pouvez définir l’expiration d’un cache d’image. Consultez ces questions de débordement de pile et répondez:

Expiration du cache sur les images statiques

0
magzalez