कैसे आप जावास्क्रिप्ट में एक छवि कैश करते हैं


84

मेरे मित्र और मैं एक ऐसी वेबसाइट पर काम कर रहे हैं, जहाँ हम भविष्य में उन्हें तेज़ी से प्रदर्शित करने के लिए कुछ छवियों को कैश करना चाहेंगे। मेरे दो मुख्य प्रश्न हैं:

  1. आप एक छवि को कैश कैसे करते हैं?
  2. एक बार कैश होने के बाद आप किसी इमेज का उपयोग कैसे करते हैं? (और सिर्फ सत्यापित करने के लिए, यदि कोई चित्र पृष्ठ ए पर कैश किया गया है, तो इसे कैश से कॉल करके पेज बी, राइट पर उपयोग करना संभव है?)

इसके अलावा, क्या यह सेट करना संभव है जब छवि का कैश्ड संस्करण समाप्त हो जाएगा?

यदि एक उदाहरण और / या किसी पृष्ठ का लिंक जो इसे आगे वर्णित करता है, इसे बहुत सराहा जाएगा।

हम कच्चे जावास्क्रिप्ट या jQuery संस्करण का उपयोग करके ठीक हैं।


12
तुम नहीं। ब्राउज़र करता है।
इंगित

ब्राउज़र कैश छवियों को स्वचालित रूप से करता है?
लोगन बेसेकर

8
@Logan: हाँ, ब्राउज़र स्वचालित रूप से छवियों को कैश कर देता है, बशर्ते आपका सर्वर ब्राउज़र को यह बताना सुरक्षित रखता है कि वह इसे कैश करना सुरक्षित है। (ये हेडर ब्राउज़र को समाप्ति का समय भी बता सकते हैं, जो आपके प्रश्न का हिस्सा है।)
icktoofay

मैं यह कैसे सत्यापित कर सकता हूं कि मेरा ब्राउज़र आवश्यक हेडर भेज रहा है?
लोगन बेसेकर

1
@LoganBesecker आप अपने ब्राउज़र देव टूल्स के नेटवर्क सेक्शन में रिस्पॉन्स हेडर्स की जांच कर सकते हैं।
jlaceda

जवाबों:


133

एक बार जब किसी छवि को ब्राउज़र में किसी भी तरह से लोड किया जाता है, तो यह ब्राउज़र कैश में होगा और अगली बार उपयोग किए जाने पर बहुत तेज़ी से लोड होगा, चाहे वह उपयोग वर्तमान पृष्ठ में हो या किसी अन्य पेज में जब तक छवि है इसका उपयोग ब्राउज़र कैश से समाप्त होने से पहले किया जाता है।

इसलिए, छवियों को प्रीच करने के लिए, आपको बस उन्हें ब्राउज़र में लोड करना होगा। यदि आप छवियों का एक गुच्छा तैयार करना चाहते हैं, तो संभवतः इसे जावास्क्रिप्ट के साथ करना सबसे अच्छा है क्योंकि यह आमतौर पर जब जावास्क्रिप्ट से किया जाता है तो पेज लोड नहीं करेगा। आप ऐसा कर सकते हैं:

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

इस फ़ंक्शन को जितनी बार चाहें उतनी बार और प्रत्येक बार कॉल किया जा सकता है, यह सिर्फ प्रीचेच में अधिक छवियां जोड़ देगा।

एक बार जब इस तरह की तस्वीरों को जावास्क्रिप्ट के माध्यम से पहले से लोड किया गया है, तो ब्राउज़र उनके कैश में होगा और आप सामान्य URL को अन्य स्थानों पर (आपके वेब पेजों में) संदर्भित कर सकते हैं और ब्राउज़र उस URL को अपने कैश से अधिक के बजाय लाएगा। नेटवर्क।

अंततः समय के साथ, ब्राउज़र कैश भर सकता है और सबसे पुरानी चीजों को टॉस कर सकता है जो थोड़ी देर में उपयोग नहीं किए गए हैं। तो आखिरकार, छवियों को कैश से बाहर निकाल दिया जाएगा, लेकिन उन्हें थोड़ी देर के लिए वहां रहना चाहिए (यह निर्भर करता है कि कैश कितना बड़ा है और अन्य ब्राउज़िंग कैसे की जाती है)। हर बार छवियों को वास्तव में फिर से लोड किया जाता है या वेब पेज में उपयोग किया जाता है, यह स्वचालित रूप से ब्राउज़र कैश में अपनी स्थिति को ताज़ा करता है ताकि उन्हें कैश से बाहर निकालने की संभावना कम हो।

ब्राउज़र कैश क्रॉस-पेज है इसलिए यह ब्राउज़र में लोड किए गए किसी भी पेज के लिए काम करता है। तो आप अपनी साइट में एक जगह पर प्रीचैच कर सकते हैं और फिर ब्राउज़र कैश आपकी साइट के अन्य सभी पृष्ठों के लिए काम करेगा।


जब उपर्युक्त के रूप में पेश किया जाता है, तो छवियों को अतुल्यकालिक रूप से लोड किया जाता है ताकि वे आपके पृष्ठ के लोडिंग या प्रदर्शन को अवरुद्ध न करें। लेकिन, यदि आपके पृष्ठ की अपनी बहुत सारी छवियां हैं, तो ये प्रीचेच छवियां आपके पृष्ठ में प्रदर्शित छवियों के साथ बैंडविड्थ या कनेक्शन के लिए प्रतिस्पर्धा कर सकती हैं। आम तौर पर, यह ध्यान देने योग्य मुद्दा नहीं है, लेकिन एक धीमी गति से कनेक्शन पर, यह प्रारंभिक प्रशिक्षण मुख्य पृष्ठ के लोड को धीमा कर सकता है। यदि पिछली बार लोड की जाने वाली प्रीलोड छवियों के लिए यह ठीक था, तो आप फ़ंक्शन के एक संस्करण का उपयोग कर सकते हैं जो अन्य सभी पेज संसाधनों के पहले से लोड होने के बाद प्रीलोडिंग शुरू करने की प्रतीक्षा करेगा।

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

इस उदाहरण में आप प्रत्येक url के लिए एक नई छवि ऑब्जेक्ट बना रहे हैं। यदि आप img वैरिएबल को लूप के बाहर सेट करते हैं और बस src को अपडेट करते हैं, तो इसका एक ही प्रभाव होना चाहिए और संसाधनों पर कटौती करना चाहिए
Cadlac

2
@cadlac - लेकिन यह सुनिश्चित करने के लिए कि ब्राउज़र वास्तव में प्रत्येक छवि को डाउलोड और कैश करेगा, आपको एक नई .src संपत्ति सेट करने से पहले एक छवि डाउनलोड होने तक इंतजार करना होगा। अन्यथा ब्राउज़र केवल पूर्व डाउनलोड को रोक सकता है और इसे सफलतापूर्वक कैश नहीं कर सकता है।
jfriend00

यह प्रतीक्षा किए बिना ब्राउज़र के नए संस्करणों पर काम करने लगता है, लेकिन आप एक अच्छा बिंदु बनाते हैं। मुझे यह देखने के लिए कुछ पुराने ब्राउज़रों पर कोशिश करनी होगी कि यह संगतता है :)
Cadlac

@cadlac - कोई ज़रूरत नहीं है। Image()जब छवि लोड हो रही है तो मैंने सूची से तत्व को हटाने के लिए कोड को अपडेट किया । छवि को लोड करना समाप्त होने तक इंतजार करना सुरक्षित है।
18

1
मैंने स्क्रिप्ट का एक और संस्करण जोड़ा है जो तब तक इंतजार करता है जब तक कि अन्य दस्तावेज़ संसाधन लोड नहीं किए जाते हैं, इसलिए छवियों के पूर्व लोडिंग दृश्यमान पृष्ठ संसाधनों के लोड के साथ बैंडविड्थ के लिए प्रतिस्पर्धा नहीं करता है।
jfriend00

13

जैसा कि @ पॉइन्टी ने कहा कि आप जावास्क्रिप्ट के साथ छवियों को कैश नहीं करते हैं, ब्राउज़र ऐसा करता है। तो यह वही हो सकता है जो आप के लिए पूछ रहे हैं और नहीं हो सकता है ... लेकिन आप जावास्क्रिप्ट का उपयोग करके छवियों को पहले से लोड कर सकते हैं। उन सभी छवियों को डालकर, जिन्हें आप किसी सरणी में प्रीलोड करना चाहते हैं और उस एरे में सभी चित्रों को छिपे हुए img तत्वों में डालकर, आप प्रभावी रूप से छवियों (या कैश) को प्रीलोड करते हैं।

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

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

2
क्या एक पृष्ठ पर एक छवि प्रीलोड करना संभव होगा (इसे प्रदर्शित किए बिना), फिर इसे अगले पृष्ठ पर प्रदर्शित करें?
लोगन बेसेकर

2
मेरे ज्ञान के लिए यदि आप एक पृष्ठ पर एक छवि प्रीलोड करते हैं तो उसे ब्राउज़र कैश में दर्ज किया जाएगा और फिर किसी अन्य पेज पर प्रदर्शित किया जाएगा। अगर यह गलत है, तो कृपया मुझे कोई सही करे।
Trav McKinney

4

हालांकि आपका प्रश्न "जावास्क्रिप्ट का उपयोग करना" कहता है, आप prefetchकिसी भी संपत्ति को प्रीलोड करने के लिए लिंक टैग की विशेषता का उपयोग कर सकते हैं । इस लेखन के रूप में (10 अगस्त, 2016) यह सफारी में समर्थित नहीं है, लेकिन हर जगह बहुत अधिक है:

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

समर्थन पर अधिक जानकारी यहाँ: http://caniuse.com/#search=prefetch

ध्यान दें कि IE 9,10 caniuseमैट्रिक्स में सूचीबद्ध नहीं हैं क्योंकि Microsoft ने उनके लिए समर्थन बंद कर दिया है।

इसलिए यदि आप वास्तव में जावास्क्रिप्ट का उपयोग करने पर अटक गए थे, तो आप इन तत्वों को गतिशील रूप से अपने पेज में जोड़ने के लिए jquery का उपयोग कर सकते थे;;


1
अच्छा अच्छा अच्छा अच्छा!
भार्गव नानकेलवा

3

कुछ चीजें हैं जिन्हें आप देख सकते हैं:

अपनी छवियों को प्री-लोड
करना .htaccess फ़ाइल में कैश समय सेट करना छवियों का
फ़ाइल आकार और उन्हें 6464 एन्कोडिंग।

प्रीलोडिंग: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

कैशिंग: http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html

बेस 64 एनकोडिंग के लिए कुछ अलग विचार हैं, कुछ का कहना है कि http अनुरोध बैंडविड्थ को कम कर देता है, जबकि अन्य कहते हैं कि "कथित" लोडिंग बेहतर है। मैं इसे हवा में छोड़ दूंगा।


3

उत्तरों की पूर्णता के लिए जोड़ना: HTML के साथ पूर्व लोड करना

<link rel="preload" href="bg-image-wide.png" as="image">

अन्य प्रीलोडिंग सुविधाएँ मौजूद हैं, लेकिन कोई भी इस उद्देश्य के लिए बहुत उपयुक्त नहीं है <link rel="preload">:

  • <link rel="prefetch">ब्राउज़रों में लंबे समय से समर्थित है, लेकिन यह प्रीफ़िटिंग संसाधनों के लिए अभिप्रेत है जो अगले नेविगेशन / पेज लोड (जैसे जब आप अगले पृष्ठ पर जाते हैं) में उपयोग किया जाएगा। यह ठीक है, लेकिन वर्तमान पृष्ठ के लिए उपयोगी नहीं है! इसके अलावा, ब्राउज़र प्रीफ़ैच संसाधनों को प्रीलोड वालों की तुलना में कम प्राथमिकता देगा - वर्तमान पृष्ठ अगले की तुलना में अधिक महत्वपूर्ण है। देखें लिंक प्रीफ़ेचिंग पूछे जाने वाले प्रश्न अधिक जानकारी के लिए।
  • <link rel="prerender">यदि उपयोगकर्ता इसे नेविगेट करता है, तो पृष्ठभूमि में एक निर्दिष्ट वेब पेज रेंडर करता है, इसके लोड को तेज करता है। उपयोगकर्ताओं की बैंडविड्थ को बर्बाद करने की क्षमता के कारण, क्रोम प्रेंडरेंडर को इसके बजाय NoState प्रीफ़ैच के रूप में मानता है।
  • <link rel="subresource"> कुछ समय पहले क्रोम में समर्थित था, और प्री-लोड के रूप में एक ही मुद्दे से निपटने का इरादा था, लेकिन इसमें एक समस्या थी: आइटम के लिए प्राथमिकता का काम करने का कोई तरीका नहीं था (जैसा कि तब मौजूद नहीं था), इसलिए वे सभी काफी कम प्राथमिकता के साथ लाया गया।

वहाँ स्क्रिप्ट-आधारित संसाधन लोडर की एक संख्या है, लेकिन उनके पास ब्राउज़र की प्राथमिकता प्राथमिकता कतार में कोई शक्ति नहीं है, और बहुत अधिक प्रदर्शन समस्याओं के अधीन हैं।

स्रोत: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content


1

जेएस के माध्यम से अतुल्यकालिक प्री लोडिंग छवियों के लिए मेरे पास एक समान उत्तर है । उन्हें गतिशील रूप से लोड करना सामान्य रूप से उन्हें लोड करने के समान है। वे कैश करेंगे।

कैशिंग के लिए, आप ब्राउज़र को नियंत्रित नहीं कर सकते, लेकिन आप इसे सर्वर के माध्यम से सेट कर सकते हैं। यदि आपको मांग पर वास्तव में एक ताजा संसाधन लोड करने की आवश्यकता है, तो आप कैश बस्टर तकनीक का उपयोग करके एक ताजा संसाधन लोड करने के लिए मजबूर कर सकते हैं ।


1

मैं छवियों को आलसी करने के लिए एक समान तकनीक का उपयोग करता हूं, लेकिन मदद नहीं कर सकता है लेकिन ध्यान दें कि जावास्क्रिप्ट पहले लोड होने पर ब्राउज़र कैश तक पहुंच नहीं करता है।

मेरा उदाहरण:

मेरे चित्र पर मेरे बैनर पर एक घूर्णन बैनर है जिसमें 4 छवियां हैं स्लाइडर 2 सेकंड प्रतीक्षा करते हैं, जावास्क्रिप्ट से अगली छवि लोड होती है, 2 सेकंड प्रतीक्षा करता है, आदि।

इन छवियों में अनोखे यूआरएल होते हैं जो जब भी मैं उन्हें संशोधित करता हूं, तो उन्हें कैशिंग हेडर मिलते हैं जो एक वर्ष के लिए ब्राउज़र में कैश करेंगे।

max-age: 31536000, public

अब जब मैं क्रोम देवटूल खोलता हूं और यह सुनिश्चित करता हूं कि डी 'डिसेबल कैश' विकल्प सक्रिय नहीं है और पेज को पहली बार लोड करने के बाद (कैश क्लियर करने के बाद) सभी चित्र प्राप्त होते हैं और 200 की स्थिति होती है। बैनर में सभी छवियों के पूर्ण चक्र के बाद नेटवर्क अनुरोध बंद हो जाते हैं और कैश्ड छवियों का उपयोग किया जाता है।

अब जब मैं एक नियमित रिफ्रेश करता हूं या एक उपपृष्ठ पर जाता हूं और वापस क्लिक करता हूं, तो जो चित्र कैश में होते हैं, उन्हें नजरअंदाज कर दिया जाता है। मुझे Chrome devtools के नेटवर्क टैब में "डिस्क कैश से एक ग्रे संदेश" देखने की उम्मीद है। इसके बजाय मैं ग्रे के बजाय हरे रंग की स्थिति सर्कल के साथ हर दो सेकंड में अनुरोधों को पास करता हूं, मुझे डेटा स्थानांतरित होते हुए दिखाई देता है, इसलिए मुझे लगता है कि जावास्क्रिप्ट से जावास्क्रिप्ट बिल्कुल भी एक्सेस नहीं किया गया है। जब पृष्ठ लोड हो जाता है तो यह हर बार छवि प्राप्त करता है।

इसलिए होमपेज पर प्रत्येक अनुरोध छवि की कैशिंग नीति की परवाह किए बिना 4 अनुरोधों को चलाता है।

उपरोक्त एक साथ और नए http2 मानक अधिकांश वेबसर्वर और ब्राउज़र को ध्यान में रखते हुए अब समर्थन करते हुए, मुझे लगता है कि यह बेहतर है कि lazyloading का उपयोग बंद कर दें क्योंकि http2 सभी छवियों को लगभग एक साथ लोड करेगा।

यदि यह क्रोम Devtools में एक बग है, तो यह वास्तव में आश्चर्यचकित करता है कि किसी ने भी अभी तक इस पर ध्यान नहीं दिया है। ;)

यदि यह सच है, तो आलसी लोडिंग का उपयोग करने से केवल बैंडवाथ का उपयोग बढ़ता है।

कृपया मुझे सुधारें अगर मैं गलत हूं। :)


1

आजकल, Google द्वारा कैश और आपकी छवि प्रदान करने की प्रक्रिया में सुधार करने के लिए एक नई तकनीक का सुझाव दिया गया है:

  1. जावास्क्रिप्ट लेज़िज़ाइज़ फ़ाइल को शामिल करें: lazysizes.js
  2. उस HTML फ़ाइल में फ़ाइल जोड़ें जिसे आप उपयोग करना चाहते हैं: <script src="lazysizes.min.js" async></script>
  3. lazyloadअपनी छवि में वर्ग जोड़ें : <img data-src="images/flower3.png" class="lazyload" alt="">

0

हां, ब्राउज़र आपके लिए छवियों को स्वचालित रूप से कैश करता है।

हालाँकि, आप समाप्त करने के लिए एक छवि कैश सेट कर सकते हैं। इस ढेर अतिप्रवाह सवाल और जवाब की जाँच करें:

स्थैतिक छवियों पर कैश समाप्ति


0

मैं हमेशा कोंवा जेएस में उल्लिखित उदाहरण का उपयोग करना पसंद करता हूं : छवियों को लोड करने के लिए छवि घटनाएं

  1. उदाहरण के लिए आपको ऑब्जेक्ट या सरणी के रूप में छवि URL की एक सूची होनी चाहिए:

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

  2. फ़ंक्शन परिभाषा को परिभाषित करें, जहां यह अपनी तर्क सूची में छवि URL और कॉलबैक फ़ंक्शन की सूची प्राप्त करता है, इसलिए जब यह लोडिंग छवि को पूरा करता है तो आप अपने वेब पेज पर उत्कृष्टता शुरू कर सकते हैं:

    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. अंत में, आपको फ़ंक्शन को कॉल करने की आवश्यकता है। आप से उदाहरण के लिए यह कॉल कर सकते हैं jQueryके दस्तावेज तैयार

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.