initial: bootstrap from BukidBountyApp base
This commit is contained in:
141
public/sw.js
Normal file
141
public/sw.js
Normal file
@@ -0,0 +1,141 @@
|
||||
// public/sw.js
|
||||
const CDN_SHA = '75a5d4f202f55d7a5fc5d7eb5a6037776dc865ef';
|
||||
const BUILD_VERSION = 'app-CnfIWXGb';
|
||||
importScripts('/synclib.js');
|
||||
self.__WB_MANIFEST = (typeof PrecacheStaticURLs !== 'undefined') ? PrecacheStaticURLs : [];
|
||||
importScripts('/dist/js/workbox-sw.js');
|
||||
|
||||
if (workbox) {
|
||||
const { registerRoute } = workbox.routing;
|
||||
const { precacheAndRoute } = workbox.precaching;
|
||||
const { StaleWhileRevalidate, CacheFirst } = workbox.strategies;
|
||||
const { BackgroundSyncPlugin } = workbox.backgroundSync;
|
||||
const { CacheableResponsePlugin } = workbox.cacheableResponse;
|
||||
const { ExpirationPlugin } = workbox.expiration;
|
||||
|
||||
// 1a. CDN assets route — must be registered before precacheAndRoute so CORS
|
||||
// responses from cdn.jsdelivr.net are intercepted here rather than by the
|
||||
// precache handler, which would attempt to clone opaque (no-cors) responses.
|
||||
registerRoute(
|
||||
({ url }) => url.hostname === 'cdn.jsdelivr.net',
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: 'cdn-assets-cache',
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({
|
||||
statuses: [0, 200],
|
||||
}),
|
||||
new ExpirationPlugin({
|
||||
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
|
||||
maxEntries: 200,
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// 1. Precaching static assets
|
||||
precacheAndRoute(self.__WB_MANIFEST);
|
||||
|
||||
// 2. Stale-while-revalidate strategy for pages
|
||||
const urlsToCache = (typeof PrecacheStaleRevalidateURLs !== 'undefined') ? PrecacheStaleRevalidateURLs : [];
|
||||
|
||||
const navigationHandler = new StaleWhileRevalidate({
|
||||
cacheName: 'page-stale-while-revalidate-cache',
|
||||
});
|
||||
|
||||
registerRoute(
|
||||
({ request }) => {
|
||||
try {
|
||||
// Handle explicit URLs in the cache list
|
||||
return urlsToCache.includes(new URL(request.url).pathname);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
navigationHandler
|
||||
);
|
||||
|
||||
// 2.1 Navigation Fallback: Handle all other navigation requests (HTML reloads)
|
||||
// This ensures that any direct navigation to a SPA route works while offline
|
||||
const { NavigationRoute } = workbox.routing;
|
||||
registerRoute(new NavigationRoute(navigationHandler));
|
||||
|
||||
// 3. Cache-first strategy for /RequestData/File/ blobs
|
||||
registerRoute(
|
||||
({ url }) => url.pathname.startsWith('/RequestData/File/'),
|
||||
new CacheFirst({
|
||||
cacheName: 'request-data-cache',
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({
|
||||
statuses: [0, 200],
|
||||
}),
|
||||
new ExpirationPlugin({
|
||||
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
|
||||
maxEntries: 2000,
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// 3.1 Cache-first strategy for build assets (hashed files)
|
||||
registerRoute(
|
||||
({ url }) => url.pathname.startsWith('/build/assets/'),
|
||||
new CacheFirst({
|
||||
cacheName: 'build-assets-cache-' + BUILD_VERSION,
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({
|
||||
statuses: [0, 200],
|
||||
}),
|
||||
new ExpirationPlugin({
|
||||
maxAgeSeconds: 180 * 24 * 60 * 60, // 6 months
|
||||
maxEntries: 1000,
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
// 4. Background sync
|
||||
const bgSyncPlugin = new BackgroundSyncPlugin('sync-queue', {
|
||||
maxRetentionTime: 24 * 60 // 24 hours
|
||||
});
|
||||
|
||||
// Example: Apply background sync to POST requests to /api/sync
|
||||
registerRoute(
|
||||
({ url }) => url.pathname.includes('/api/sync'),
|
||||
new workbox.strategies.NetworkOnly({
|
||||
plugins: [bgSyncPlugin],
|
||||
}),
|
||||
'POST'
|
||||
);
|
||||
}
|
||||
|
||||
// 5. Message passing to clients
|
||||
function postMessageToClients(data) {
|
||||
self.clients.matchAll().then(clients => {
|
||||
clients.forEach(client => {
|
||||
client.postMessage(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(keys =>
|
||||
Promise.all(
|
||||
keys
|
||||
.filter(k => k.startsWith('build-assets-cache') && k !== 'build-assets-cache-' + BUILD_VERSION)
|
||||
.map(k => caches.delete(k))
|
||||
)
|
||||
).then(() => self.clients.claim())
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('message', event => {
|
||||
if (event.data && event.data.type === 'PING') {
|
||||
postMessageToClients({ type: 'PONG' });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user