Download the whole app build behind a loading page

In production, a page request without the running build's cookie gets a
small loading page instead of the app. It downloads every file in
.bunext/public (listed at /build-info.json) into that build's cache,
checks they are all there, hands over to a new service worker waiting
behind an older one, sets the cookie and reloads. The service worker
then serves the app's code from the cache, so later visits load it from
the device.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-20 19:33:15 +01:00
co-authored by Claude Opus 5.5
parent 9778d0b9ff
commit b3057119df
16 changed files with 991 additions and 45 deletions
+54
View File
@@ -0,0 +1,54 @@
/**
* Paths the loading page never stands in for: the app's code, live data,
* media, proxied computers and the files the loading page itself needs.
*/
const OpenPrefixes = ["/.bunext/", "/api/", "/ws", "/media", "/computers/"];
type Params = {
method: string;
pathname: string;
/**
* `Sec-Fetch-Mode` and `Sec-Fetch-Dest`, when the browser sends them.
* A navigation the service worker passes on keeps `navigate` but
* arrives with the destination `empty`.
*/
fetch_mode?: string | null;
fetch_dest?: string | null;
accept?: string | null;
/**
* The build in the browser's cookie, if any.
*/
cookie_build_id?: string | null;
/**
* The running build; null in development.
*/
build_id?: string | null;
};
/**
* Whether a request is a browser opening a page of the app on a build it
* hasn't downloaded yet, so it gets the loading page instead. Only page
* navigations: anything with a file extension (`/favicon.ico`,
* `/sw.js`, `/build-info.json`) goes through as usual.
*/
export default function needsPrecachePage({
method,
pathname,
fetch_mode,
fetch_dest,
accept,
cookie_build_id,
build_id,
}: Params): boolean {
if (!build_id) return false;
if (cookie_build_id == build_id) return false;
if (method != "GET") return false;
if (OpenPrefixes.some((prefix) => pathname.startsWith(prefix))) return false;
if (pathname.split("/").pop()?.includes(".")) return false;
if (fetch_mode || fetch_dest) {
return fetch_mode == "navigate" || fetch_dest == "document";
}
return Boolean(accept?.includes("text/html"));
}