`Service Worker` जावास्क्रिप्ट में

`Service Worker` जावास्क्रिप्ट में

यह लेख जावास्क्रिप्ट में Service Worker की अवधारणा को समझाता है।

हम Service Worker की मूल बातों से लेकर व्यावहारिक कैश नियंत्रण तक, चरण-दर-चरण समझाएँगे।

YouTube Video

offline.html
 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4  <meta charset="UTF-8">
 5  <title>Offline</title>
 6</head>
 7<body>
 8  <h1>You are offline</h1>
 9  <p>This is the offline fallback page.</p>
10</body>
11</html>
style.css
1body {
2  font-family: sans-serif;
3  background-color: #f0f0f0;
4  padding: 20px;
5}
6h1 {
7  color: #333;
8}
javascript-service-worker.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>JavaScript &amp; HTML</title>
  6  <style>
  7    * {
  8        box-sizing: border-box;
  9    }
 10
 11    body {
 12        margin: 0;
 13        padding: 1em;
 14        padding-bottom: 10em;
 15        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 16        background-color: #f7f9fc;
 17        color: #333;
 18        line-height: 1.6;
 19    }
 20
 21    .container {
 22        max-width: 800px;
 23        margin: 0 auto;
 24        padding: 1em;
 25        background-color: #ffffff;
 26        border: 1px solid #ccc;
 27        border-radius: 10px;
 28        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 29    }
 30
 31    .container-flex {
 32        display: flex;
 33        flex-wrap: wrap;
 34        gap: 2em;
 35        max-width: 1000px;
 36        margin: 0 auto;
 37        padding: 1em;
 38        background-color: #ffffff;
 39        border: 1px solid #ccc;
 40        border-radius: 10px;
 41        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 42    }
 43
 44    .left-column, .right-column {
 45        flex: 1 1 200px;
 46        min-width: 200px;
 47    }
 48
 49    h1, h2 {
 50        font-size: 1.2rem;
 51        color: #007bff;
 52        margin-top: 0.5em;
 53        margin-bottom: 0.5em;
 54        border-left: 5px solid #007bff;
 55        padding-left: 0.6em;
 56        background-color: #e9f2ff;
 57    }
 58
 59    button {
 60        display: block;
 61        margin: 1em auto;
 62        padding: 0.75em 1.5em;
 63        font-size: 1rem;
 64        background-color: #007bff;
 65        color: white;
 66        border: none;
 67        border-radius: 6px;
 68        cursor: pointer;
 69        transition: background-color 0.3s ease;
 70    }
 71
 72    button:hover {
 73        background-color: #0056b3;
 74    }
 75
 76    #output {
 77        margin-top: 1em;
 78        background-color: #1e1e1e;
 79        color: #0f0;
 80        padding: 1em;
 81        border-radius: 8px;
 82        min-height: 200px;
 83        font-family: Consolas, monospace;
 84        font-size: 0.95rem;
 85        overflow-y: auto;
 86        white-space: pre-wrap;
 87    }
 88
 89    .highlight {
 90        outline: 3px solid #ffc107; /* yellow border */
 91        background-color: #fff8e1;  /* soft yellow background */
 92        transition: background-color 0.3s ease, outline 0.3s ease;
 93    }
 94
 95    .active {
 96        background-color: #28a745; /* green background */
 97        color: #fff;
 98        box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
 99        transition: background-color 0.3s ease, box-shadow 0.3s ease;
100    }
101  </style>
102</head>
103<body>
104    <div class="container">
105        <h1>JavaScript Console</h1>
106        <button id="executeBtn">Execute</button>
107        <div id="output"></div>
108    </div>
109
110    <div class="container">
111        <h2>HTML Sample</h2>
112        <button id="fetchBtn">Fetch Test</button>
113    </div>
114
115    <script>
116        // Override console.log to display messages in the #output element
117        (function () {
118            // Override console.log
119            const originalLog = console.log;
120            console.log = function (...args) {
121                originalLog.apply(console, args);
122                const message = document.createElement('div');
123                message.textContent = args.map(String).join(' ');
124                output.appendChild(message);
125            };
126
127            // Override console.error
128            const originalError = console.error;
129            console.error = function (...args) {
130                originalError.apply(console, args);
131                const message = document.createElement('div');
132                message.textContent = args.map(String).join(' ');
133                message.style.color = 'red'; // Color error messages red
134                output.appendChild(message);
135            };
136        })();
137
138        document.getElementById('executeBtn').addEventListener('click', () => {
139            // Prevent multiple loads
140            if (document.getElementById('externalScript')) return;
141
142            const script = document.createElement('script');
143            script.src = 'javascript-service-worker.js';
144            script.id = 'externalScript';
145            //script.onload = () => console.log('javascript-service-worker.js loaded and executed.');
146            //script.onerror = () => console.log('Failed to load javascript-service-worker.js.');
147            document.body.appendChild(script);
148        });
149    </script>
150</body>
151</html>

Service Worker जावास्क्रिप्ट में

Service Worker एक जावास्क्रिप्ट फीचर है जो ब्राउज़र और नेटवर्क के बीच कार्य करता है, जिससे अनुरोधों की कैशिंग और ऑफलाइन समर्थन संभव होता है। यह PWAs (प्रोग्रेसिव वेब ऐप्स) की मुख्य तकनीक है और वेब अनुप्रयोगों को नेटिव ऐप जैसा अनुभव प्रदान करती है।

Service Worker क्या है?

Service Worker एक जावास्क्रिप्ट फ़ाइल है जो ब्राउज़र के पृष्ठभूमि थ्रेड में चलती है। यह पेज से अलग थ्रेड पर चलता है, UI तक पहुंच नहीं रखता, लेकिन नेटवर्क अनुरोधों को इंटरसेप्ट कर सकता है, कैशिंग प्रबंधित कर सकता है, और पुश सूचनाओं को संभाल सकता है।

Service Worker की मुख्य विशेषताएँ निम्नलिखित हैं:।

  • यह केवल HTTPS पर ही काम करता है, सिवाय localhost के।
  • यह Promise-आधारित असिंक्रोनस API का उपयोग करता है।
  • यह इवेंट-चालित है, और install, activate, fetch, और push जैसे इवेंट्स का उपयोग करता है।

Service Worker को रजिस्टर करना

सबसे पहले, चलिए ब्राउज़र में Service Worker को रजिस्टर करने का कोड लिखते हैं।

 1if ('serviceWorker' in navigator) {
 2    window.addEventListener('load', () => {
 3        navigator.serviceWorker.register('/sw.js')
 4        .then(registration => {
 5            console.log(
 6                'Service Worker registered with scope:',
 7                registration.scope
 8            );
 9        })
10        .catch(error => {
11            console.error('Service Worker registration failed:', error);
12        });
13    });
14}

व्याख्या

  • navigator.serviceWorker.register() का उपयोग करके /sw.js (जो कि Service Worker फ़ाइल है) को रजिस्टर करें।
  • रजिस्ट्रेशन के दौरान सफलता के लिए then और त्रुटि के लिए catch का उपयोग कर सकते हैं।
  • registration.scope उस पथ सीमा (स्कोप) को दर्शाता है जिस पर Service Worker का प्रभाव होता है।
  • डिफ़ॉल्ट रूप से, स्कोप वह डायरेक्टरी होती है जहाँ रजिस्टर की गई फाइल (इस मामले में, /sw.js) स्थित होती है और उसकी सब-डायरेक्टरीज़।

Service Worker का स्कोप

यदि आप स्कोप को सीमित करना चाहते हैं, तो आप register के दूसरे आर्ग्युमेंट का उपयोग करके scope निर्दिष्ट कर सकते हैं।

1navigator.serviceWorker.register('/sw.js', { scope: '/app/' })
2.then(registration => {
3    console.log(
4        'Service Worker registered with scope:',
5        registration.scope
6    );
7});

व्याख्या

  • इस सेटिंग के साथ, केवल /app/ के अंतर्गत आने वाले पेज ही Service Worker द्वारा नियंत्रित होंगे।

Service Worker फ़ाइल बनाना

इसके बाद, sw.js नामक एक फ़ाइल बनाएं और आवश्यक बुनियादी इवेंट्स लागू करें।

1// sw.js
2const CACHE_NAME = 'my-cache-v1';
3const urlsToCache = [
4    '/',
5    '/index.html',
6    '/styles.css',
7    '/script.js',
8    '/offline.html'
9];

यह कोड कैश किए जाने वाले संसाधनों की सूची को परिभाषित करता है।

प्रत्येक इवेंट की भूमिकाएँ और तंत्र

install

 1// Install event (initial caching)
 2self.addEventListener('install', event => {
 3    console.log('[ServiceWorker] Install');
 4    event.waitUntil(
 5        caches.open(CACHE_NAME).then(cache => {
 6            console.log('[ServiceWorker] Caching app shell');
 7            return cache.addAll(urlsToCache);
 8        })
 9    );
10});
  • Service Worker के पहली बार रजिस्टर होने पर self.addEventListener('install') ट्रिगर होता है। इस चरण में, आवश्यक फ़ाइलें पहले से कैश कर ली जाती हैं।

activate

 1// Activation event (delete old caches)
 2self.addEventListener('activate', event => {
 3    console.log('[ServiceWorker] Activate');
 4    event.waitUntil(
 5        caches.keys().then(keyList => {
 6            return Promise.all(keyList.map(key => {
 7                if (key !== CACHE_NAME) {
 8                    console.log('[ServiceWorker] Removing old cache:', key);
 9                    return caches.delete(key);
10                }
11            }));
12        })
13    );
14    return self.clients.claim();
15});
  • activate इवेंट में, पुराने कैश हटाए जाते हैं ताकि स्टोरेज को अनुकूलित किया जा सके। केवल नए संस्करण का कैश रखा जाता है।

fetch

1// Fetch event (cache-first strategy)
2self.addEventListener('fetch', event => {
3  console.log('[ServiceWorker] Fetch', event.request.url);
4    event.respondWith(
5        caches.match(event.request).then(response => {
6            return response || fetch(event.request).catch(() => caches.match('/offline.html'));
7        })
8    );
9});

सभी HTTP अनुरोध इंटरसेप्ट किए जाते हैं—यदि कैश्ड संस्करण मौजूद है तो उसे लौटाया जाता है; अन्यथा, नेटवर्क से प्राप्त किया जाता है। ऑफ़लाइन होने पर, एक विकल्प पृष्ठ (जैसे, offline.html) लौटाया जाता है।

प्रक्रिया की पुष्टि की जा रही है

आइए वास्तव में देखें कि Service Worker कैसे काम करता है।

 1document.getElementById('fetchBtn').addEventListener('click', () => {
 2    fetch('/style.css')
 3        .then(response => response.text())
 4        .then(data => {
 5            console.log('Fetched data:', data);
 6        })
 7        .catch(error => {
 8            console.error('Fetch failed:', error);
 9        });
10});
  • यहाँ, हम Service Worker के पंजीकरण और परीक्षण बटन क्लिक करके संसाधनों को प्राप्त करने के व्यवहार की जांच करते हैं।

कैशिंग रणनीतियों के उदाहरण

निम्नलिखित सामान्य कैशिंग रणनीतियाँ हैं:।

Cache First

यहाँ Cache First रणनीति का एक उदाहरण कार्यान्वयन है:।

1self.addEventListener('fetch', event => {
2    event.respondWith(
3        caches.match(event.request).then(response => {
4            return response || fetch(event.request);
5        })
6    );
7});
  • यह कोड कैश-फर्स्ट रणनीति को लागू करता है, जिसमें अनुरोधित संसाधन यदि कैश में उपलब्ध है तो वहीं से लौटाया जाता है; यदि नहीं है, तो उसे नेटवर्क से प्राप्त किया जाता है।

Network First

यहाँ Network First रणनीति का एक उदाहरण कार्यान्वयन है:।

 1self.addEventListener('fetch', event => {
 2    event.respondWith(
 3        fetch(event.request)
 4            .then(response => {
 5                return caches.open(CACHE_NAME).then(cache => {
 6                    cache.put(event.request, response.clone());
 7                    return response;
 8                });
 9            })
10            .catch(() => caches.match(event.request))
11    );
12});
  • यह कोड नेटवर्क-फर्स्ट रणनीति को लागू करता है, जिसमें अनुरोधित संसाधन सबसे पहले नेटवर्क से प्राप्त किया जाता है, और यदि वह विफल रहता है तो कैश से प्राप्त किया जाता है।

केवल स्टाइल्स और जावास्क्रिप्ट को कैश करें, APIs को रियल-टाइम में एक्सेस करें

यहाँ एक उदाहरण कार्यान्वयन है जिसमें स्टाइल्स और जावास्क्रिप्ट को कैश किया जाता है जबकि APIs को रियल-टाइम में एक्सेस किया जाता है:।

 1self.addEventListener('fetch', event => {
 2    if (event.request.url.includes('/api/')) {
 3        // Fetch API responses in real-time without caching
 4        return;
 5    }
 6
 7    // Use cache-first strategy for static files
 8    event.respondWith(
 9        caches.match(event.request).then(response => {
10            return response || fetch(event.request);
11        })
12    );
13});
  • यह कोड हमेशा एपीआई अनुरोधों को रियल-टाइम में एक्सेस करता है और स्टाइलशीट्स तथा जावास्क्रिप्ट जैसी स्थिर फ़ाइलों पर कैश-फर्स्ट रणनीति लागू करता है।

अपडेट प्रक्रिया

सर्विस वर्कर की अपडेट प्रक्रिया निम्नलिखित है:।

  1. एक नया sw.js पहचाना जाता है।
  2. install इवेंट ट्रिगर होता है।
  3. यह तब तक प्रतीक्षा करता है जब तक पिछला Service Worker निष्क्रिय नहीं हो जाता।
  4. activate इवेंट ट्रिगर होता है।
  5. यह नए Service Worker में स्विच कर जाता है।
  6. ‘controllerchange’ इवेंट चालू होता है।

अपडेट का पता लगाना

एक बार Service Worker इंस्टॉल हो जाने के बाद, पुराना वर्शन अगली विजिट तक उपयोग में रहता है। अपडेट लागू करने के लिए, आमतौर पर ऐसा कोड उपयोग किया जाता है जो अपडेट का पता लगाता है और पेज को दोबारा लोड करता है।

1navigator.serviceWorker.addEventListener('controllerchange', () => {
2    window.location.reload();
3});
  • ‘controllerchange’ इवेंट तब चालू होता है जब सर्विस वर्कर का कंट्रोलर, यानी वर्तमान पेज को नियंत्रित करने वाला सर्विस वर्कर, बदल जाता है।
  • पहले से खुले पेज वर्तमान सर्विस वर्कर का उपयोग जारी रखते हैं, और नया स्थापित सर्विस वर्कर उन पृष्ठों पर तुरंत प्रभावी नहीं होता है। इसलिए, एक तकनीक उपयोग की जाती है जिसमें ‘controllerchange’ इवेंट के माध्यम से यह पता लगाया जाता है कि नया कंट्रोलर सक्रिय हो गया है, और फिर पृष्ठ को तुरंत अपडेट लागू करने के लिए दोबारा लोड किया जाता है।

सावधानियाँ और सर्वोत्तम अभ्यास

Service Worker का उपयोग करते समय, निम्नलिखित बातों का ध्यान रखें:।

  • HTTPS आवश्यक है सुरक्षा प्रतिबंधों के कारण, यह http:// पर काम नहीं करता (सिर्फ localhost को छोड़कर)।

  • Hashed फ़ाइल नाम कैश नाम में फ़ाइल का नाम, URL, और संस्करण जानकारी शामिल की जा सकती है।

  • क्लाइंट्स के साथ संचार Service Worker और पृष्ठ की जावास्क्रिप्ट के बीच संवाद के लिए postMessage का उपयोग करें।

सारांश

Service Worker वेब ऐप्स में ऑफलाइन समर्थन और प्रदर्शन सुधार के लिए एक आवश्यक तकनीक है। इंस्टॉलेशन, एक्टिवेशन, और फ़ेच हैंडलिंग की बुनियादी प्रक्रिया को समझकर तथा उपयुक्त कैशिंग रणनीतियाँ लागू करके, आप उच्च-गुणवत्ता वाली वेब एप्लीकेशन बना सकते हैं।

आप हमारे YouTube चैनल पर Visual Studio Code का उपयोग करके ऊपर दिए गए लेख के साथ आगे बढ़ सकते हैं। कृपया YouTube चैनल को भी देखें।

YouTube Video