Files
alert/public/sw.js
2026-04-24 20:30:52 +08:00

132 lines
4.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Parse the parameters in the current script's own URL
const scriptUrl = new URL(self.location);
// Get the incoming version, and provide a default value if it doesn't exist
const version = scriptUrl.searchParams.get("v") || "default-version";
// Dynamically concatenate CACHE_NAME
const CACHE_NAME = `risk-guard-cache-${version}`;
console.log("Current Service Worker CACHE_NAME:", CACHE_NAME);
// 例如umi.1a2b3c4d.js, logo.7b3e198f.png
const HASH_REGEX =
/\.[0-9a-f]{8}\.(js|css|png|jpe?g|gif|webp|svg|ico|woff2?|eot|ttf)$/i;
// 1. Installation phase: forcibly skip waiting and directly enter the activation state
self.addEventListener("install", (event) => {
self.skipWaiting();
});
// 2. Activation phase: clean up old caches and immediately take control of the page
self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cache) => {
if (cache !== CACHE_NAME) {
console.log("Cleaning old cache:", cache);
return caches.delete(cache);
}
}),
);
}),
);
self.clients.claim(); // Immediately control all open clients (tabs)
});
// 3. Fetch event: this is the key to trigger the installation icon to be displayed
self.addEventListener("fetch", (event) => {
const { request } = event;
const url = new URL(request.url);
// If not a GET request, skip processing and go straight to the cache
if (request.method !== "GET") return;
// If not an http or https protocol (like chrome-extension), skip processing and go straight to the cache
if (!(url.protocol === "http:" || url.protocol === "https:")) {
return;
}
// Ignore HMR (hot module replacement) and API requests (you can adjust according to your actual API prefix)
if (
url.pathname.includes("/api/") ||
url.pathname.includes("/sockjs-node/")
) {
return;
}
// 1. Handle navigation requests: fetch from network first, then cache if successful
if (request.mode === "navigate") {
event.respondWith(
fetch(request).catch(() => {
return caches.match(request);
}),
);
return;
}
// 2. Handle static assets (js, css, images) - cache first
const isStaticAsset = url.pathname.match(
/\.(js|css|png|jpg|jpeg|svg|gif|woff2?|otf|ttf)$/,
);
const isHashed = HASH_REGEX.test(url.pathname);
if (isStaticAsset) {
if (isHashed) {
// ==========================================
// Strategy A: Resources with Hash -> Cache First
// ==========================================
event.respondWith(
caches.match(request).then((response) => {
// If cache hit, return the cached response immediately
if (response) return response;
// Otherwise, fetch from network first
return fetch(request).then((networkResponse) => {
if (
!networkResponse ||
networkResponse.status !== 200 ||
(networkResponse.type !== "basic" &&
networkResponse.type !== "cors")
) {
return networkResponse;
}
// Clone the response to allow multiple requests
const responseToCache = networkResponse.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseToCache);
});
return networkResponse;
});
}),
);
} else {
// ==========================================
// Strategy B: Resources without Hash (such as index.html) -> Network First
// Ensure that the latest code is always retrieved, only fall back to cache when offline
// ==========================================
event.respondWith(
fetch(request)
.then((networkResponse) => {
// Network request successful, updating cache
if (networkResponse && networkResponse.status === 200) {
const responseToCache = networkResponse.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseToCache);
});
}
return networkResponse;
})
.catch(() => {
// Network request failed (for example, the user disconnected from the Internet), try reading the historical version from the cache
console.log("[SW] Network offline, try reading cache:", request.url);
return caches.match(request);
}),
);
}
}
});