mirror of
https://github.com/mickael-kerjean/filestash
synced 2026-01-02 05:44:52 +01:00
feature (fastboot): leverage importmap for fast start
This commit is contained in:
parent
5041bfeb0d
commit
45bc001f5e
6 changed files with 78 additions and 54 deletions
48
public/assets/boot/warmup.js
Normal file
48
public/assets/boot/warmup.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
if (!HTMLScriptElement.supports?.("importmap")) throw new Error("fastboot is not supported on this platform");
|
||||
window.bundler = (function(origin) {
|
||||
const esModules = {};
|
||||
return {
|
||||
register: (path, code) => {
|
||||
if (path.endsWith(".js")) {
|
||||
code = code.replace(/from\s?"([^"]+)"/g, (_, spec) =>
|
||||
`from "${new URL(spec, origin + path).href}"`,
|
||||
);
|
||||
code = code.replace(/\bimport\s+"([^"]+)"/g, (_, spec) =>
|
||||
`import "${new URL(spec, origin + path).href}"`,
|
||||
);
|
||||
code = code.replace(/(?<!["])\bimport\.meta\.url\b(?!["])/g, `"${origin + path}"`);
|
||||
code += `\n//# sourceURL=${path}`;
|
||||
esModules[path] = "data:text/javascript," + encodeURIComponent(code);
|
||||
} else if (path.endsWith(".css")) {
|
||||
code = code.replace(/@import url\("([^"]+)"\);/g, (m, rel) => {
|
||||
const $style = document.head.querySelector(`style[id="${new URL(rel, origin + path).href}"]`);
|
||||
if (!$style) throw new DOMException(
|
||||
`Missing CSS dependency: ${rel} (referenced from ${path})`,
|
||||
"NotFoundError",
|
||||
);
|
||||
return `/* ${m} */`;
|
||||
});
|
||||
code += `\n/*# sourceURL=${path} */`;
|
||||
document.head.appendChild(Object.assign(document.createElement("style"), {
|
||||
innerHTML: code,
|
||||
id: origin + path,
|
||||
}));
|
||||
}
|
||||
},
|
||||
esModules,
|
||||
};
|
||||
})(new URL(import.meta.url).origin);
|
||||
await new Promise((resolve, reject) => {
|
||||
document.head.appendChild(Object.assign(document.createElement("script"), {
|
||||
type: "module",
|
||||
src: `./assets/bundle.js?version=${window.VERSION}`,
|
||||
onload: resolve,
|
||||
onerror: reject,
|
||||
}));
|
||||
});
|
||||
document.head.appendChild(Object.assign(document.createElement("script"), {
|
||||
type: "importmap",
|
||||
textContent: JSON.stringify({
|
||||
imports: window.bundler.esModules,
|
||||
}, null, 4),
|
||||
}));
|
||||
|
|
@ -21,6 +21,7 @@ export async function loadCSS(baseURL, path) {
|
|||
$style.setAttribute("href", link.toString());
|
||||
$style.setAttribute("rel", "stylesheet");
|
||||
if (document.head.querySelector(`[href="${link.toString()}"]`)) return Promise.resolve();
|
||||
else if (document.head.querySelector(`style[id="${link.toString()}"]`)) return Promise.resolve();
|
||||
document.head.appendChild($style);
|
||||
return new Promise((done) => {
|
||||
$style.onload = done;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ async function load(route, opts) {
|
|||
}
|
||||
const module = window.env === "test"
|
||||
? require("../.." + route)
|
||||
: await import("../.." + route);
|
||||
: await import(new URL("../.." + route, import.meta.url));
|
||||
|
||||
if (typeof module.init === "function") await module.init();
|
||||
|
||||
|
|
|
|||
2
public/global.d.ts
vendored
2
public/global.d.ts
vendored
|
|
@ -5,5 +5,7 @@ interface Window {
|
|||
[key: string]: any;
|
||||
"xdg-open"?: (mime: string) => void;
|
||||
};
|
||||
VERSION: string;
|
||||
bundler: any;
|
||||
BEARER_TOKEN?: string;
|
||||
}
|
||||
|
|
@ -17,22 +17,19 @@
|
|||
|
||||
<template id="head">
|
||||
<link rel="stylesheet" href="custom.css">
|
||||
<link rel="stylesheet" href="./assets/{{ .version }}/css/designsystem.css">
|
||||
</template>
|
||||
<template id="body">
|
||||
<script type="module" src="./assets/{{ .version }}/components/loader.js"></script>
|
||||
<script type="module">
|
||||
import main from "./assets/{{ .version }}/lib/skeleton/index.js";
|
||||
import routes from "./assets/{{ .version }}/boot/router_frontoffice.js";
|
||||
|
||||
main(document.getElementById("app"), routes, {
|
||||
spinner: `<component-loader></component-loader>`,
|
||||
beforeStart: import("{{ .base }}assets/{{ .version }}/boot/ctrl_boot_frontoffice.js"),
|
||||
});
|
||||
</script>
|
||||
<component-modal></component-modal>
|
||||
<script type="module" src="./assets/{{ .version }}/components/modal.js" defer></script>
|
||||
<component-notification></component-notification>
|
||||
<script type="module" src="./assets/{{ .version }}/components/notification.js" defer></script>
|
||||
</template>
|
||||
|
||||
<script type="module">
|
||||
|
|
@ -41,46 +38,20 @@
|
|||
document.body.appendChild(document.querySelector("template#body").content);
|
||||
}
|
||||
async function ignitionSequence() {
|
||||
if (!("serviceWorker" in navigator)) return
|
||||
try {
|
||||
window.bundler = (function () {
|
||||
let modules = [];
|
||||
return {
|
||||
register: (path, code) => modules[path] = code,
|
||||
state: () => modules,
|
||||
};
|
||||
})();
|
||||
const [register] = await Promise.all([
|
||||
navigator.serviceWorker.register("sw.js").then((register) => new Promise((resolve) => {
|
||||
register.active ?
|
||||
resolve(register) :
|
||||
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
||||
resolve(register);
|
||||
});
|
||||
})),
|
||||
new Promise((resolve, reject) => {
|
||||
const $script = document.createElement("script");
|
||||
$script.type = "module";
|
||||
$script.src = "./assets/bundle.js?version={{ slice .version 0 7 }}::{{ .hash }}";
|
||||
document.head.appendChild($script);
|
||||
$script.onload = resolve;
|
||||
$script.onerror = reject;
|
||||
}),
|
||||
]);
|
||||
register.active.postMessage({
|
||||
"type": "preload",
|
||||
"payload": bundler.state(),
|
||||
"version": "{{ slice .version 0 7 }}::{{ .hash }}",
|
||||
});
|
||||
await new Promise((resolve, reject) => navigator.serviceWorker.addEventListener("message", (event) => {
|
||||
if (event.data && event.data.type === "preload") {
|
||||
if (event.data.status !== "ok") console.log(`turboload failure data=${JSON.stringify(event.data)}`);
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
} catch (err) { console.error(err); }
|
||||
}
|
||||
window.VERSION = "{{ slice .version 0 7 }}::{{ .hash }}";
|
||||
|
||||
try { await import("./assets/boot/warmup.js"); }
|
||||
catch (err) { console.error(err); }
|
||||
|
||||
await Promise.all([
|
||||
import("./assets/{{ .version }}/components/loader.js"),
|
||||
import("./assets/{{ .version }}/components/modal.js"),
|
||||
import("./assets/{{ .version }}/components/notification.js"),
|
||||
import("./assets/{{ .version }}/helpers/loader.js").then(({ loadCSS }) => {
|
||||
loadCSS(import.meta.url, "{{ .base }}assets/{{ .version }}/css/designsystem.css");
|
||||
}),
|
||||
]);
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
|
|
@ -108,7 +79,7 @@
|
|||
// |
|
||||
// | |
|
||||
await ignitionSequence() // |
|
||||
// |
|
||||
// |
|
||||
liftoff() // |
|
||||
// | |
|
||||
// |_____________________________________________|
|
||||
|
|
|
|||
|
|
@ -248,7 +248,6 @@ func ServeBundle() func(*App, http.ResponseWriter, *http.Request) {
|
|||
"/assets/" + BUILD_REF + "/boot/router_frontoffice.js",
|
||||
"/assets/" + BUILD_REF + "/boot/common.js",
|
||||
|
||||
"/assets/" + BUILD_REF + "/css/designsystem.css",
|
||||
"/assets/" + BUILD_REF + "/css/designsystem_input.css",
|
||||
"/assets/" + BUILD_REF + "/css/designsystem_textarea.css",
|
||||
"/assets/" + BUILD_REF + "/css/designsystem_inputgroup.css",
|
||||
|
|
@ -263,6 +262,7 @@ func ServeBundle() func(*App, http.ResponseWriter, *http.Request) {
|
|||
"/assets/" + BUILD_REF + "/css/designsystem_skeleton.css",
|
||||
"/assets/" + BUILD_REF + "/css/designsystem_utils.css",
|
||||
"/assets/" + BUILD_REF + "/css/designsystem_alert.css",
|
||||
"/assets/" + BUILD_REF + "/css/designsystem.css",
|
||||
|
||||
"/assets/" + BUILD_REF + "/components/decorator_shell_filemanager.css",
|
||||
"/assets/" + BUILD_REF + "/components/loader.js",
|
||||
|
|
@ -286,6 +286,7 @@ func ServeBundle() func(*App, http.ResponseWriter, *http.Request) {
|
|||
"/assets/" + BUILD_REF + "/helpers/log.js",
|
||||
"/assets/" + BUILD_REF + "/helpers/sdk.js",
|
||||
|
||||
"/assets/" + BUILD_REF + "/lib/rx.js",
|
||||
"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs.min.js",
|
||||
"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs-ajax.min.js",
|
||||
"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs-shared.min.js",
|
||||
|
|
@ -294,12 +295,11 @@ func ServeBundle() func(*App, http.ResponseWriter, *http.Request) {
|
|||
"/assets/" + BUILD_REF + "/lib/path.js",
|
||||
"/assets/" + BUILD_REF + "/lib/random.js",
|
||||
"/assets/" + BUILD_REF + "/lib/settings.js",
|
||||
"/assets/" + BUILD_REF + "/lib/skeleton/index.js",
|
||||
"/assets/" + BUILD_REF + "/lib/rx.js",
|
||||
"/assets/" + BUILD_REF + "/lib/ajax.js",
|
||||
"/assets/" + BUILD_REF + "/lib/animate.js",
|
||||
"/assets/" + BUILD_REF + "/lib/assert.js",
|
||||
"/assets/" + BUILD_REF + "/lib/dom.js",
|
||||
"/assets/" + BUILD_REF + "/lib/skeleton/index.js",
|
||||
"/assets/" + BUILD_REF + "/lib/skeleton/router.js",
|
||||
"/assets/" + BUILD_REF + "/lib/skeleton/lifecycle.js",
|
||||
"/assets/" + BUILD_REF + "/lib/error.js",
|
||||
|
|
@ -311,6 +311,10 @@ func ServeBundle() func(*App, http.ResponseWriter, *http.Request) {
|
|||
"/assets/" + BUILD_REF + "/model/session.js",
|
||||
"/assets/" + BUILD_REF + "/model/plugin.js",
|
||||
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_logout.js",
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_error.js",
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_homepage.js",
|
||||
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_connectpage.js",
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_connectpage.css",
|
||||
"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form.css",
|
||||
|
|
@ -320,19 +324,18 @@ func ServeBundle() func(*App, http.ResponseWriter, *http.Request) {
|
|||
"/assets/" + BUILD_REF + "/pages/connectpage/model_backend.js",
|
||||
"/assets/" + BUILD_REF + "/pages/connectpage/model_config.js",
|
||||
"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form_state.js",
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_logout.js",
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_error.js",
|
||||
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_filespage.js",
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_filespage.css",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.css",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.css",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.css",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/model_acl.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/cache.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/thing.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/thing.css",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.css",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.css",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/state_config.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/helper.js",
|
||||
|
|
@ -351,13 +354,12 @@ func ServeBundle() func(*App, http.ResponseWriter, *http.Request) {
|
|||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_newitem.js",
|
||||
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_newitem.css",
|
||||
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_viewerpage.js",
|
||||
// "/assets/" + BUILD_REF + "/pages/ctrl_viewerpage.js", // TODO: dynamic imports
|
||||
"/assets/" + BUILD_REF + "/pages/ctrl_viewerpage.css",
|
||||
"/assets/" + BUILD_REF + "/pages/viewerpage/mimetype.js",
|
||||
"/assets/" + BUILD_REF + "/pages/viewerpage/model_files.js",
|
||||
"/assets/" + BUILD_REF + "/pages/viewerpage/common.js",
|
||||
"/assets/" + BUILD_REF + "/pages/viewerpage/application_downloader.js",
|
||||
|
||||
"/assets/" + BUILD_REF + "/pages/viewerpage/component_menubar.js",
|
||||
"/assets/" + BUILD_REF + "/pages/viewerpage/component_menubar.css",
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue