बैकग्राउंड या इवेंट पेजों को सर्विस वर्कर से बदलना
सर्विस वर्कर, एक्सटेंशन के बैकग्राउंड या इवेंट पेज की जगह ले लेता है, ताकि बैकग्राउंड कोड मुख्य थ्रेड से दूर रहे. इससे, एक्सटेंशन सिर्फ़ तब चल पाते हैं, जब उनकी ज़रूरत होती है. इससे संसाधनों की बचत होती है.
एक्सटेंशन के लॉन्च होने से ही, बैकग्राउंड पेज उनके लिए एक ज़रूरी कॉम्पोनेंट रहे हैं. आसान शब्दों में कहें, तो बैकग्राउंड पेज ऐसा प्लैटफ़ॉर्म उपलब्ध कराते हैं जो किसी भी अन्य विंडो या टैब से अलग होता है. इससे एक्सटेंशन, इवेंट को मॉनिटर कर सकते हैं और उनके हिसाब से कार्रवाई कर सकते हैं.
इस पेज पर, बैकग्राउंड पेजों को एक्सटेंशन सेवा वर्कर्स में बदलने के टास्क के बारे में बताया गया है. एक्सटेंशन के लिए सर्विस वर्कर के बारे में ज़्यादा जानने के लिए, सर्विस वर्कर की मदद से इवेंट मैनेज करना ट्यूटोरियल और एक्सटेंशन के लिए सर्विस वर्कर के बारे में जानकारी सेक्शन देखें.
बैकग्राउंड स्क्रिप्ट और एक्सटेंशन सेवा वर्कर्स के बीच अंतर
कुछ संदर्भों में, आपको एक्सटेंशन सेवा वर्कर्स 'बैकग्राउंड स्क्रिप्ट' के तौर पर दिखेंगे. एक्सटेंशन सर्विस वर्कर, बैकग्राउंड में काम करते हैं. हालांकि, उन्हें बैकग्राउंड स्क्रिप्ट कहना कुछ हद तक गुमराह करने वाला है. ऐसा इसलिए, क्योंकि इनमें एक जैसी सुविधाएं होती हैं. इन दोनों के बीच के फ़र्क़ के बारे में यहां बताया गया है.
बैकग्राउंड पेजों में हुए बदलाव
बैकग्राउंड पेजों की तुलना में, सेवा वर्कर में कई अंतर होते हैं.
- ये मुख्य थ्रेड से अलग काम करते हैं. इसका मतलब है कि ये एक्सटेंशन के कॉन्टेंट में रुकावट नहीं डालते.
- इनमें खास सुविधाएं होती हैं. जैसे, एक्सटेंशन के ऑरिजिन पर फ़ेच इवेंट को इंटरसेप्ट करना. जैसे, टूलबार पॉप-अप से आने वाले इवेंट.
- वे क्लाइंट इंटरफ़ेस की मदद से, दूसरे कॉन्टेक्स्ट के साथ बातचीत कर सकते हैं और इंटरैक्ट कर सकते हैं.
आपको ये बदलाव करने होंगे
बैकग्राउंड स्क्रिप्ट और सेवा वर्कर के काम करने के तरीके में अंतर के हिसाब से, आपको कोड में कुछ बदलाव करने होंगे. सबसे पहले, मेनिफ़ेस्ट फ़ाइल में सर्विस वर्कर के बारे में बताने का तरीका, बैकग्राउंड स्क्रिप्ट के बारे में बताने के तरीके से अलग है. इसके अलावा:
- ये कॉल, डीओएम या
window
इंटरफ़ेस को ऐक्सेस नहीं कर सकते. इसलिए, आपको ऐसे कॉल को किसी दूसरे एपीआई या ऑफ़स्क्रीन दस्तावेज़ में ले जाना होगा. - इवेंट के कॉलबैक में या रिटर्न किए गए प्रॉमिस के जवाब में, इवेंट लिसनर रजिस्टर नहीं किए जाने चाहिए.
- ये
XMLHttpRequest()
के साथ काम नहीं करते. इसलिए, आपको इस इंटरफ़ेस के कॉल कोfetch()
के कॉल से बदलना होगा. - इस्तेमाल में न होने पर ये वैरिएबल बंद हो जाते हैं. इसलिए, आपको ग्लोबल वैरिएबल के बजाय, ऐप्लिकेशन की स्थितियों को सेव करके रखना होगा. सेवा वर्कर को बंद करने पर, टाइमर भी समय पूरा होने से पहले खत्म हो सकते हैं. आपको उन्हें अलार्म से बदलना होगा.
इस पेज पर इन टास्क के बारे में पूरी जानकारी दी गई है.
मेनिफ़ेस्ट में "background" फ़ील्ड को अपडेट करना
मेनिफ़ेस्ट V3 में, बैकग्राउंड पेजों की जगह सर्विस वर्कर ले लेता है. मेनिफ़ेस्ट में हुए बदलावों की सूची यहां दी गई है.
manifest.json
में"background.scripts"
को"background.service_worker"
से बदलें. ध्यान दें कि"service_worker"
फ़ील्ड में स्ट्रिंग डाली जाती है, न कि स्ट्रिंग का कलेक्शन.manifest.json
से"background.persistent"
को हटाएं.
{ ... "background": { "scripts": [ "backgroundContextMenus.js", "backgroundOauth.js" ], "persistent": false }, ... }
{ ... "background": { "service_worker": "service_worker.js", "type": "module" } ... }
"service_worker"
फ़ील्ड में सिर्फ़ एक स्ट्रिंग डाली जा सकती है. import
कीवर्ड का इस्तेमाल करके, ES मॉड्यूल का इस्तेमाल करने पर ही, आपको "type"
फ़ील्ड की ज़रूरत होगी. इसकी वैल्यू हमेशा "module"
होगी. ज़्यादा जानकारी के लिए, एक्सटेंशन सेवा वर्कर के बारे में बुनियादी जानकारी देखें
डीओएम और विंडो कॉल को ऑफ़स्क्रीन दस्तावेज़ पर ले जाना
कुछ एक्सटेंशन को नई विंडो या टैब खोले बिना, DOM और विंडो ऑब्जेक्ट का ऐक्सेस चाहिए. Offscreen API, इन इस्तेमाल के उदाहरणों के साथ काम करता है. यह एक्सटेंशन के साथ पैकेज किए गए ऐसे दस्तावेज़ों को खोलता और बंद करता है जो उपयोगकर्ता को नहीं दिखाए जाते. इससे उपयोगकर्ता अनुभव पर कोई असर नहीं पड़ता. ऑफ़स्क्रीन दस्तावेज़, मैसेज पास करने के अलावा, अन्य एक्सटेंशन कॉन्टेक्स्ट के साथ एपीआई शेयर नहीं करते. हालांकि, एक्सटेंशन के साथ इंटरैक्ट करने के लिए, वे पूरे वेब पेज के तौर पर काम करते हैं.
Offscreen API का इस्तेमाल करने के लिए, सेवा वर्कर से ऑफ़स्क्रीन दस्तावेज़ बनाएं.
chrome.offscreen.createDocument({
url: chrome.runtime.getURL('offscreen.html'),
reasons: ['CLIPBOARD'],
justification: 'testing the offscreen API',
});
ऑफ़स्क्रीन दस्तावेज़ में, वह कार्रवाई करें जो पहले बैकग्राउंड स्क्रिप्ट में की जाती थी. उदाहरण के लिए, होस्ट पेज पर चुने गए टेक्स्ट को कॉपी किया जा सकता है.
let textEl = document.querySelector('#text');
textEl.value = data;
textEl.select();
document.execCommand('copy');
मैसेज पास करने की सुविधा का इस्तेमाल करके, ऑफ़स्क्रीन दस्तावेज़ों और एक्सटेंशन सेवा के कर्मचारियों के बीच बातचीत करें.
localStorage को किसी दूसरे टाइप में बदलना
वेब प्लैटफ़ॉर्म के Storage
इंटरफ़ेस (window.localStorage
से ऐक्सेस किया जा सकता है) का इस्तेमाल, सर्विस वर्कर में नहीं किया जा सकता. इसे ठीक करने के लिए, इनमें से कोई एक काम करें. सबसे पहले, इसे किसी दूसरे स्टोरेज सिस्टम के कॉल से बदला जा सकता है. chrome.storage.local
नेमस्पेस, ज़्यादातर इस्तेमाल के उदाहरणों के लिए काम करेगा. हालांकि, अन्य विकल्प भी उपलब्ध हैं.
इसके कॉल को ऑफ़स्क्रीन दस्तावेज़ में भी ले जाया जा सकता है. उदाहरण के लिए, localStorage
में पहले से सेव किए गए डेटा को किसी दूसरे तरीके से माइग्रेट करने के लिए:
- कन्वर्ज़न रूटीन और
runtime.onMessage
हैंडलर के साथ ऑफ़स्क्रीन दस्तावेज़ बनाएं. - ऑफ़स्क्रीन दस्तावेज़ में कन्वर्ज़न रूटीन जोड़ें.
- एक्सटेंशन के सेवा वर्कर में, अपने डेटा के लिए
chrome.storage
देखें. - अगर आपको अपना डेटा नहीं मिलता है, तो ऑफ़स्क्रीन दस्तावेज़ create और कन्वर्ज़न रूटीन शुरू करने के लिए,
runtime.sendMessage()
को कॉल करें. - ऑफ़स्क्रीन दस्तावेज़ में जोड़े गए
runtime.onMessage
हैंडलर में, कन्वर्ज़न रूटीन को कॉल करें.
एक्सटेंशन में वेब स्टोरेज एपीआई के काम करने के तरीके में भी कुछ बारीकियां हैं. ज़्यादा जानने के लिए, स्टोरेज और कुकी लेख पढ़ें.
लिसनर को सिंक करके रजिस्टर करना
मेनिफ़ेस्ट V3 में, किसी प्रोमिस या कॉलबैक के अंदर असाइनीटिक रूप से (एक साथ कई काम करने की सुविधा) किसी लिसनर को रजिस्टर करने की गारंटी नहीं है. नीचे दिया गया कोड देखें.
chrome.storage.local.get(["badgeText"], ({ badgeText }) => {
chrome.browserAction.setBadgeText({ text: badgeText });
chrome.browserAction.onClicked.addListener(handleActionClick);
});
यह सुविधा, बैकग्राउंड में लगातार चलने वाले पेज के साथ काम करती है, क्योंकि यह पेज लगातार चलता रहता है और इसे कभी भी फिर से शुरू नहीं किया जाता. मेनिफ़ेस्ट V3 में, इवेंट डिस्पैच होने पर सेवा वर्कर को फिर से शुरू किया जाएगा. इसका मतलब है कि इवेंट ट्रिगर होने पर, लिसनर रजिस्टर नहीं होंगे, क्योंकि इन्हें अलग-अलग समय पर जोड़ा जाता है. साथ ही, इवेंट को भी मिटा दिया जाएगा.
इसके बजाय, इवेंट लिसनर रजिस्ट्रेशन को अपनी स्क्रिप्ट के टॉप लेवल पर ले जाएं. इससे यह पक्का होता है कि Chrome, आपकी कार्रवाई के क्लिक हैंडलर को तुरंत ढूंढ और उसे ट्रिगर कर पाएगा. भले ही, आपका एक्सटेंशन स्टार्टअप लॉजिक को लागू करना पूरा न कर पाया हो.
chrome.action.onClicked.addListener(handleActionClick);
chrome.storage.local.get(["badgeText"], ({ badgeText }) => {
chrome.action.setBadgeText({ text: badgeText });
});
XMLHttpRequest() को global fetch() से बदलें
XMLHttpRequest()
को किसी सेवा वर्कर, एक्सटेंशन या किसी अन्य तरीके से कॉल नहीं किया जा सकता. अपनी बैकग्राउंड स्क्रिप्ट में XMLHttpRequest()
पर किए गए कॉल को ग्लोबल fetch()
पर किए गए कॉल से बदलें.
const xhr = new XMLHttpRequest(); console.log('UNSENT', xhr.readyState); xhr.open('GET', '/api', true); console.log('OPENED', xhr.readyState); xhr.onload = () => { console.log('DONE', xhr.readyState); }; xhr.send(null);
const response = await fetch('https://www.example.com/greeting.json'') console.log(response.statusText);
सेटिंग को सेव करना
सेवा वर्कर कुछ समय के लिए ही काम करते हैं. इसका मतलब है कि उपयोगकर्ता के ब्राउज़र सेशन के दौरान, वे बार-बार शुरू, चलेंगे, और बंद हो जाएंगे. इसका यह भी मतलब है कि पिछले कॉन्टेक्स्ट को हटाने के बाद, ग्लोबल वैरिएबल में डेटा तुरंत उपलब्ध नहीं होता. इस समस्या से बचने के लिए, स्टोरेज एपीआई का इस्तेमाल सटीक जानकारी के सोर्स के तौर पर करें. इसका तरीका जानने के लिए, यहां दिया गया उदाहरण देखें.
नीचे दिए गए उदाहरण में, नाम को स्टोर करने के लिए ग्लोबल वैरिएबल का इस्तेमाल किया गया है. किसी सेवा वर्कर में, उपयोगकर्ता के ब्राउज़र सेशन के दौरान, इस वैरिएबल को कई बार रीसेट किया जा सकता है.
let savedName = undefined; chrome.runtime.onMessage.addListener(({ type, name }) => { if (type === "set-name") { savedName = name; } }); chrome.browserAction.onClicked.addListener((tab) => { chrome.tabs.sendMessage(tab.id, { name: savedName }); });
मेनिफ़ेस्ट V3 के लिए, ग्लोबल वैरिएबल को Storage API के कॉल से बदलें.
chrome.runtime.onMessage.addListener(({ type, name }) => { if (type === "set-name") { chrome.storage.local.set({ name }); } }); chrome.action.onClicked.addListener(async (tab) => { const { name } = await chrome.storage.local.get(["name"]); chrome.tabs.sendMessage(tab.id, { name }); });
टाइमर को अलार्म में बदलना
setTimeout()
या setInterval()
तरीकों का इस्तेमाल करके, देर से या समय-समय पर होने वाली कार्रवाइयों का इस्तेमाल करना आम बात है. हालांकि, ये एपीआई सर्विस वर्कर में काम नहीं कर सकते, क्योंकि जब भी सर्विस वर्कर को बंद किया जाता है, तो टाइमर रद्द हो जाते हैं.
// 3 minutes in milliseconds const TIMEOUT = 3 * 60 * 1000; setTimeout(() => { chrome.action.setIcon({ path: getRandomIconPath(), }); }, TIMEOUT);
इसके बजाय, Alarms API का इस्तेमाल करें. अन्य लिसनर की तरह, अलार्म लिसनर को भी आपकी स्क्रिप्ट के सबसे ऊपर वाले लेवल में रजिस्टर किया जाना चाहिए.
async function startAlarm(name, duration) { await chrome.alarms.create(name, { delayInMinutes: 3 }); } chrome.alarms.onAlarm.addListener(() => { chrome.action.setIcon({ path: getRandomIconPath(), }); });
सेवा वर्कर को चालू रखना
सेवा वर्कर, इवेंट-ड्रिवन होते हैं और कोई गतिविधि न होने पर बंद हो जाते हैं. इससे Chrome, आपके एक्सटेंशन की परफ़ॉर्मेंस और मेमोरी खर्च को ऑप्टिमाइज़ कर सकता है. सेवा वर्कर के लाइफ़साइकल से जुड़े दस्तावेज़ में ज़्यादा जानें. कुछ खास मामलों में, यह पक्का करने के लिए अतिरिक्त उपाय करने पड़ सकते हैं कि सेवा वर्कर लंबे समय तक चालू रहे.
लंबे समय तक चलने वाली कार्रवाई पूरी होने तक, सेवा वर्कर को चालू रखना
लंबे समय तक चलने वाले ऐसे सर्विस वर्कर ऑपरेशन के दौरान, जो एक्सटेंशन एपीआई को कॉल नहीं करते, हो सकता है कि सर्विस वर्कर ऑपरेशन के बीच में बंद हो जाए. उदाहरण के लिए:
fetch()
अनुरोध को पूरा होने में पांच मिनट से ज़्यादा समय लग सकता है. उदाहरण के लिए, खराब कनेक्शन पर बड़ी फ़ाइल डाउनलोड करना.- ऐसी जटिल गणना जो सिंक नहीं होती और जिसमें 30 सेकंड से ज़्यादा समय लगता है.
इन मामलों में, सेवा वर्कर के लाइफ़टाइम को बढ़ाने के लिए, समय-समय पर टाइम आउट काउंटर को रीसेट करने के लिए, ट्रिवल एक्सटेंशन एपीआई को कॉल किया जा सकता है. कृपया ध्यान दें कि यह सुविधा सिर्फ़ असाधारण मामलों के लिए है. ज़्यादातर मामलों में, एक ही नतीजा पाने के लिए, प्लैटफ़ॉर्म के हिसाब से बेहतर तरीका होता है.
यहां दिए गए उदाहरण में, waitUntil()
हेल्पर फ़ंक्शन दिखाया गया है. यह फ़ंक्शन, किसी प्रॉमिस के पूरा होने तक आपके सेवा वर्कर को चालू रखता है:
async function waitUntil(promise) = {
const keepAlive = setInterval(chrome.runtime.getPlatformInfo, 25 * 1000);
try {
await promise;
} finally {
clearInterval(keepAlive);
}
}
waitUntil(someExpensiveCalculation());
किसी सेवा वर्कर को लगातार चालू रखना
कुछ मामलों में, लाइफ़टाइम को अनलिमिटेड तौर पर बढ़ाना ज़रूरी होता है. हमने एंटरप्राइज़ और शिक्षा को इस्तेमाल के सबसे बड़े उदाहरणों के तौर पर पहचाना है. हम खास तौर पर इनके लिए इसकी अनुमति देते हैं. हालांकि, हम आम तौर पर इसकी अनुमति नहीं देते. इन असाधारण स्थितियों में, किसी मामूली एक्सटेंशन एपीआई को समय-समय पर कॉल करके, सेवा वर्कर को चालू रखा जा सकता है. ध्यान रखें कि यह सुझाव सिर्फ़ उन एक्सटेंशन पर लागू होता है जो एंटरप्राइज़ या शिक्षा के इस्तेमाल के उदाहरणों के लिए, मैनेज किए जा रहे डिवाइसों पर चल रहे हैं. अन्य मामलों में ऐसा करने की अनुमति नहीं है. साथ ही, Chrome एक्सटेंशन टीम आने वाले समय में उन एक्सटेंशन के ख़िलाफ़ कार्रवाई करने का अधिकार सुरक्षित रखती है.
अपने सेवा वर्कर को चालू रखने के लिए, नीचे दिए गए कोड स्निपेट का इस्तेमाल करें:
/**
* Tracks when a service worker was last alive and extends the service worker
* lifetime by writing the current time to extension storage every 20 seconds.
* You should still prepare for unexpected termination - for example, if the
* extension process crashes or your extension is manually stopped at
* chrome://serviceworker-internals.
*/
let heartbeatInterval;
async function runHeartbeat() {
await chrome.storage.local.set({ 'last-heartbeat': new Date().getTime() });
}
/**
* Starts the heartbeat interval which keeps the service worker alive. Call
* this sparingly when you are doing work which requires persistence, and call
* stopHeartbeat once that work is complete.
*/
async function startHeartbeat() {
// Run the heartbeat once at service worker startup.
runHeartbeat().then(() => {
// Then again every 20 seconds.
heartbeatInterval = setInterval(runHeartbeat, 20 * 1000);
});
}
async function stopHeartbeat() {
clearInterval(heartbeatInterval);
}
/**
* Returns the last heartbeat stored in extension storage, or undefined if
* the heartbeat has never run before.
*/
async function getLastHeartbeat() {
return (await chrome.storage.local.get('last-heartbeat'))['last-heartbeat'];
}