Repository navigation
Expand file tree
/
Copy pathimageCacheWorker.js
More file actions
151 lines (133 loc) · 4.18 KB
/
Copy pathimageCacheWorker.js
File metadata and controls
151 lines (133 loc) · 4.18 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
export const version = import.meta.env.PRIMAL_VERSION;
const IMAGE_CACHE = `images-${version}`;
const DAY = 1000 * 60 * 60 * 24;
let imageToElementMap = {};
// Install event - precache critical images
self.addEventListener('install', event => {
event.waitUntil(
caches.open(IMAGE_CACHE).then(async (cache) => {
try {
// Fetch the manifest
const manifestResponse = await fetch('/manifest.json');
const manifest = await manifestResponse.json();
// Extract asset URLs from manifest
const assetUrls = Object.values(manifest)
.filter(entry => entry.file && entry.file.match(/\.(png|jpg|jpeg|svg|webp)$/))
.map(entry => `/${entry.file}`);
const uniqueAssetUrls = [...new Set(assetUrls)];
return cache.addAll(uniqueAssetUrls);
}
catch (e) {
console.log('Error fertching manifest: ', e)
}
}).catch((e => {
if (self.location.hostname === 'localhost') {
console.log('Error prefetching cached images: ', e);
}
}))
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys =>
Promise.all(
keys
.filter(k => k !== IMAGE_CACHE)
.map(k => caches.delete(k))
)
)
.then(() => self.clients.claim())
.then(() => {
// Notify all open tabs that a new version is active
self.clients.matchAll({ type: 'window' }).then(clients => {
clients.forEach(client => {
client.postMessage({ type: 'SW_ACTIVATED' });
});
});
})
);
});
// Fetch event - intercept image requests
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
const isLocal = url.origin === location.origin;
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request, {
cache: 'no-store',
headers: {
'Cache-Control': 'no-store',
'Pragma': 'no-cache',
},
}).catch(() => caches.match(event.request))
);
return; // important: stop processing other handlers
}
if (event.request.destination === 'document') {
// Always go to network for HTML
event.respondWith(
fetch(event.request, { cache: 'no-cache' })
.catch(() => caches.match(event.request))
);
}
if (event.request.destination === 'image') {
event.respondWith(
caches.open(IMAGE_CACHE).then(cache => {
return cache.match(event.request).then(response => {
if (response) {
return response;
}
if (isLocal) {
// Fetch fresh image
return fetch(event.request, { mode: 'no-cors' }).then(fetchResponse => {
cache.put(event.request, fetchResponse.clone());
return fetchResponse;
}).catch(error => {
// console.error('FAILED TO FETCH IMAGE: ', url);
});
}
return fetch(event.request).then(fetchResponse => {
cache.put(event.request, fetchResponse.clone());
return fetchResponse;
}).catch(error => {
console.error('FAILED TO FETCH IMAGE: ', url);
});
});
}).catch(error => {
console.error('FAILED TO OPEN IMAGE: ', url);
})
);
}
});
self.addEventListener('message', event => {
if (event.data?.type === 'SKIP_WAITING') {
self.skipWaiting();
}
if (event.data.type === 'CACHE_AVATAR' && typeof event.data.url === 'string') {
const url = event.data.url;
event.waitUntil(new Promise(async (resolve) => {
try {
const cache = await caches.open(IMAGE_CACHE);
const response = await cache.match(url);
if (!!response) {
resolve();
}
else {
try {
// Fetch with no-cors for cross-origin avatars
const fetchResponse = await fetch(url, { mode: 'no-cors' });
await cache.put(url, fetchResponse);
resolve();
} catch {
console.error('Failed to cache avatar:', url, error);
resolve();
}
}
}
catch (e) {
console.error('Failed to open cache: ', e);
resolve();
}
}));
}
});