-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsw.js
More file actions
174 lines (152 loc) · 8.13 KB
/
Copy pathsw.js
File metadata and controls
174 lines (152 loc) · 8.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* ═══════════════════════════════════════════════════════════════
ARCHIT KONDE — PORTFOLIO | sw.js (Service Worker)
What is a Service Worker?
─────────────────────────
A Service Worker is a script the browser runs in the background,
completely separate from the web page. It acts as a programmable
network proxy — intercepting every request your page makes and
deciding whether to fetch it from the network or serve it from
a local cache.
Why does this matter?
─────────────────────
Once installed, the site works even with no internet connection.
Repeat visits also load instantly (served from cache, not network).
Lifecycle (3 events):
─────────────────────
1. install → runs ONCE when the SW is first registered
→ we use it to pre-cache all site assets
2. activate → runs when the SW takes control of the page
→ we use it to delete any OLD cache versions
3. fetch → runs on EVERY network request the page makes
→ we intercept it and choose: cache or network
Cache Strategy used here:
─────────────────────────
• HTML pages → Network-first, fall back to cache
(so content updates are always reflected when online)
• CSS/JS/fonts → Cache-first, fall back to network
(these rarely change; fast from cache is ideal)
Diagram:
─────────────────────────────────────────────────────────
Page requests asset
│
▼
Is it in PRECACHE_ASSETS? → YES → return cached version (instant)
│
NO
▼
Is it a navigation (HTML page)?
YES → try network first → if offline, serve cache
NO → try cache first → if not cached, try network
│
▼
Serve response to page
─────────────────────────────────────────────────────────
═══════════════════════════════════════════════════════════════ */
/* ── Cache version ───────────────────────────────────────────────
Bump this string (e.g. 'v2', 'v3') whenever you deploy major
changes. The activate event deletes any caches with old names,
forcing users to re-download the latest assets.
──────────────────────────────────────────────────────────────── */
const CACHE_NAME = 'archit-portfolio-v42';
const OFFLINE_PAGE = '/404.html'; // shown if navigation fails offline
/* ── Assets to pre-cache on install ─────────────────────────────
These are downloaded and stored the moment the SW installs.
After that, they're served from cache on every request.
──────────────────────────────────────────────────────────────── */
const PRECACHE_ASSETS = [
'/',
'/index.html',
'/styles/main.min.css',
'/scripts/app.min.js',
'/404.html',
'/manifest.json',
'/assets/icons/icon-192.svg',
'/assets/icons/icon-512.svg',
'/pages/blog/rag-from-scratch.html',
'/pages/blog/supportops-ai-monitor.html',
'/pages/blog/triagegeist-solution.html',
'/pages/blog/insurance-reshopping-predictor.html',
'/docs/resume.pdf'
];
/* ── INSTALL event ───────────────────────────────────────────────
Fires once when the service worker is first installed.
We open our named cache and store all precache assets.
waitUntil() tells the browser "don't finish installing until
this Promise resolves" — ensuring the cache is ready before
the SW activates.
──────────────────────────────────────────────────────────────── */
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(PRECACHE_ASSETS))
.then(() => self.skipWaiting())
);
});
/* ── ACTIVATE event ──────────────────────────────────────────────
Fires when the SW takes control of the page.
We delete any caches whose name doesn't match CACHE_NAME.
This is how old versions are cleaned up after a cache bump.
──────────────────────────────────────────────────────────────── */
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(name => name !== CACHE_NAME) // find old caches
.map(name => caches.delete(name)) // delete each one
);
})
);
/* clients.claim() makes the SW control already-open pages
without needing a full reload. */
self.clients.claim();
});
/* ── FETCH event ─────────────────────────────────────────────────
Fires on EVERY network request from the page.
We apply different strategies depending on the request type.
──────────────────────────────────────────────────────────────── */
self.addEventListener('fetch', event => {
/* Ignore non-GET requests (POST, PUT, etc.) and
cross-origin requests (e.g. Google Fonts CDN).
Let those pass straight through to the network. */
if (event.request.method !== 'GET') return;
if (!event.request.url.startsWith(self.location.origin)) return;
/* ── Navigation requests (HTML pages) → Network-first ──────
Try to get a fresh version from the network.
If offline, serve the cached version instead.
If nothing is cached either, show the offline page. */
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.then(response => {
/* Got a network response — clone it into cache */
const copy = response.clone();
caches.open(CACHE_NAME).then(cache => cache.put(event.request, copy));
return response;
})
.catch(() => {
/* Offline — serve cached page or fallback */
return caches.match(event.request)
.then(cached => cached || caches.match(OFFLINE_PAGE));
})
);
return;
}
/* ── All other requests (CSS, JS, fonts, images) → Cache-first
Check cache first. If found, return immediately (fast!).
If not cached, fetch from network and store for next time. */
event.respondWith(
caches.match(event.request).then(cached => {
if (cached) return cached;
return fetch(event.request).then(response => {
/* Only cache valid responses (status 200, not opaque) */
if (!response || response.status !== 200 || response.type === 'error') {
return response;
}
const copy = response.clone();
caches.open(CACHE_NAME).then(cache => cache.put(event.request, copy));
return response;
});
})
);
});