web-dev-qa-db-ja.com

Javascriptで画像をキャッシュする方法

私の友人と私は、将来より速く表示するために特定の画像をキャッシュしたいウェブサイトに取り組んでいます。主に2つの質問があります。

  1. どのように画像をキャッシュしますか?
  2. キャッシュされた画像はどのように使用しますか? (そして確認のために、画像がページAにキャッシュされている場合、キャッシュから呼び出してページBで使用することができますよね?)

また、whenイメージのキャッシュバージョンの有効期限を設定することは可能ですか?

これをさらに説明する例および/またはページへのリンクが含まれていれば幸いです。

生のJavascriptまたはjQueryバージョンを使用しても問題ありません。

66
Logan Besecker

画像がブラウザに何らかの方法でロードされると、ブラウザのキャッシュに格納され、その使用が現在のページまたは他のページで使用されているかどうかに関係なく、次回の使用時にはるかに高速にロードされますブラウザのキャッシュから期限切れになる前に使用されます。

したがって、画像をプリキャッシュするには、ブラウザに画像をロードするだけです。たくさんの画像をプリキャッシュしたい場合は、javascriptを使用するのが一般的にベストです。javascriptから実行した場合、ページの読み込みを保持できないためです。次のようにできます:

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

この関数は何度でも呼び出すことができ、毎回、プリキャッシュに画像を追加するだけです。

JavaScriptを介してこのように画像がプリロードされると、ブラウザはキャッシュ内に画像を保持し、他の場所(Webページ内)で通常のURLを参照するだけで、ブラウザはURLではなくキャッシュからそのURLを取得します通信網。

最終的には、ブラウザーのキャッシュがいっぱいになり、しばらく使用されていない最も古いものが破棄される可能性があります。そのため、最終的に、画像はキャッシュからフラッシュされますが、しばらくはそこにとどまる必要があります(キャッシュの大きさと他のブラウジングの量によって異なります)。画像が実際に再びプリロードされるかWebページで使用されるたびに、ブラウザキャッシュ内の位置が自動的に更新されるため、キャッシュからフラッシュされる可能性が低くなります。

ブラウザのキャッシュはクロスページなので、ブラウザに読み込まれたページに対して機能します。そのため、サイトの1か所で事前キャッシュを行うことができ、ブラウザキャッシュはサイトの他のすべてのページで機能します。


上記のように事前キャッシュする場合、画像は非同期に読み込まれるため、ページの読み込みや表示がブロックされることはありません。ただし、ページに独自の画像が多数ある場合、これらのプリキャッシュ画像は、ページに表示される画像と帯域幅または接続を競うことができます。通常、これは目立った問題ではありませんが、接続が遅い場合、この事前キャッシュによりメインページの読み込みが遅くなる可能性があります。プリロードイメージを最後にロードしても問題ない場合は、他のすべてのページリソースが既にロードされるまでプリロードの開始を待機するバージョンの関数を使用できます。

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

@PointyがJavaScriptで画像をキャッシュしないと言ったように、ブラウザはそれを行います。したがって、これはあなたが求めているものであり、そうではないかもしれません...しかし、javascriptを使用して画像をプリロードすることができます。プリロードするすべての画像を配列に配置し、その配列内のすべての画像を非表示のimg要素に配置することで、画像を効果的にプリロード(またはキャッシュ)できます。

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

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

あなたが見ることができるいくつかのことがあります:

画像をプリロードする
。htaccessファイルでのキャッシュ時間の設定
画像のファイルサイズとBase64エンコード。

プリロード: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

キャッシュ: http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html

Base64エンコーディングにはいくつかの異なる考えがあり、http要求が帯域幅を低下させていると言う人もいれば、「知覚された」ロードが優れていると言う人もいます。これは空中に残しておきます。

3
Tim

「javascriptを使用して」という質問があったとしても、リンクタグのprefetch属性を使用して、アセットをプリロードできます。この記事の執筆時点(2016年8月10日)では、Safariではサポートされていませんが、他のほとんどの場所でサポートされています。

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

サポートの詳細はこちら: http://caniuse.com/#search=prefetch

IE 9,10はcaniuseマトリックスにリストされていないことに注意してください。Microsoftはそれらのサポートを終了しています。

したがって、javascriptの使用にこだわっている場合は、jqueryを使用してこれらの要素をページに動的に追加することもできます;-)

1
Brad Parks

同様の手法を使用して画像を遅延読み込みしますが、Javascriptが最初の読み込み時にブラウザーのキャッシュにアクセスしないことに注意してください。

私の例:

ホームページに4つの画像を含む回転バナーがあり、スライダーは2秒待機します。JavaScriptは次の画像を読み込み、2秒待機します。

これらの画像には、変更するたびに変わる一意のURLがあるため、1年間ブラウザにキャッシュされるキャッシュヘッダーを取得します。

max-age: 31536000, public

Chrome Devtoolsを開き、de 'キャッシュを無効にする'オプションがアクティブになっていないことを確認し、ページを初めて(キャッシュをクリアした後)読み込むと、すべての画像が取得され、ステータスが200になります。バナー内のすべての画像の完全なサイクルの後、ネットワーク要求は停止し、キャッシュされた画像が使用されます。

これで、定期的な更新を行うか、サブページに移動してクリックして戻ると、キャッシュ内の画像は無視されるようです。 Chrome devtoolsの[ネットワーク]タブに「ディスクキャッシュから」という灰色のメッセージが表示されると予想されます。代わりに、灰色ではなく緑色のステータスサークルでリクエストが2秒ごとに通過するのを見ると、データが転送されているので、javascriptからキャッシュにまったくアクセスされていない印象を受けます。ページが読み込まれるたびに画像を取得するだけです。

したがって、ホームページへの各リクエストは、画像のキャッシュポリシーに関係なく4つのリクエストをトリガーします。

上記を合わせて、ほとんどのWebサーバーとブラウザがサポートする新しいhttp2標準を考慮すると、http2はすべての画像をほぼ同時に読み込むため、遅延読み込みの使用を停止する方が良いと思います。

これがChrome Devtoolsのバグである場合、誰もまだこれに気づいていないことに本当に驚きます。 ;)

これが当てはまる場合、遅延読み込みを使用しても帯域幅の使用量が増えるだけです。

私が間違っている場合は修正してください。 :)

1

私は 類似の答え を使用して、JSを介した非同期プリロードイメージを作成しています。動的にロードすることは、通常のロードと同じです。それらはキャッシュされます。

キャッシュに関しては、ブラウザを制御することはできませんが、サーバー経由で設定することはできます。本当に新鮮なリソースをオンデマンドでロードする必要がある場合、 cache buster technique を使用して強制的に新鮮なリソースをロードできます。

1
Joseph

Konva JS:Image Events に記載されている例を使用して、画像をロードすることを常に好みます。

  1. オブジェクトまたは配列として画像URLのリストが必要です。例えば:

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

  2. 関数の定義を定義します。ここで、画像のURLのリストと引数リストのコールバック関数を受け取るため、画像の読み込みが完了したら、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. 最後に、関数を呼び出す必要があります。あなたは例えばからそれを呼び出すことができます jQueryDocument Ready

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

0
Mahdi Alkhatib

はい、ブラウザは自動的に画像をキャッシュします。

ただし、画像キャッシュを期限切れに設定することはできます。このStack Overflowの質問と回答をご覧ください。

静的イメージのキャッシュ有効期限

0
magzalez