प्रोडक्शन में सर्विस वर्कर

पोर्ट्रेट स्क्रीनशॉट

खास जानकारी

जानें कि हमने Google I/O 2015 वेब ऐप्लिकेशन को तेज़ और ऑफ़लाइन-पहले रखने के लिए सर्विस वर्कर लाइब्रेरी का इस्तेमाल कैसे किया.

खास जानकारी

इस साल के Google I/O 2015 वेब ऐप्लिकेशन को Google की डेवलपर रिलेशन टीम ने लिखा था. यह इंस्ट्रुमेंट में मौजूद हमारे दोस्तों के डिज़ाइन पर आधारित है, जिन्होंने शानदार ऑडियो/विज़ुअल प्रयोग लिखा था. हमारी टीम का मकसद यह पक्का करना था कि I/O वेब ऐप्लिकेशन (जिसे मैं इसके कोडनेम, IOWA से खेलता हूं) वह सब कुछ दिखा दे जो मॉडर्न वेब कर सकता है. हमारी ज़रूरी सुविधाओं की सूची में सबसे ऊपर, सबसे पहले ऑफ़लाइन अनुभव था.

अगर आपने इस साइट पर हाल ही में कोई भी अन्य लेख पढ़ा है, तो बिलकुल सर्विस वर्कर आपका सामना कर रहे हैं. आपको यह जानकर हैरानी नहीं होगी कि IOWA की ऑफ़लाइन सहायता उन पर बहुत ज़्यादा निर्भर है. IOWA की असल दुनिया की ज़रूरतों को ध्यान में रखते हुए, हमने दो अलग-अलग ऑफ़लाइन इस्तेमाल के उदाहरणों को मैनेज करने के लिए, दो लाइब्रेरी डेवलप की हैं: sw-precache, स्टैटिक रिसॉर्स को अपने-आप प्रीकैशिंग के लिए और दूसरी रनटाइम कैश मेमोरी और फ़ॉलबैक की रणनीतियों को मैनेज करने के लिए.sw-toolbox

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

sw-precache की मदद से प्रीकैश किया जा रहा है

IOWA के स्टैटिक संसाधन—इसके एचटीएमएल, JavaScript, सीएसएस, और इमेज—वेब ऐप्लिकेशन के लिए मुख्य शेल उपलब्ध कराते हैं. इन संसाधनों को कैश मेमोरी में सेव करने के बारे में सोचते समय इन दो ज़रूरी शर्तों को पूरा करना ज़रूरी था: हम यह पक्का करना चाहते थे कि ज़्यादातर स्टैटिक संसाधन कैश मेमोरी में सेव किए जाएं और उन्हें अप-टू-डेट रखा जाए. इन ज़रूरतों को ध्यान में रखकर sw-precache बनाया गया था.

बिल्ड-टाइम इंटिग्रेशन

sw-precache IOWA के gulp-आधारित बिल्ड प्रोसेस के साथ, और हम ग्लोब के स्टैटिक पैटर्न पर भरोसा करते हैं, ताकि यह पक्का किया जा सके कि हम सभी IO पैटर्न की पूरी सूची जनरेट करें

staticFileGlobs: [
    rootDir + '/bower_components/**/*.{html,js,css}',
    rootDir + '/elements/**',
    rootDir + '/fonts/**',
    rootDir + '/images/**',
    rootDir + '/scripts/**',
    rootDir + '/styles/**/*.css',
    rootDir + '/data-worker-scripts.js'
]

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

कैश मेमोरी में सेव किए गए संसाधन अपडेट किए जा रहे हैं

sw-precache एक बेस सर्विस वर्कर स्क्रिप्ट जनरेट करता है, जिसमें प्री-कैश किए गए हर संसाधन के लिए एक यूनीक एमडी5 हैश शामिल होता है. जब भी कोई मौजूदा संसाधन बदलता है या नया संसाधन जोड़ा जाता है, तब सर्विस वर्कर स्क्रिप्ट फिर से जनरेट होती है. इससे सर्विस वर्कर अपडेट फ़्लो अपने-आप ट्रिगर हो जाता है, जिसमें नए संसाधनों को कैश मेमोरी में सेव किया जाता है और पुराने संसाधनों को पूरी तरह मिटा दिया जाता है. एक जैसे एमडी5 हैश वाले सभी मौजूदा संसाधनों को ज्यों का त्यों छोड़ दिया जाता है. इसका मतलब है कि जो उपयोगकर्ता साइट पर पहले आए हैं वे बदले गए संसाधनों का कम से कम सेट डाउनलोड करते हैं. इस वजह से, पूरे कैश मेमोरी की समयसीमा एक साथ खत्म होने की तुलना में, ज़्यादा बेहतर अनुभव मिलता है.

किसी भी ग्लोब पैटर्न से मेल खाने वाली हर फ़ाइल, उपयोगकर्ता के पहली बार IOWA पर जाने पर डाउनलोड और कैश मेमोरी में सेव होती है. हमने यह पक्का करने की कोशिश की है कि पेज को रेंडर करने के लिए सिर्फ़ ज़रूरी संसाधन ही पहले से कैश मेमोरी में सेव किए गए हों. ऑडियो/विज़ुअल एक्सपेरिमेंट में इस्तेमाल किए गए मीडिया या सेशन के स्पीकर की प्रोफ़ाइल इमेज जैसे सेकंडरी कॉन्टेंट को जान-बूझकर पहले से कैश मेमोरी में सेव नहीं किया गया था. इसलिए, हमने sw-toolbox लाइब्रेरी का इस्तेमाल किया, ताकि इन संसाधनों के ऑफ़लाइन अनुरोधों को हैंडल किया जा सके.

sw-toolbox, हमारी सभी डाइनैमिक ज़रूरतों के लिए

जैसा कि बताया गया है, किसी साइट के लिए ऑफ़लाइन काम करने के लिए ज़रूरी हर संसाधन को पहले से कैश मेमोरी में सेव नहीं किया जा सकता. कुछ संसाधन बहुत बड़े होते हैं या इनका इस्तेमाल बहुत कम किया जाता है, ताकि आपके काम की जानकारी मिल सके. वहीं, अन्य संसाधन डाइनैमिक होते हैं, जैसे कि किसी रिमोट एपीआई या सेवा से मिलने वाले जवाब. हालांकि, अगर किसी अनुरोध के लिए पहले से कैश मेमोरी में डेटा सेव नहीं किया गया है, तो इसका मतलब यह नहीं है कि अनुरोध की वजह से NetworkError ट्रिगर हो जाएगा. sw-toolbox ने हमें अनुरोध हैंडलर लागू करने की सुविधा दी है. यह सुविधा कुछ संसाधनों के लिए रनटाइम को कैश मेमोरी में सेव करने और दूसरों के लिए कस्टम फ़ॉलबैक मैनेज करती है. हमने इसका इस्तेमाल, पहले से कैश मेमोरी में सेव किए गए संसाधनों को, पुश नोटिफ़िकेशन के तौर पर अपडेट करने के लिए भी किया था.

यहां कस्टम अनुरोध हैंडलर के कुछ उदाहरण दिए गए हैं, जिन्हें हमने sw-टूलबॉक्स के ऊपर बनाया है. sw-precache के importScripts parameter की मदद से, उन्हें बेस सर्विस वर्कर स्क्रिप्ट के साथ इंटिग्रेट करना आसान था. यह स्टैंडअलोन JavaScript फ़ाइलों को सर्विस वर्कर के दायरे में ले आता है.

ऑडियो/विज़ुअल से जुड़ा प्रयोग

ऑडियो/विज़ुअल प्रयोग के लिए, हमने sw-toolbox की networkFirst कैश मेमोरी में सेव करने की रणनीति का इस्तेमाल किया है. प्रयोग के यूआरएल पैटर्न से मेल खाने वाले सभी एचटीटीपी अनुरोध, सबसे पहले नेटवर्क के लिए किए जाएंगे. अगर रिस्पॉन्स मिलता है, तो कैश मेमोरी एपीआई का इस्तेमाल करके उस रिस्पॉन्स को बंद कर दिया जाएगा. अगर नेटवर्क उपलब्ध न होने पर बाद में कोई अनुरोध किया जाता है, तो पहले से कैश मेमोरी में सेव किए गए रिस्पॉन्स का इस्तेमाल किया जाएगा.

हर बार एक सफल नेटवर्क रिस्पॉन्स मिलने पर, कैश मेमोरी अपने-आप अपडेट हो जाती है. इसलिए, हमें संसाधनों को अलग-अलग वर्शन बनाने या एंट्री की समयसीमा खत्म होने की ज़रूरत नहीं थी.

toolbox.router.get('/experiment/(.+)', toolbox.networkFirst);

स्पीकर प्रोफ़ाइल इमेज

स्पीकर प्रोफ़ाइल इमेज के लिए, हमारा मकसद, स्पीकर की इमेज उपलब्ध होने पर, उसका पहले से कैश किया गया वर्शन दिखाना था. अगर ऐसा नहीं होता, तो उसे फिर से पाने के लिए नेटवर्क पर वापस आ जाता था. अगर नेटवर्क का वह अनुरोध पूरा नहीं हो पाता है, तो हमने एक जेनरिक प्लेसहोल्डर इमेज का इस्तेमाल किया. इस इमेज को पहले से कैश मेमोरी में सेव किया गया था. इसलिए, यह इमेज हमेशा उपलब्ध रहेगी. यह ऐसी इमेज इस्तेमाल करते समय इस्तेमाल की जाने वाली एक सामान्य रणनीति है जिसे किसी जेनरिक प्लेसहोल्डर से बदला जा सकता है. साथ ही, इसे sw-toolbox के cacheFirst और cacheOnly हैंडलर की चेन से लागू करना आसान था.

var DEFAULT_PROFILE_IMAGE = 'images/touch/homescreen96.png';

function profileImageRequest(request) {
    return toolbox.cacheFirst(request).catch(function() {
    return toolbox.cacheOnly(new Request(DEFAULT_PROFILE_IMAGE));
    });
}

toolbox.precache([DEFAULT_PROFILE_IMAGE]);
toolbox.router.get('/(.+)/images/speakers/(.*)',
                    profileImageRequest,
                    {origin: /.*\.googleapis\.com/});
किसी सेशन के पेज की प्रोफ़ाइल इमेज
किसी सेशन पेज से प्रोफ़ाइल इमेज.

लोगों के शेड्यूल में अपडेट

IOWA की एक मुख्य सुविधा, साइन-इन किए हुए उपयोगकर्ताओं को उन सेशन का शेड्यूल बनाने और उसे बनाए रखने की अनुमति देना है जिनमें वे हिस्सा लेने वाले थे. जैसा कि आपको उम्मीद थी, सेशन के अपडेट, बैकएंड सर्वर पर एचटीटीपी POST अनुरोधों के ज़रिए किए गए थे. साथ ही, उपयोगकर्ता के ऑफ़लाइन होने पर, स्थिति में बदलाव करने के उन अनुरोधों को मैनेज करने के लिए, हमने कुछ समय लगाया. हमने IndexedDB में पूरे न हो पाने वाले अनुरोधों को सूची में शामिल किया है. साथ ही, मुख्य वेब पेज के लॉजिक के साथ सूची में शामिल अनुरोधों के लिए IndexedDB की जांच की गई है. साथ ही, मिले अनुरोधों को फिर से करने की कोशिश की है.

var DB_NAME = 'shed-offline-session-updates';

function queueFailedSessionUpdateRequest(request) {
    simpleDB.open(DB_NAME).then(function(db) {
    db.set(request.url, request.method);
    });
}

function handleSessionUpdateRequest(request) {
    return global.fetch(request).then(function(response) {
    if (response.status >= 500) {
        return Response.error();
    }
    return response;
    }).catch(function() {
    queueFailedSessionUpdateRequest(request);
    });
}

toolbox.router.put('/(.+)api/v1/user/schedule/(.+)',
                    handleSessionUpdateRequest);
toolbox.router.delete('/(.+)api/v1/user/schedule/(.+)',
                        handleSessionUpdateRequest);

ये कोशिश मुख्य पेज के संदर्भ से की गई हैं. इसलिए, हम यह पक्का कर सकते हैं कि इनमें उपयोगकर्ता क्रेडेंशियल का नया सेट शामिल हो. फिर से कोशिश करने पर, हमने एक मैसेज दिखाया. इसमें उपयोगकर्ता को बताया जाता है कि सूची में पहले से जोड़े गए अपडेट लागू कर दिए गए हैं.

simpleDB.open(QUEUED_SESSION_UPDATES_DB_NAME).then(function(db) {
    var replayPromises = [];
    return db.forEach(function(url, method) {
    var promise = IOWA.Request.xhrPromise(method, url, true).then(function() {
        return db.delete(url).then(function() {
        return true;
        });
    });
    replayPromises.push(promise);
    }).then(function() {
    if (replayPromises.length) {
        return Promise.all(replayPromises).then(function() {
        IOWA.Elements.Toast.showMessage(
            'My Schedule was updated with offline changes.');
        });
    }
    });
}).catch(function() {
    IOWA.Elements.Toast.showMessage(
    'Offline changes could not be applied to My Schedule.');
});

ऑफ़लाइन Google Analytics

इसी तरह, हमने एक हैंडलर भी लागू किया, ताकि Google Analytics के फ़ेल हो चुके अनुरोधों की सूची बनाई जा सके. साथ ही, नेटवर्क के उपलब्ध होने पर, उन्हें बाद में फिर से चलाने की कोशिश की जाए. इस तरीके से, ऑफ़लाइन होने का मतलब यह नहीं है कि Google Analytics से मिलने वाली अहम जानकारी से समझौता कर लिया जाए. हमने सूची में शामिल हर अनुरोध में qt पैरामीटर जोड़ा है. इसे पहली बार अनुरोध किए जाने के बाद बीत चुके समय पर सेट किया जाता है. इससे यह पक्का किया जाता है कि Google Analytics बैकएंड को इवेंट एट्रिब्यूशन का सही समय मिले. Google Analytics केवल 4 घंटे तक के qt के मानों को आधिकारिक रूप से समर्थन करता है, इसलिए हमने हर बार सर्विस वर्कर के शुरू होने पर, उन अनुरोधों को जल्द से जल्द दोबारा चलाने की कोशिश की.

var DB_NAME = 'offline-analytics';
var EXPIRATION_TIME_DELTA = 86400000;
var ORIGIN = /https?:\/\/((www|ssl)\.)?google-analytics\.com/;

function replayQueuedAnalyticsRequests() {
    simpleDB.open(DB_NAME).then(function(db) {
    db.forEach(function(url, originalTimestamp) {
        var timeDelta = Date.now() - originalTimestamp;
        var replayUrl = url + '&qt=' + timeDelta;
        fetch(replayUrl).then(function(response) {
        if (response.status >= 500) {
            return Response.error();
        }
        db.delete(url);
        }).catch(function(error) {
        if (timeDelta > EXPIRATION_TIME_DELTA) {
            db.delete(url);
        }
        });
    });
    });
}

function queueFailedAnalyticsRequest(request) {
    simpleDB.open(DB_NAME).then(function(db) {
    db.set(request.url, Date.now());
    });
}

function handleAnalyticsCollectionRequest(request) {
    return global.fetch(request).then(function(response) {
    if (response.status >= 500) {
        return Response.error();
    }
    return response;
    }).catch(function() {
    queueFailedAnalyticsRequest(request);
    });
}

toolbox.router.get('/collect',
                    handleAnalyticsCollectionRequest,
                    {origin: ORIGIN});
toolbox.router.get('/analytics.js',
                    toolbox.networkFirst,
                    {origin: ORIGIN});

replayQueuedAnalyticsRequests();

पुश नोटिफ़िकेशन के लैंडिंग पेज

सर्विस वर्कर, सिर्फ़ IOWA के ऑफ़लाइन फ़ंक्शन को मैनेज नहीं करते, बल्कि उन्होंने पुश नोटिफ़िकेशन भी चलाए. इनका इस्तेमाल हम उपयोगकर्ताओं को उनके बुकमार्क किए गए सेशन के अपडेट के बारे में सूचना देने के लिए करते थे. इन सूचनाओं से जुड़े लैंडिंग पेज पर, सेशन की अपडेट की गई जानकारी दिखती है. उन लैंडिंग पेजों को पूरी साइट के हिस्से के तौर पर पहले ही कैश मेमोरी में सेव किया जा रहा था. इसलिए, वे ऑफ़लाइन भी काम कर रहे थे. हालांकि, हमें यह पक्का करना था कि ऑफ़लाइन देखे जाने पर भी उस पेज पर मौजूद सेशन की जानकारी अप-टू-डेट हो. ऐसा करने के लिए, हमने पुश नोटिफ़िकेशन को ट्रिगर करने वाले अपडेट के साथ, पहले से कैश मेमोरी में सेव किए गए सेशन के मेटाडेटा में बदलाव किया था और नतीजे को कैश मेमोरी में सेव किया था. अगली बार सेशन की ज़्यादा जानकारी वाला पेज खोलने पर, इस अप-टू-डेट जानकारी का इस्तेमाल किया जाएगा. भले ही, यह जानकारी ऑनलाइन हो या ऑफ़लाइन.

caches.open(toolbox.options.cacheName).then(function(cache) {
    cache.match('api/v1/schedule').then(function(response) {
    if (response) {
        parseResponseJSON(response).then(function(schedule) {
        sessions.forEach(function(session) {
            schedule.sessions[session.id] = session;
        });
        cache.put('api/v1/schedule',
                    new Response(JSON.stringify(schedule)));
        });
    } else {
        toolbox.cache('api/v1/schedule');
    }
    });
});

गॉचा और ध्यान देने लायक बातें

बेशक, कोई भी IOWA के स्केल के प्रोजेक्ट पर काम नहीं करता. ऐसा करने के लिए, कई चीज़ें इकट्ठा नहीं की जातीं. यहां कुछ ऐसे प्रोजेक्ट दिए गए हैं जिनका हमने सामना किया और उन पर हमने कैसे काम किया.

पुराना कॉन्टेंट

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

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

if (navigator.serviceWorker && navigator.serviceWorker.controller) {
    navigator.serviceWorker.controller.onstatechange = function(e) {
    if (e.target.state === 'redundant') {
        var tapHandler = function() {
        window.location.reload();
        };
        IOWA.Elements.Toast.showMessage(
        'Tap here or refresh the page for the latest content.',
        tapHandler);
    }
    };
}
नया कॉन्टेंट टोस्ट
"सबसे नया कॉन्टेंट" टोस्ट.

पक्का करें कि स्टैटिक कॉन्टेंट स्टैटिक हो!

sw-precache, लोकल फ़ाइलों के कॉन्टेंट के MD5 हैश का इस्तेमाल करता है. साथ ही, यह सिर्फ़ उन संसाधनों को फ़ेच करता है जिनका हैश बदला गया है. इसका मतलब यह है कि पेज पर रिसॉर्स तुरंत उपलब्ध हो जाते हैं. हालांकि, इसका मतलब यह भी है कि एक बार किसी पेज को कैश मेमोरी में सेव कर देने के बाद, वह तब तक कैश मेमोरी में सेव रहता है, जब तक कि उसे अपडेट की गई सर्विस वर्कर स्क्रिप्ट में नया हैश असाइन नहीं किया जाता.

हमें I/O के दौरान इस व्यवहार में समस्या हुई, क्योंकि हमारे बैकएंड को कॉन्फ़्रेंस के हर दिन के लिए, लाइव स्ट्रीम के YouTube वीडियो आईडी डाइनैमिक तौर पर अपडेट करने की ज़रूरत थी. मुख्य टेंप्लेट फ़ाइल स्टैटिक थी और बदली नहीं गई थी. इसलिए, हमारे सर्विस वर्कर के अपडेट का फ़्लो ट्रिगर नहीं हुआ. साथ ही, YouTube वीडियो को अपडेट करके, सर्वर से डाइनैमिक रिस्पॉन्स मिलने की वजह से, कई लोगों को कैश मेमोरी में सेव किया गया रिस्पॉन्स मिला.

इस तरह की समस्या से बचने के लिए, यह पक्का करें कि आपका वेब ऐप्लिकेशन इस तरह से डिज़ाइन किया गया हो कि शेल हमेशा स्टैटिक रहे और सुरक्षित तरीके से पहले से कैश मेमोरी में सेव किया जा सके. वहीं दूसरी ओर, शेल में बदलाव करने वाले कोई भी डाइनैमिक रिसॉर्स अलग से लोड किए जाते हैं.

प्रीकैशिंग के आपके अनुरोधों को कैश मेमोरी में सेव करने की सुविधा

जब sw-precache, रिसॉर्स को प्री-कैश करने के लिए अनुरोध करता है, तो वह उन रिस्पॉन्स का हमेशा के लिए इस्तेमाल करता है. ऐसा तब तक किया जाता है, जब तक उसे लगता है कि फ़ाइल का MD5 हैश नहीं बदला है. इसका मतलब है कि इस बात का ध्यान रखना ज़रूरी है कि पहले से कैश मेमोरी में सेव किए गए अनुरोध का रिस्पॉन्स नया हो और उसे ब्राउज़र के एचटीटीपी कैश से न दिखाया गया हो. (हां, सर्विस वर्कर में किए गए fetch() अनुरोध, ब्राउज़र की एचटीटीपी कैश मेमोरी के डेटा के साथ जवाब दे सकते हैं.)

यह पक्का करने के लिए कि हम पहले से कैश मेमोरी में सेव किए गए जवाब सीधे नेटवर्क से पाएं, न कि ब्राउज़र की एचटीटीपी कैश मेमोरी से. इसके लिए, sw-precache अनुरोध किए गए हर यूआरएल में, कैश मेमोरी में सेव होने वाला क्वेरी पैरामीटर अपने-आप जोड़ता है. अगर sw-precache का इस्तेमाल नहीं किया जा रहा है और कैश-फ़र्स्ट रिस्पॉन्स रणनीति का इस्तेमाल किया जा रहा है, तो पक्का करें कि आप अपने कोड में ऐसा ही कुछ करें!

कैश बस्टिंग का एक बेहतर समाधान यह है कि प्रीकैशिंग के लिए इस्तेमाल किए जाने वाले हर Request के कैश मोड को reload पर सेट किया जाए. इससे यह पक्का होगा कि रिस्पॉन्स नेटवर्क से मिले. हालांकि, फ़िलहाल Chrome में कैश मोड का विकल्प मौजूद नहीं है.

लॉग इन और आउट करने के लिए सहायता

IOWA ने उपयोगकर्ताओं को अपने Google खातों का इस्तेमाल करके लॉग इन करने और पसंद के मुताबिक इवेंट के शेड्यूल अपडेट करने की अनुमति दी. इसका मतलब यह भी था कि उपयोगकर्ता बाद में लॉग आउट कर सकते हैं. लोगों के हिसाब से तैयार किए गए जवाब का डेटा कैश मेमोरी में सेव करना निश्चित तौर पर एक मुश्किल विषय है. हालांकि, ऐसा हमेशा एक ही तरीका नहीं होता है.

ऑफ़लाइन होने पर भी अपना निजी शेड्यूल देखना, IOWA अनुभव का अहम हिस्सा था. इसलिए, हमने तय किया कि कैश मेमोरी में सेव किए गए डेटा का इस्तेमाल करना सही है. जब कोई उपयोगकर्ता साइन आउट करता है, तो हमने पक्का कर लिया है कि पहले से कैश मेमोरी में सेव किए गए सेशन का डेटा मिटा दिया जाए.

    self.addEventListener('message', function(event) {
      if (event.data === 'clear-cached-user-data') {
        caches.open(toolbox.options.cacheName).then(function(cache) {
          cache.keys().then(function(requests) {
            return requests.filter(function(request) {
              return request.url.indexOf('api/v1/user/') !== -1;
            });
          }).then(function(userDataRequests) {
            userDataRequests.forEach(function(userDataRequest) {
              cache.delete(userDataRequest);
            });
          });
        });
      }
    });

अतिरिक्त क्वेरी पैरामीटर के लिए सावधान रहें!

जब कोई सर्विस वर्कर, कैश मेमोरी में सेव किए गए किसी रिस्पॉन्स की जांच करता है, तो वह अनुरोध यूआरएल को कुंजी के तौर पर इस्तेमाल करता है. डिफ़ॉल्ट रूप से, अनुरोध का यूआरएल, कैश मेमोरी में सेव किए गए रिस्पॉन्स को स्टोर करने के लिए इस्तेमाल किए जाने वाले यूआरएल से पूरी तरह मेल खाना चाहिए. इसमें, यूआरएल के खोज वाले हिस्से में मौजूद सभी क्वेरी पैरामीटर भी शामिल हैं.

इसकी वजह से डेवलपमेंट के दौरान हमें एक समस्या हुई, जब हमने यह ट्रैक करने के लिए यूआरएल पैरामीटर का इस्तेमाल करना शुरू किया कि हमारे ट्रैफ़िक कहां से आ रहा है. उदाहरण के लिए, हमने उन यूआरएल में utm_source=notification पैरामीटर जोड़ा जो हमारी किसी सूचना पर क्लिक करने पर खोले गए थे और हमारे वेब ऐप्लिकेशन मेनिफ़ेस्ट के लिए, start_url में utm_source=web_app_manifest का इस्तेमाल किया गया था. जिन यूआरएल को कैश मेमोरी में सेव किए गए जवाबों से पहले मैच किया गया था वे पैरामीटर जोड़ने पर वे यूआरएल मिस थे.

यह कुछ हद तक ignoreSearch विकल्प से ठीक किया जाता है. इसका इस्तेमाल Cache.match() को कॉल करते समय किया जा सकता है. माफ़ करें, Chrome, ignoreSearch के साथ काम अभी तक नहीं किया जा सकता. भले ही, ऐसा हुआ हो, लेकिन इसका स्टेटस कुछ भी नहीं है. हमें एक ऐसे तरीके की ज़रूरत थी जिससे कुछ यूआरएल क्वेरी पैरामीटर को अनदेखा किया जा सके और दूसरे क्वेरी पैरामीटर को शामिल न किया जा सके.

हमने sw-precache को बढ़ाया है, ताकि कैश मेमोरी के मिलान की जांच करने से पहले ही कुछ क्वेरी पैरामीटर हटा दिए जा सकें. साथ ही, इसकी मदद से डेवलपर यह तय कर सकते हैं कि ignoreUrlParametersMatching विकल्प की मदद से कौनसे पैरामीटर को अनदेखा किया जाए. बुनियादी तौर पर इसे लागू किया गया है:

function stripIgnoredUrlParameters(originalUrl, ignoredRegexes) {
    var url = new URL(originalUrl);

    url.search = url.search.slice(1)
    .split('&')
    .map(function(kv) {
        return kv.split('=');
    })
    .filter(function(kv) {
        return ignoredRegexes.every(function(ignoredRegex) {
        return !ignoredRegex.test(kv[0]);
        });
    })
    .map(function(kv) {
        return kv.join('=');
    })
    .join('&');

    return url.toString();
}

आपके लिए इसके क्या मायने हैं

Google I/O वेब ऐप्लिकेशन में सर्विस वर्कर इंटिग्रेशन, इस पॉइंट पर डिप्लॉय किया गया सबसे मुश्किल और असल दुनिया का इस्तेमाल होता है. हम वेब डेवलपर समुदाय के लिए, हमारे बनाए गए टूल sw-precache और sw-toolbox के साथ-साथ उन तकनीकों का इस्तेमाल करना चाहते हैं जिनके बारे में हम बात कर रहे हैं, ताकि आप अपने वेब ऐप्लिकेशन को बेहतर बना सकें. सर्विस वर्कर, बेहतर तरीके से काम करने की सुविधा है, जिसका इस्तेमाल आज से ही शुरू किया जा सकता है. अगर इसे सही तरीके से बनाए गए वेब ऐप्लिकेशन के हिस्से के तौर पर इस्तेमाल किया जाए, तो इसकी स्पीड और ऑफ़लाइन इस्तेमाल से आपके उपयोगकर्ताओं को काफ़ी फ़ायदा मिलेगा.