mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-05-04 08:31:12 +00:00
Fix stale frontend cache handling
This commit is contained in:
+17
-1
@@ -65,16 +65,32 @@ http {
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
location = /sw.js {
|
||||
root /app/html;
|
||||
expires off;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location = /manifest.json {
|
||||
root /app/html;
|
||||
expires off;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
root /app/html;
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /app/html;
|
||||
index index.html index.htm;
|
||||
expires off;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
|
||||
+17
-1
@@ -54,16 +54,32 @@ http {
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
location = /sw.js {
|
||||
root /app/html;
|
||||
expires off;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location = /manifest.json {
|
||||
root /app/html;
|
||||
expires off;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
root /app/html;
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /app/html;
|
||||
index index.html index.htm;
|
||||
expires off;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
|
||||
+3
-13
@@ -1,8 +1,5 @@
|
||||
const CACHE_NAME = "termix-v1";
|
||||
const CACHE_NAME = "termix-static-v2";
|
||||
const STATIC_ASSETS = [
|
||||
"/",
|
||||
"/index.html",
|
||||
"/manifest.json",
|
||||
"/favicon.ico",
|
||||
"/icons/48x48.png",
|
||||
"/icons/128x128.png",
|
||||
@@ -66,18 +63,11 @@ self.addEventListener("fetch", (event) => {
|
||||
}
|
||||
|
||||
if (request.mode === "navigate") {
|
||||
event.respondWith(
|
||||
fetch(request).catch(() => {
|
||||
return caches.match("/index.html");
|
||||
}),
|
||||
);
|
||||
event.respondWith(fetch(request));
|
||||
return;
|
||||
}
|
||||
|
||||
const isStaticAsset = STATIC_ASSETS.some((asset) => {
|
||||
if (asset === "/") return url.pathname === "/";
|
||||
return url.pathname === asset || url.pathname.startsWith("/assets/");
|
||||
});
|
||||
const isStaticAsset = STATIC_ASSETS.some((asset) => url.pathname === asset);
|
||||
|
||||
if (!isStaticAsset) {
|
||||
return;
|
||||
|
||||
@@ -1771,10 +1771,38 @@ if (frontendDist) {
|
||||
databaseLogger.info(`Serving frontend from: ${frontendDist}`, {
|
||||
operation: "static_files",
|
||||
});
|
||||
app.use(express.static(frontendDist));
|
||||
app.use(
|
||||
express.static(frontendDist, {
|
||||
setHeaders: (res, filePath) => {
|
||||
const relativePath = path
|
||||
.relative(frontendDist, filePath)
|
||||
.replaceAll(path.sep, "/");
|
||||
|
||||
if (relativePath.startsWith("assets/")) {
|
||||
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
relativePath === "index.html" ||
|
||||
relativePath === "sw.js" ||
|
||||
relativePath === "manifest.json"
|
||||
) {
|
||||
res.setHeader(
|
||||
"Cache-Control",
|
||||
"no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0",
|
||||
);
|
||||
}
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
app.use((req, res, next) => {
|
||||
if (req.method === "GET" && req.accepts("html")) {
|
||||
res.setHeader(
|
||||
"Cache-Control",
|
||||
"no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0",
|
||||
);
|
||||
res.sendFile(path.join(frontendDist, "index.html"));
|
||||
} else {
|
||||
next();
|
||||
|
||||
@@ -40,27 +40,54 @@ export function useServiceWorker(): ServiceWorkerState {
|
||||
|
||||
if (!isSupported) return;
|
||||
|
||||
const shouldReloadOnControllerChange = Boolean(
|
||||
navigator.serviceWorker.controller,
|
||||
);
|
||||
let hasReloadedForUpdate = false;
|
||||
const handleControllerChange = () => {
|
||||
if (!shouldReloadOnControllerChange || hasReloadedForUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasReloadedForUpdate = true;
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
const registerSW = async () => {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.register(
|
||||
`${getBasePath()}/sw.js`,
|
||||
{ updateViaCache: "none" },
|
||||
);
|
||||
setState((prev) => ({ ...prev, isRegistered: true }));
|
||||
|
||||
registration.addEventListener("updatefound", () =>
|
||||
handleUpdateFound(registration),
|
||||
);
|
||||
await registration.update();
|
||||
} catch (error) {
|
||||
console.error("[SW] Registration failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
navigator.serviceWorker.addEventListener(
|
||||
"controllerchange",
|
||||
handleControllerChange,
|
||||
);
|
||||
|
||||
if (document.readyState === "complete") {
|
||||
registerSW();
|
||||
} else {
|
||||
window.addEventListener("load", registerSW);
|
||||
return () => window.removeEventListener("load", registerSW);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("load", registerSW);
|
||||
navigator.serviceWorker.removeEventListener(
|
||||
"controllerchange",
|
||||
handleControllerChange,
|
||||
);
|
||||
};
|
||||
}, [handleUpdateFound]);
|
||||
|
||||
return state;
|
||||
|
||||
Reference in New Issue
Block a user