`Service Worker` sa JavaScript
Ipinapaliwanag ng artikulong ito ang konsepto ng Service Worker
sa JavaScript.
Ipapaliwanag namin ang bawat hakbang mula sa mga batayan ng Service Worker
hanggang sa aktuwal na kontrol ng cache.
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 & 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
sa JavaScript
Ang Service Worker
ay isang tampok ng JavaScript na namamagitan sa browser at sa network, nagbibigay-daan sa pag-cache ng mga request at suporta sa offline. Ito ay isang pangunahing teknolohiya ng mga PWA (Progressive Web Apps) at nagdadala ng karanasang parang native app sa mga web application.
Ano ang Service Worker
?
Ang Service Worker
ay isang JavaScript file na tumatakbo sa background thread ng browser. Tumatakbo ito sa hiwalay na thread mula sa pahina, hindi makaka-access sa UI, ngunit maaaring humarang ng mga network request, mag-manage ng caching, at mag-handle ng push notifications.
Ang mga pangunahing tampok ng Service Worker
ay kinabibilangan ng mga sumusunod:.
- Gumagana lamang ito sa HTTPS, maliban kung nasa localhost.
- Gumagamit ito ng Promise-based asynchronous API.
- Ito ay event-driven, gumagamit ng mga event tulad ng
install
,activate
,fetch
, atpush
.
Pagrehistro ng Service Worker
Una, sumulat tayo ng code upang irehistro ang Service Worker
sa browser.
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}
Paliwanag
- Gamitin ang
navigator.serviceWorker.register()
para magrehistro ng/sw.js
(angService Worker
file). - Maaari mong gamitin ang
then
para i-handle ang success atcatch
para sa error handling habang nagrerehistro. - Ang
registration.scope
ay kumakatawan sa saklaw ng path (scope) na apektado ngService Worker
. - Sa default, ang scope ay ang directory kung saan matatagpuan ang narehistrong file (sa kasong ito,
/sw.js
) at mga subdirectory nito.
Saklaw ng Service Worker
Kung nais mong limitahan ang saklaw, maaari mong tukuyin ang scope
gamit ang ikalawang argumento ng register
.
1navigator.serviceWorker.register('/sw.js', { scope: '/app/' })
2.then(registration => {
3 console.log(
4 'Service Worker registered with scope:',
5 registration.scope
6 );
7});
Paliwanag
- Sa setting na ito, tanging mga pahina sa ilalim ng
/app/
lamang ang mako-kontrol ngService Worker
.
Paglikha ng Service Worker
file
Susunod, gumawa ng file na tinatawag na sw.js
at ipatupad ang mga pangunahing event.
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];
Tinutukoy ng code na ito ang listahan ng mga resources na ise-save sa cache.
Mga tungkulin at mekanismo ng bawat event
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});
- Ang
self.addEventListener('install')
ay na-a-activate kapag angService Worker
ay nairehistro sa unang pagkakataon. Sa stage na ito, ang mga kinakailangang file ay pre-cached na.
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});
- Sa
activate
event, ang mga lumang cache ay binubura para ma-optimize ang storage. Tanging ang cache ng bagong bersyon lamang ang itinatabi.
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});
Lahat ng HTTP request ay hinaharang—kung may naka-cache na bersyon, iyon ang ibinabalik; kung wala, kinukuha mula sa network. Kapag offline, isang alternatibong pahina (hal. offline.html
) ang ibinabalik.
Kinukumpirma ang operasyon
Tingnan natin kung paano talaga gumagana ang 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});
- Dito, sinusuri natin ang pagpaparehistro ng
Service Worker
at ang kilos ng pagkuha ng mga resource sa pamamagitan ng pag-click sa test button.
Mga Halimbawa ng Caching Strategies
Ang mga sumusunod ay karaniwang caching strategies:.
Cache First
Narito ang halimbawa ng implementasyon para sa Cache First strategy:.
1self.addEventListener('fetch', event => {
2 event.respondWith(
3 caches.match(event.request).then(response => {
4 return response || fetch(event.request);
5 })
6 );
7});
- Ang code na ito ay gumagamit ng cache-first strategy, kung saan ang hinihiling na resource ay ibinibigay mula sa cache kung ito ay available; kung hindi, ito ay kinukuha mula sa network.
Network First
Narito ang halimbawa ng implementasyon para sa Network First strategy:.
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});
- Ang code na ito ay gumagamit ng network-first strategy, kung saan ang hinihiling na resource ay unang kinukuha mula sa network, at kung ito ay mabigo, ito ay kinukuha mula sa cache.
I-cache lamang ang mga style at JavaScript, at i-access ang APIs real-time
Narito ang halimbawa ng implementasyon kung saan naka-cache ang styles at JavaScript habang real-time na ina-access ang API:.
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});
- Ang code na ito ay laging gumagawa ng API requests nang real-time at gumagamit ng cache-first strategy para sa mga static files tulad ng stylesheets at JavaScript.
Daloy ng pag-update
Ang daloy ng pag-update ng isang Service Worker ay ang mga sumusunod:.
- Natuklasan ang bagong
sw.js
. - Na-trigger ang
install
event. - Maghihintay hanggang maging idle ang naunang
Service Worker
. - Na-trigger ang
activate
event. - Lumilipat na sa bagong Service Worker.
- Ang event na
controllerchange
ay nai-trigger.
Pag-detect ng update
Kapag ang Service Worker
ay na-install na, patuloy na ginagamit ang luma hanggang sa susunod na pagbisita. Upang mag-apply ng mga update, karaniwan nang gumamit ng code na nagde-detect ng mga update at nirere-load ang pahina.
1navigator.serviceWorker.addEventListener('controllerchange', () => {
2 window.location.reload();
3});
- Ang event na
controllerchange
ay nai-trigger kapag ang controller ng Service Worker, ibig sabihin ang Service Worker na kumokontrol sa kasalukuyang pahina, ay nagbago. - Ang mga pahina na kasalukuyang bukas ay patuloy na gumagamit ng kasalukuyang Service Worker, at ang bagong install na Service Worker ay hindi agad epektibo sa mga pahinang iyon. Dahil dito, ginagamit ang isang paraan kung saan ang
controllerchange
event ay ginagamit upang matukoy na may bagong controller na naging aktibo, saka nire-reload ang pahina upang agad na ma-apply ang update.
Mga Paalala at Pinakamahusay na Gawain
Kapag gumagamit ng Service Worker
, tandaan ang mga sumusunod:.
-
Kailangan ng HTTPS Dahil sa mga security restriction, hindi ito gumagana sa
http://
maliban salocalhost
. -
May Hash na Mga Pangalan ng File Maaaring isama sa pangalan ng cache ang file name, URL, at impormasyong may kaugnayan sa bersyon.
-
Komunikasyon sa Mga Kliyente Gamitin ang
postMessage
para magkomunika sa pagitan ngService Worker
at ng JavaScript ng pahina.
Buod
Ang Service Worker
ay mahalagang teknolohiya para sa suporta sa offline at pagpapabuti ng performance ng mga web app. Sa pamamagitan ng pag-unawa sa pangunahing daloy ng pag-install, activation, at fetch handling, at paggamit ng tamang caching strategies, makakabuo ka ng mas mataas na kalidad ng web application.
Maaari mong sundan ang artikulo sa itaas gamit ang Visual Studio Code sa aming YouTube channel. Paki-check din ang aming YouTube channel.