✨ feat: implement build version check and update build info handling
This commit is contained in:
@@ -50,40 +50,22 @@ const publishLocation = (_p?: string) => {
|
||||
}
|
||||
|
||||
if (typeof history !== "undefined") {
|
||||
if (typeof Proxy !== "undefined") {
|
||||
// modern browser
|
||||
const historyApply = (
|
||||
target: (this: any, ...args: readonly any[]) => unknown,
|
||||
thisArg: any,
|
||||
argumentsList: string | readonly any[]
|
||||
) => {
|
||||
publishLocation(argumentsList && argumentsList.length >= 2 && argumentsList[2])
|
||||
Reflect.apply(target, thisArg, argumentsList)
|
||||
}
|
||||
|
||||
history.pushState = new Proxy(history.pushState, {
|
||||
apply: historyApply,
|
||||
})
|
||||
|
||||
history.replaceState = new Proxy(history.replaceState, {
|
||||
apply: historyApply,
|
||||
})
|
||||
} else {
|
||||
// ie11
|
||||
const pushStateFn = history.pushState
|
||||
const replaceStateFn = history.replaceState
|
||||
|
||||
history.pushState = function (data: any, title: string, url?: string) {
|
||||
publishLocation(url)
|
||||
// @ts-ignore
|
||||
return pushStateFn.apply(history, arguments)
|
||||
}
|
||||
history.replaceState = function (data: any, title: string, url?: string) {
|
||||
publishLocation(url)
|
||||
// @ts-ignore
|
||||
return replaceStateFn.apply(history, arguments)
|
||||
}
|
||||
const historyApply = (
|
||||
target: (this: any, ...args: readonly any[]) => unknown,
|
||||
thisArg: any,
|
||||
argumentsList: string | readonly any[]
|
||||
) => {
|
||||
publishLocation(argumentsList && argumentsList.length >= 2 && argumentsList[2])
|
||||
Reflect.apply(target, thisArg, argumentsList)
|
||||
}
|
||||
|
||||
history.pushState = new Proxy(history.pushState, {
|
||||
apply: historyApply,
|
||||
})
|
||||
|
||||
history.replaceState = new Proxy(history.replaceState, {
|
||||
apply: historyApply,
|
||||
})
|
||||
} // else ssr -> no history handling
|
||||
|
||||
typeof window !== "undefined" &&
|
||||
|
||||
54
frontend/src/lib/versionCheck.ts
Normal file
54
frontend/src/lib/versionCheck.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Build-Version-Check: Auto-Reload when a newer build is detected on the server
|
||||
*
|
||||
* Every GET API response includes the header X-Build-Time with the server's build
|
||||
* timestamp. If it's newer than the one embedded in the frontend bundle, a toast
|
||||
* is shown and the page is automatically reloaded after a short delay.
|
||||
*/
|
||||
import { buildTime } from "./buildInfo"
|
||||
import { addToast } from "./toast"
|
||||
|
||||
/** Prevents multiple triggers within the same page session */
|
||||
let triggered = false
|
||||
|
||||
const RELOAD_DELAY_MS = 3000
|
||||
const STORAGE_KEY = "__build_reload__"
|
||||
|
||||
/**
|
||||
* Checks whether the server has a newer build than the current frontend bundle.
|
||||
* Only runs in the browser (SSR-safe).
|
||||
*
|
||||
* @param serverBuildTime - ISO timestamp from the X-Build-Time response header
|
||||
*/
|
||||
export function checkBuildVersion(serverBuildTime: string | null | undefined): void {
|
||||
if (!serverBuildTime || typeof window === "undefined") return
|
||||
if (triggered) return
|
||||
|
||||
// Only react if the server build is actually newer
|
||||
if (serverBuildTime <= buildTime) return
|
||||
|
||||
// Loop protection: if we already reloaded for this exact build, don't reload again
|
||||
// (e.g. CDN/cache still serving old bundle)
|
||||
try {
|
||||
if (sessionStorage.getItem(STORAGE_KEY) === serverBuildTime) return
|
||||
} catch (_) {
|
||||
// sessionStorage not available (e.g. privacy mode) – continue anyway
|
||||
}
|
||||
|
||||
triggered = true
|
||||
|
||||
// Show toast notification
|
||||
addToast("New version available – page will refresh…", "info", RELOAD_DELAY_MS + 2000)
|
||||
|
||||
// Remember that we're reloading for this build timestamp
|
||||
try {
|
||||
sessionStorage.setItem(STORAGE_KEY, serverBuildTime)
|
||||
} catch (_) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// Auto-reload after short delay so toast is visible
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
}, RELOAD_DELAY_MS)
|
||||
}
|
||||
Reference in New Issue
Block a user