Fetch the rest of a new build in the background (#394)
The app page names only what it loads at start. The composer, settings, viewers and the rest were fetched when first used, and after every deploy that first use waited on the server -- and the worker's tidy-up dropped them again at the next deploy anyway. The build now writes the list of all its files into the page as an inert JSON block. The service worker keeps everything listed and, once a page names files it does not hold, fetches them three at a time; a load cut short is resumed at the next navigation. Language catalogs are listed apart and left to be cached when used, and nothing is fetched ahead when the browser is set to save data.
This commit is contained in:
+37
-2
@@ -1,4 +1,4 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
import { defineConfig, type Plugin } from "vitest/config";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { fileURLToPath, URL } from "node:url";
|
||||
import { resolveVersion } from "../scripts/version.mjs";
|
||||
@@ -22,9 +22,44 @@ const version = resolveVersion();
|
||||
*/
|
||||
const base = baseUrlOf(process.env.BASE_PATH);
|
||||
|
||||
/*
|
||||
* Every file the build made, written into the app page for the service worker.
|
||||
*
|
||||
* The page names only what it loads at start; the composer, settings, viewers
|
||||
* and the rest arrive when first used, and after each deploy that first use
|
||||
* went back to the server. With the whole list in the page, the worker can
|
||||
* fetch them in the background once a new version is seen, and knows to keep
|
||||
* them. Language catalogs are listed apart: a reader wants one of them, which
|
||||
* is cached when it is first loaded.
|
||||
*
|
||||
* An inert JSON block rather than prefetch links, which the browser would
|
||||
* fetch on every load.
|
||||
*/
|
||||
function assetList(): Plugin {
|
||||
return {
|
||||
name: "ihasmail-asset-list",
|
||||
apply: "build",
|
||||
transformIndexHtml: {
|
||||
order: "post",
|
||||
handler(html, ctx) {
|
||||
if (!ctx.bundle) return html;
|
||||
const precache: string[] = [];
|
||||
const onDemand: string[] = [];
|
||||
for (const file of Object.values(ctx.bundle)) {
|
||||
if (!file.fileName.startsWith("assets/") || file.fileName.endsWith(".map")) continue;
|
||||
const catalog = file.type === "chunk" && file.moduleIds.length > 0 && file.moduleIds.every((id) => /[\\/]src[\\/]locales[\\/][^\\/]+\.ts$/.test(id));
|
||||
(catalog ? onDemand : precache).push(`${base}${file.fileName}`);
|
||||
}
|
||||
const json = JSON.stringify({ precache: precache.sort(), onDemand: onDemand.sort() });
|
||||
return html.replace("</body>", ` <script type="application/json" id="ihasmail-assets">${json}</script>\n </body>`);
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
base,
|
||||
plugins: [react()],
|
||||
plugins: [react(), assetList()],
|
||||
define: { __IHASMAIL_VERSION__: JSON.stringify(version) },
|
||||
resolve: {
|
||||
alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) },
|
||||
|
||||
Reference in New Issue
Block a user