कैशिंग शैलियाँ. स्पष्ट शब्दों और उदाहरणों में क्लाइंट कैशिंग की मूल बातें। अंतिम-संशोधित, ईटैग, समाप्ति, कैश-नियंत्रण: अधिकतम आयु और अन्य शीर्षलेख। यूआरएल फ़िंगरप्रिंट

💖क्या आपको यह पसंद है?लिंक को अपने दोस्तों के साथ साझा करें

उचित रूप से कॉन्फ़िगर की गई कैशिंग भारी प्रदर्शन लाभ प्रदान करती है, बैंडविड्थ बचाती है और सर्वर लागत को कम करती है, लेकिन कई साइटें कैशिंग को खराब तरीके से लागू करती हैं, जिससे दौड़ की स्थिति पैदा होती है जिससे इंटरकनेक्टेड संसाधन सिंक से बाहर हो जाते हैं।

कैशिंग की अधिकांश सर्वोत्तम प्रथाएं दो पैटर्न में से एक में आती हैं:

पैटर्न नंबर 1: अपरिवर्तनीय सामग्री और लंबी अधिकतम आयु कैश कैश-नियंत्रण: अधिकतम आयु=31536000
  • URL की सामग्री नहीं बदलती, इसलिए...
  • ब्राउज़र या सीडीएन संसाधन को एक वर्ष तक आसानी से कैश कर सकता है
  • निर्दिष्ट अधिकतम आयु से कम उम्र की कैश्ड सामग्री का उपयोग सर्वर से परामर्श किए बिना किया जा सकता है

पेज: अरे, मुझे "/script-v1.js", "/styles-v1.css" और "/cats-v1.jpg" चाहिए 10:24

नकद: मैं खाली हूं, आपका क्या ख्याल है, सर्वर? 10:24

सर्वर: ठीक है, वे यहाँ हैं। वैसे, नकद, उनका उपयोग एक वर्ष के लिए किया जाना चाहिए, इससे अधिक नहीं। 10:25

नकद: धन्यवाद! 10:25

पेज: हुर्रे! 10:25

अगले दिन

पेज: अरे, मुझे "/script-v2 .js", "/styles-v2 .css" और "/cats-v1.jpg" चाहिए 08:14

नकद: बिल्लियों के साथ एक तस्वीर है, लेकिन बाकी नहीं। सर्वर? 08:14

सर्वर: आसान - यहां नया सीएसएस और जेएस है। एक बार फिर, कैश: उनकी शेल्फ लाइफ एक वर्ष से अधिक नहीं है। 08:15

नकद: बढ़िया! 08:15

पेज: धन्यवाद! 08:15

नकद: हम्म, मैंने काफी समय से "/script-v1.js" और "/styles-v1.css" का उपयोग नहीं किया है। इन्हें हटाने का समय आ गया है. 12:32

इस पैटर्न का उपयोग करके, आप कभी भी किसी विशिष्ट यूआरएल की सामग्री नहीं बदलते हैं, आप यूआरएल ही बदलते हैं:

प्रत्येक URL में कुछ न कुछ होता है जो सामग्री के साथ बदलता है। यह एक संस्करण संख्या, एक संशोधित तिथि, या एक सामग्री हैश हो सकता है (जिसे मैंने अपने ब्लॉग के लिए चुना है)।

अधिकांश सर्वर-साइड फ्रेमवर्क में ऐसे उपकरण होते हैं जो आपको इस तरह के काम आसानी से करने की अनुमति देते हैं (Django में मैं मेनिफेस्ट​स्टेटिक​फाइल्स​स्टोरेज का उपयोग करता हूं); Node.js में बहुत छोटी लाइब्रेरी भी हैं जो समान समस्याओं का समाधान करती हैं, उदाहरण के लिए, गल्प-रेव।

हालाँकि, यह पैटर्न लेखों और ब्लॉग पोस्ट जैसी चीज़ों के लिए उपयुक्त नहीं है। उनके यूआरएल का संस्करण नहीं बनाया जा सकता और उनकी सामग्री बदल सकती है। सचमुच, मुझसे अक्सर व्याकरण संबंधी और विराम चिह्न संबंधी त्रुटियाँ होती हैं और मुझे सामग्री को शीघ्रता से अद्यतन करने में सक्षम होने की आवश्यकता होती है।

पैटर्न #2: परिवर्तनशील सामग्री जो हमेशा सर्वर पर मान्य होती है कैश-कंट्रोल: नो-कैश
  • यूआरएल की सामग्री बदल जाएगी, जिसका अर्थ है...
  • सर्वर को निर्दिष्ट किए बिना किसी भी स्थानीय रूप से कैश्ड संस्करण का उपयोग नहीं किया जा सकता है।

पृष्ठ: अरे, मुझे "/about/" और "/sw.js" की सामग्री चाहिए 11:32

नकद: मैं आपकी मदद नहीं कर सकता. सर्वर? 11:32

सर्वर: कुछ हैं. नकद, उन्हें अपने पास रखें, लेकिन उनका उपयोग करने से पहले मुझसे पूछें। 11:33

नकद: बिल्कुल! 11:33

पेज: धन्यवाद! 11:33

अगले दिन

पेज: अरे, मुझे "/about/" और "/sw.js" की सामग्री फिर से चाहिए 09:46

नकद: बस एक मिनट। सर्वर, क्या मेरी प्रतियाँ ठीक हैं? "/about/" की प्रति सोमवार की है, और "/sw.js" की प्रति कल की है। 09:46

सर्वर: "/sw.js" नहीं बदला है... 09:47

नकद: बढ़िया. पेज, "/sw.js" रखें। 09:47

सर्वर: ...लेकिन मेरे पास "/के बारे में/" है नया संस्करण. नकद, इसे पकड़ो, लेकिन पिछली बार की तरह, पहले मुझसे पूछना मत भूलना। 09:47

नकद: समझ गया! 09:47

पृष्ठ: बढ़िया! 09:47

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

इस पैटर्न में, हम प्रतिक्रिया में एक ETag (आपकी पसंद का संस्करण आईडी) या एक अंतिम-संशोधित हेडर जोड़ सकते हैं। अगली बार जब क्लाइंट सामग्री का अनुरोध करता है, तो क्रमशः इफ-नोन-मैच या इफ-मॉडिफाइड-सिंस आउटपुट होता है, जो सर्वर को यह कहने की अनुमति देता है कि "आपके पास जो है उसका उपयोग करें, आपका कैश अद्यतित है," यानी HTTP 304 लौटाएं।

यदि ईटैग/अंतिम-संशोधित भेजना संभव नहीं है, तो सर्वर हमेशा संपूर्ण सामग्री भेजता है।

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

यह असामान्य नहीं है कि हमारे पास पहले पैटर्न के लिए बुनियादी ढांचा नहीं है, लेकिन पैटर्न 2 में नेटवर्क अनुरोधों के साथ समस्याएं भी उत्पन्न हो सकती हैं। परिणामस्वरूप, एक मध्यवर्ती विकल्प का उपयोग किया जाता है: कम अधिकतम आयु और परिवर्तनशील सामग्री। यह एक बुरा समझौता है.

परिवर्तनशील सामग्री के साथ अधिकतम आयु का उपयोग करना आम तौर पर गलत विकल्प है

और, दुर्भाग्य से, यह आम है; जीथब पेज इसका एक उदाहरण है।

कल्पना करना:

  • /लेख/
  • /styles.css
  • /script.js

सर्वर हेडर के साथ:

कैश-नियंत्रण: पुनः सत्यापित करना होगा, अधिकतम-आयु=600

  • यूआरएल सामग्री बदल जाती है
  • यदि ब्राउज़र में 10 मिनट से अधिक पुराना कैश्ड संस्करण है, तो इसका उपयोग सर्वर से परामर्श किए बिना किया जाता है
  • यदि ऐसा कोई कैश नहीं है, तो नेटवर्क अनुरोध का उपयोग किया जाता है, यदि संभव हो तो इफ-मॉडिफाइड-सिंस या इफ-नोन-मैच के साथ।

पेज: अरे, मुझे "/article/", "/script.js" और "/styles.css" चाहिए 10:21

नकद: मेरे पास आपके जैसा कुछ भी नहीं है, सर्वर? 10:21

सर्वर: कोई समस्या नहीं, वे यहाँ हैं। लेकिन याद रखें, नकद: इनका उपयोग अगले 10 मिनट के भीतर किया जा सकता है। 10:22

नकद: हाँ! 10:22

पेज: धन्यवाद! 10:22

पृष्ठ: अरे, मुझे फिर से "/article/", "/script.js" और "/styles.css" की आवश्यकता है 10:28

नकद: उफ़, मुझे खेद है, लेकिन मैंने "/styles.css" खो दिया है, लेकिन मेरे पास बाकी सब कुछ है, यह लीजिए। सर्वर, क्या आप मेरे लिए "/styles.css" को अनुकूलित कर सकते हैं? 10:28

सर्वर: आराम से, पिछली बार जब आप उसे ले गए थे तब से वह पहले ही बदल चुका है। आप इसे अगले 10 मिनट तक सुरक्षित रूप से उपयोग कर सकते हैं। 10:29

नकद: कोई समस्या नहीं. 10:29

पेज: धन्यवाद! लेकिन ऐसा लगता है कि कुछ ग़लत हो गया! सबकुछ टूटा हुआ है! क्या हो रहा है? 10:29

इस पैटर्न को परीक्षण के दौरान जीवन का अधिकार है, लेकिन यह एक वास्तविक परियोजना में सब कुछ तोड़ देता है और इसे ट्रैक करना बहुत मुश्किल है। उपरोक्त उदाहरण में, सर्वर ने HTML, CSS और JS को अपडेट किया है, लेकिन पेज को पुराने कैश्ड HTML और JS के साथ-साथ सर्वर से अपडेट किए गए CSS के साथ प्रस्तुत किया गया है। संस्करण बेमेल सब कुछ बर्बाद कर देता है।

अक्सर जब हम HTML में महत्वपूर्ण परिवर्तन करते हैं, तो हम नई संरचना को ठीक से प्रतिबिंबित करने के लिए CSS और सामग्री और स्टाइल को बनाए रखने के लिए JavaScript दोनों को बदलते हैं। ये सभी संसाधन स्वतंत्र हैं, लेकिन कैशिंग हेडर इसे व्यक्त नहीं कर सकते। परिणामस्वरूप, उपयोगकर्ता स्वयं को पा सकते हैं नवीनतम संस्करणएक/दो संसाधन और बाकी का पुराना संस्करण।

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

उपयोगकर्ता के लिए, इसका परिणाम टूटा हुआ पृष्ठ लेआउट या अन्य समस्याएं हो सकता है। छोटी-मोटी गड़बड़ियों से लेकर पूरी तरह अनुपयोगी सामग्री तक।

सौभाग्य से, उपयोगकर्ताओं के पास आपातकालीन निकास है...

पृष्ठ को ताज़ा करने से कभी-कभी मदद मिलती है

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

एक सेवा कर्मी इन बगों का जीवन बढ़ा सकता है

उदाहरण के लिए, आपके पास इस तरह का एक सेवा कर्मी है:

स्थिरांक संस्करण = "2"; self.addEventListener("इंस्टॉल", इवेंट => ( इवेंट.waitUntil(caches.open(`static-$(version)`) .then(cache => कैशे.addAll([ "/styles.css", "/script .js" ]))); )); self.addEventListener("सक्रिय करें", इवेंट => ( // ...पुराने कैश हटाएं... )); self.addEventListener("fetch", इवेंट => ( इवेंट.रेस्पॉन्डविथ(caches.match(event.request) .then(response => प्रतिक्रिया || भ्रूण(इवेंट.request))); ));

यह सेवा कर्मी:

  • कैश स्क्रिप्ट और शैलियाँ
  • यदि कोई मेल है तो कैश का उपयोग करता है, अन्यथा नेटवर्क तक पहुंचता है

यदि हम सीएसएस/जेएस बदलते हैं, तो हम संस्करण संख्या भी बढ़ाते हैं, जो अपडेट को ट्रिगर करता है। हालाँकि, चूँकि addAll पहले कैश तक पहुँचता है, हम अधिकतम आयु और बेमेल CSS और JS संस्करणों के कारण दौड़ की स्थिति में आ सकते हैं।

एक बार जब वे कैश हो जाते हैं, तो हमारे पास अगले सर्विस वर्कर अपडेट तक असंगत सीएसएस और जेएस होंगे - और ऐसा तब तक होगा जब तक हम अपडेट के दौरान फिर से दौड़ की स्थिति में नहीं आ जाते।

आप सेवा कर्मी में कैशिंग छोड़ सकते हैं:

Self.addEventListener("इंस्टॉल", इवेंट => ( इवेंट.waitUntil(caches.open(`static-$(version)`) .then(cache => कैशे.addAll([ new Request("/styles.css", (कैश: "नो-कैश")), नया अनुरोध ("/स्क्रिप्ट.जेएस", (कैश: "नो-कैश")) ]))); ));

दुर्भाग्य से, कैशिंग के विकल्प क्रोम/ओपेरा में समर्थित नहीं हैं और इन्हें अभी फ़ायरफ़ॉक्स के रात्रिकालीन बिल्ड में जोड़ा गया है, लेकिन आप इसे स्वयं कर सकते हैं:

Self.addEventListener("इंस्टॉल", इवेंट => ( इवेंट.waitUntil(caches.open(`static-$(version)`) .then(cache => Promise.all([ "/styles.css", "/script .js" ].map(url => ( // कैश-बस्ट एक रैंडम क्वेरी स्ट्रिंग रिटर्न फ़ेच का उपयोग कर(`$(url)?$(Math.random())`).then(response => ( // असफल) 404, 500 आदि पर यदि (!response.ok) थ्रो एरर("ठीक नहीं"); कैश लौटाएं।पुट(url, प्रतिक्रिया); )) ))))); ));

इस उदाहरण में, मैं एक यादृच्छिक संख्या का उपयोग करके कैश को रीसेट कर रहा हूं, लेकिन आप आगे जा सकते हैं और निर्माण करते समय सामग्री का हैश जोड़ सकते हैं (यह sw-precache के समान है)। यह पहले पैटर्न का एक प्रकार का कार्यान्वयन है जावास्क्रिप्ट का उपयोग करना, लेकिन केवल सेवा कर्मी के साथ काम करता है, ब्राउज़र और सीडीएन के साथ नहीं।

सेवाकर्मी और HTTP कैश एक साथ बढ़िया काम करते हैं, उन्हें झगड़ने पर मजबूर न करें!

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

उचित कैशिंग हेडर किसी सेवा कर्मी को अपडेट करना भी बहुत आसान बना सकते हैं।

स्थिरांक संस्करण = "23"; self.addEventListener("इंस्टॉल", इवेंट => ( इवेंट.waitUntil(caches.open(`static-$(version)`) .then(cache => कैश.addAll([ "/", "/script-f93bca2c. js", "/styles-a837cb1e.css", "/cats-0e9a2ef4.jpg" ]))); ));

यहां मैंने रूट पेज को पैटर्न #2 (सर्वर-साइड पुनर्वैधीकरण) के साथ और अन्य सभी संसाधनों को पैटर्न #1 (अपरिवर्तनीय सामग्री) के साथ कैश किया है। प्रत्येक सर्विस वर्कर अपडेट के कारण रूट पेज पर एक अनुरोध आएगा, और अन्य सभी संसाधन केवल तभी लोड किए जाएंगे जब उनका यूआरएल बदल गया हो। यह अच्छा है क्योंकि यह ट्रैफ़िक बचाता है और प्रदर्शन में सुधार करता है, भले ही आप पिछले वाले से अपग्रेड कर रहे हों या बहुत पुराने से पुराना संस्करण.

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

सेवा कर्मी अस्थायी बैसाखी के बजाय वृद्धि के रूप में बेहतर काम करते हैं, इसलिए इससे लड़ने के बजाय कैश के साथ काम करें।

जब सावधानी से उपयोग किया जाता है, तो अधिकतम-आयु और परिवर्तनशील सामग्री बहुत अच्छी हो सकती है

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

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

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

जब सही ढंग से उपयोग किया जाता है, तो कैशिंग महत्वपूर्ण प्रदर्शन सुधार और बैंडविड्थ बचत प्रदान करता है। यदि आप आसानी से यूआरएल बदल सकते हैं, या सर्वर-साइड पुनर्वैधीकरण का उपयोग कर सकते हैं तो अपरिवर्तनीय सामग्री परोसें। यदि आप पर्याप्त साहसी हैं और आश्वस्त हैं कि आपकी सामग्री में ऐसी निर्भरताएँ नहीं हैं जो सिंक से बाहर हो सकती हैं, तो अधिकतम-आयु और परिवर्तनशील सामग्री को मिलाएं।

वेबसाइटों में परिवर्तन करते समय, हम अक्सर इस तथ्य का सामना करते हैं कि पृष्ठों, सीएसएस फ़ाइलों और स्क्रिप्ट (.js) की सामग्री ब्राउज़र द्वारा कैश की जाती है और काफी लंबे समय तक अपरिवर्तित रहती है। इससे यह तथ्य सामने आता है कि किए गए परिवर्तनों को सभी ब्राउज़रों में प्रतिबिंबित करने के लिए, ग्राहकों को F5 या Ctrl + F5 के जटिल संयोजनों का आदी बनाना आवश्यक है। और समय-समय पर इन्हें दबाते रहना सुनिश्चित करें।

यह प्रक्रिया काफी कठिन और असुविधाजनक है। बेशक, आप हर बार फ़ाइलों का नाम बदलकर स्थिति से बाहर निकल सकते हैं, लेकिन फिर से यह असुविधाजनक है।

हालाँकि, एक ऐसा तरीका है जो हमें उन्हीं नामों के साथ रहने और जरूरत पड़ने पर .css या .js फ़ाइलों की कैशिंग को रीसेट करने की अनुमति देगा। और Ctrl+F5 को हमेशा के लिए भूल जाइये।

लब्बोलुआब यह है कि हम अंत में अपनी .css या .js फ़ाइलों में एक छद्म पैरामीटर संलग्न करेंगे, जिसे हम समय-समय पर बदल देंगे, जिससे ब्राउज़र में कैश रीसेट हो जाएगा।

इस प्रकार, प्रवेश सोर्स कोडअब इस तरह दिखेगा:

जहां 186485 एक मनमाना संयोजन है जो उसी फ़ाइल को आउटपुट करेगा, लेकिन ब्राउज़र इसे नए के रूप में व्याख्या करता है, छद्म पैरामीटर के लिए धन्यवाद ?186485

अब, हर बार हमारे पैरामीटर की सभी घटनाओं को न बदलने के लिए, हम इसे एक PHP फ़ाइल में सेट करेंगे, जिसे हम उन सभी स्थानों से कनेक्ट करेंगे जिनकी हमें ज़रूरत है:



मित्रों को बताओ