mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 08:29:42 +02:00
fix(web): cache-bust same-origin module scripts + stylesheets
Static assets are served Cache-Control: max-age=1y, immutable, but the script and link tags in index.html carried no version — so any edit to a frontend module (panels-ui.js, styles.css, …) stayed cached until a manual hard refresh. renderIndexHtml now appends ?v=<mtime> to every same-origin .js/.css ref (generalizing the existing gesture-bundle cache-bust), re-stat'd per render so a changed file is picked up with no server restart. External URLs, already- versioned refs, and refs with no file on disk are left untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -997,6 +997,9 @@ export class WebServer extends EventEmitter {
|
|||||||
'<title>Codeman</title>',
|
'<title>Codeman</title>',
|
||||||
`<title>${escapeHtmlText(this.windowTitle)}</title>`
|
`<title>${escapeHtmlText(this.windowTitle)}</title>`
|
||||||
);
|
);
|
||||||
|
// Cache-bust same-origin module scripts + stylesheets so a normal reload
|
||||||
|
// always serves the latest (static assets carry a 1-year immutable cache).
|
||||||
|
html = this.cacheBustAssets(html);
|
||||||
// Detached single-session ("solo") window: inject the target session id so
|
// Detached single-session ("solo") window: inject the target session id so
|
||||||
// the client can enter solo mode even if a (network-first) service worker
|
// the client can enter solo mode even if a (network-first) service worker
|
||||||
// later serves a cached shell. The client primarily detects solo mode from
|
// later serves a cached shell. The client primarily detects solo mode from
|
||||||
@@ -1032,6 +1035,26 @@ export class WebServer extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Append ?v=<mtime> to every same-origin .js/.css reference in the page so a
|
||||||
|
* normal reload always serves the latest. Codeman's static assets are sent
|
||||||
|
* with `Cache-Control: max-age=1y, immutable` and the script/link tags carry
|
||||||
|
* no version, so without this an edited module (panels-ui.js, styles.css, …)
|
||||||
|
* stays cached until a manual hard refresh. mtime is re-stat'd per render, so
|
||||||
|
* a changed file is picked up with no server restart. External URLs (have a
|
||||||
|
* `:` scheme), already-versioned refs (have a `?`), and refs with no matching
|
||||||
|
* file on disk are left untouched. */
|
||||||
|
private cacheBustAssets(html: string): string {
|
||||||
|
const publicDir = join(__dirname, 'public');
|
||||||
|
return html.replace(/(\s(?:src|href)=")([^"?:]+\.(?:js|css))(")/g, (full, pre, ref, post) => {
|
||||||
|
try {
|
||||||
|
const v = Math.floor(statSync(join(publicDir, ref)).mtimeMs);
|
||||||
|
return `${pre}${ref}?v=${v}${post}`;
|
||||||
|
} catch {
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async setupSessionListeners(session: Session): Promise<void> {
|
private async setupSessionListeners(session: Session): Promise<void> {
|
||||||
// Create run summary tracker for this session
|
// Create run summary tracker for this session
|
||||||
const summaryTracker = new RunSummaryTracker(session.id, session.name);
|
const summaryTracker = new RunSummaryTracker(session.id, session.name);
|
||||||
|
|||||||
Reference in New Issue
Block a user