aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-10 10:42:36 +0100
committerDanilo M. <danix@danix.xyz>2026-11-10 10:42:36 +0100
commite3583dca51ce4b1e5d045147d939a0544622b194 (patch)
treef52d1a89892f6678ea1d9fe2782e621661fb8d99
parent84916f24d22cc32b5f51bbc7794b37848469edc8 (diff)
downloaddeck-it-e3583dca51ce4b1e5d045147d939a0544622b194.tar.gz
deck-it-e3583dca51ce4b1e5d045147d939a0544622b194.zip
perf: load and mount panels in parallel
Boot imported, mounted and awaited the first poll of each panel in turn, so one slow source (the build VM over ssh, a printer that is off) held back every panel after it, and tabs appeared one by one. All panel code is now imported at once, panels mount in the server's order so cards and tabs do not shuffle, and first polls run without being awaited. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--static/app.js35
1 files changed, 19 insertions, 16 deletions
diff --git a/static/app.js b/static/app.js
index 31083a6..2f61c81 100644
--- a/static/app.js
+++ b/static/app.js
@@ -222,7 +222,9 @@ function makeCard(name, title) {
return body;
}
-async function startPoll(name, panel, el) {
+// The first poll is not awaited: a slow source (the build VM over ssh, a
+// printer that is off) must not hold back the other panels.
+function startPoll(name, panel, el) {
const poll = async () => {
try {
const r = await fetch(`/api/${name}`);
@@ -232,42 +234,43 @@ async function startPoll(name, panel, el) {
}
};
refreshers.push(poll);
- await poll();
+ poll();
setInterval(poll, (panel.interval ?? 1) * 1000);
}
-async function mountDashboard(name, panel) {
+function mountDashboard(name, panel) {
const body = makeCard(name, panel.title ?? name);
panel.mount?.(body);
- await startPoll(name, panel, body);
+ startPoll(name, panel, body);
}
-async function mountTab(name, panel, section) {
+function mountTab(name, panel, section) {
const wrap = document.createElement("div");
wrap.className = "tab-content";
section.append(wrap);
panel.mount?.(wrap);
- await startPoll(name, panel, wrap);
+ startPoll(name, panel, wrap);
}
async function boot() {
const r = await fetch("/api/modules");
if (!r.ok) return;
- for (const { name } of await r.json()) {
- let panel;
- try {
- panel = (await import(`./modules/${name}.js`)).default;
- } catch {
- continue;
- }
+ // Every panel's code at once; then mount in the server's order, so the
+ // cards and tabs do not shuffle with whichever import lands first.
+ const names = (await r.json()).map(({ name }) => name);
+ const loaded = await Promise.all(names.map((name) =>
+ import(`./modules/${name}.js`).then((m) => m.default, () => null)));
+ names.forEach((name, i) => {
+ const panel = loaded[i];
+ if (!panel) return;
const tabName = panel.tab ?? "Dashboard";
try {
- if (tabName === "Dashboard") await mountDashboard(name, panel);
- else await mountTab(name, panel, ensureTab(tabName).section);
+ if (tabName === "Dashboard") mountDashboard(name, panel);
+ else mountTab(name, panel, ensureTab(tabName).section);
} catch {
// a broken panel must not take down the rest of the dashboard
}
- }
+ });
closeGaps();
ready = true;
saveLayout();