हमने डेवलपर को सर्विस वर्कर की मदद से, नेटवर्क कनेक्शन की समस्या हल करने का तरीका दिया. आपको कैश मेमोरी और अनुरोधों को मैनेज करने का कंट्रोल मिलता है. इसका मतलब है कि आपको अपने पैटर्न बनाने का विकल्प मिलता है. यहां कुछ संभावित पैटर्न दिए गए हैं. हालांकि, व्यवहार में आपको यूआरएल और कॉन्टेक्स्ट के हिसाब से, इनका एक साथ इस्तेमाल करना पड़ सकता है.
इनमें से कुछ पैटर्न का डेमो देखने के लिए, Trained-to-thrill देखें.
संसाधन कब सेव किए जाते हैं
सर्विस वर्कर की मदद से, कैश मेमोरी से अलग अनुरोधों को हैंडल किया जा सकता है. इसलिए, मैं इन्हें अलग से दिखाऊंगा. सबसे पहले, यह तय करना कि आपको कैश मेमोरी का इस्तेमाल कब करना चाहिए.
इंस्टॉल करने पर, डिपेंडेंसी के तौर पर
Service Worker API आपको install इवेंट देता है. इसका इस्तेमाल, इवेंट से पहले की जाने वाली ज़रूरी कार्रवाइयों को पूरा करने के लिए किया जा सकता है. install के दौरान, आपके सर्विस वर्कर के पिछले वर्शन काम करते रहते हैं और पेजों को सेवा देते रहते हैं. इस दौरान, आपको ऐसा कुछ नहीं करना चाहिए जिससे मौजूदा सर्विस वर्कर में रुकावट आए.
इनके लिए सबसे सही है: सीएसएस, इमेज, फ़ॉन्ट, JS, टेंप्लेट या कोई भी ऐसी चीज़ जिसे आपको अपनी साइट के उस वर्शन के लिए स्टैटिक मानना है.
उन चीज़ों को फ़ेच करें जिन्हें फ़ेच न करने पर, आपकी साइट पूरी तरह से काम नहीं करेगी. साथ ही, उन चीज़ों को फ़ेच करें जिन्हें किसी प्लैटफ़ॉर्म के हिसाब से बनाए गए ऐप्लिकेशन के शुरुआती डाउनलोड में शामिल किया जाता है.
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open('mysite-static-v3').then(function (cache) {
return cache.addAll([
'/css/whatever-v3.css',
'/css/imgs/sprites-v6.png',
'/css/fonts/whatever-v8.woff',
'/js/all-min-v4.js',
// etc.
]);
}),
);
});
event.waitUntil, इंस्टॉल करने की अवधि और उसकी सफलता के बारे में जानकारी देने के लिए प्रॉमिस लेता है. अगर प्रॉमिस अस्वीकार कर दिया जाता है, तो इंस्टॉलेशन को फ़ेल माना जाता है. साथ ही, इस सर्विस वर्कर को बंद कर दिया जाता है. अगर कोई पुराना वर्शन चल रहा है, तो उसे बंद नहीं किया जाएगा. caches.open() और cache.addAll() लौटाने के वादे.
अगर कोई संसाधन फ़ेच नहीं किया जा सका, तो cache.addAll() कॉल अस्वीकार कर देता है.
मैं trained-to-thrill पर इसका इस्तेमाल स्टैटिक ऐसेट को कैश मेमोरी में सेव करने के लिए करता हूं.
इंस्टॉल करने पर, डिपेंडेंसी के तौर पर नहीं
यह किसी डिपेंडेंसी के तौर पर इंस्टॉल करने जैसा ही है. हालांकि, इससे इंस्टॉल पूरा होने में देरी नहीं होगी. साथ ही, अगर कैश मेमोरी काम नहीं करती है, तो इंस्टॉल करने की प्रोसेस फ़ेल नहीं होगी.
इनके लिए सबसे सही है: बड़े संसाधन जिनकी तुरंत ज़रूरत नहीं होती. जैसे, गेम के बाद के लेवल के लिए ऐसेट.
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open('mygame-core-v1').then(function (cache) {
cache
.addAll
// levels 11-20
();
return cache
.addAll
// core assets and levels 1-10
();
}),
);
});
इस उदाहरण में, cache.addAll ने लेवल 11 से 20 तक के लिए event.waitUntil से किया गया वादा पूरा नहीं किया है. इसलिए, अगर यह उदाहरण काम नहीं करता है, तो भी गेम ऑफ़लाइन उपलब्ध रहेगा. ज़ाहिर है, आपको उन लेवल के मौजूद न होने की संभावना को ध्यान में रखना होगा. साथ ही, अगर वे मौजूद नहीं हैं, तो उन्हें फिर से कैश मेमोरी में सेव करने की कोशिश करनी होगी.
लेवल 11 से 20 डाउनलोड करते समय, सर्विस वर्कर बंद हो सकता है. ऐसा इसलिए, क्योंकि वह इवेंट मैनेज करने का काम पूरा कर चुका है. इसका मतलब है कि उन्हें कैश मेमोरी में सेव नहीं किया जाएगा. Web Periodic Background Synchronization API इस तरह के मामलों को हैंडल कर सकता है. साथ ही, यह फ़िल्मों जैसे बड़े डाउनलोड को भी हैंडल कर सकता है.
चालू करने पर
इनके लिए सबसे सही है: डेटा को व्यवस्थित करना और माइग्रेट करना.
जब नया सर्विस वर्कर इंस्टॉल हो जाता है और पिछले वर्शन का इस्तेमाल नहीं किया जा रहा होता है, तब नया सर्विस वर्कर चालू हो जाता है. इसके बाद, आपको activate इवेंट मिलता है. पिछला वर्शन बंद हो गया है. इसलिए, यह IndexedDB में स्कीमा माइग्रेशन को मैनेज करने और इस्तेमाल न की गई कैश मेमोरी को मिटाने का सही समय है.
self.addEventListener('activate', function (event) {
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames
.filter(function (cacheName) {
// Return true if you want to remove this cache,
// but remember that caches are shared across
// the whole origin
})
.map(function (cacheName) {
return caches.delete(cacheName);
}),
);
}),
);
});
ऐक्टिवेशन के दौरान, fetch जैसे इवेंट को एक कतार में रखा जाता है. इसलिए, ऐक्टिवेशन में ज़्यादा समय लगने से पेज लोड होने में समस्या आ सकती है. इसे कम से कम समय के लिए चालू रखें. साथ ही, इसका इस्तेमाल सिर्फ़ उन कामों के लिए करें जो पिछले वर्शन के चालू होने पर नहीं किए जा सकते थे.
मैं trained-to-thrill पर इसका इस्तेमाल, पुरानी कैश मेमोरी हटाने के लिए करता हूं.
उपयोगकर्ता के इंटरैक्शन पर
इनके लिए सबसे सही: जब पूरी साइट को ऑफ़लाइन नहीं किया जा सकता और आपने उपयोगकर्ता को वह कॉन्टेंट चुनने की अनुमति दी है जिसे उसे ऑफ़लाइन उपलब्ध कराना है. उदाहरण के लिए, YouTube पर मौजूद कोई वीडियो, Wikipedia पर मौजूद कोई लेख या Flickr पर मौजूद कोई गैलरी.
उपयोगकर्ता को "बाद में पढ़ें" या "ऑफ़लाइन के लिए सेव करें" बटन दें. इस पर क्लिक करने पर, नेटवर्क से आपकी ज़रूरत की जानकारी फ़ेच की जाती है और उसे कैश मेमोरी में सेव किया जाता है.
document.querySelector('.cache-article').addEventListener('click', function (event) {
event.preventDefault();
var id = this.dataset.articleId;
caches.open('mysite-article-' + id).then(function (cache) {
fetch('/get-article-urls?id=' + id)
.then(function (response) {
// /get-article-urls returns a JSON-encoded array of
// resource URLs that a given article depends on
return response.json();
})
.then(function (urls) {
cache.addAll(urls);
});
});
});
Cache API, पेजों और सर्विस वर्कर के लिए उपलब्ध है. इसका मतलब है कि पेज से सीधे कैश मेमोरी में डेटा जोड़ा जा सकता है.
नेटवर्क रिस्पॉन्स पर
इसके लिए सबसे सही है: ऐसे संसाधनों को बार-बार अपडेट करना जो अक्सर बदलते रहते हैं. जैसे, किसी उपयोगकर्ता का इनबॉक्स या लेख का कॉन्टेंट. यह अवतार जैसे ग़ैर-ज़रूरी कॉन्टेंट के लिए भी काम का है. हालांकि, इसका इस्तेमाल सावधानी से करना चाहिए.
अगर कोई अनुरोध, कैश मेमोरी में मौजूद किसी भी आइटम से मेल नहीं खाता है, तो उसे नेटवर्क से पाएं, उसे पेज पर भेजें, और उसे कैश मेमोरी में जोड़ें.
अगर आपको कई यूआरएल के लिए ऐसा करना है, जैसे कि अवतार, तो आपको यह ध्यान रखना होगा कि इससे आपके ऑरिजिन का स्टोरेज न बढ़े. अगर उपयोगकर्ता को डिस्क स्पेस वापस पाना है, तो आपको मुख्य उम्मीदवार नहीं बनना चाहिए. पक्का करें कि आपने कैश मेमोरी में मौजूद उन आइटम को हटा दिया हो जिनकी अब आपको ज़रूरत नहीं है.
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.open('mysite-dynamic').then(function (cache) {
return cache.match(event.request).then(function (response) {
return (
response ||
fetch(event.request).then(function (response) {
cache.put(event.request, response.clone());