diff options
| author | Danilo M. <danix@danix.xyz> | 2026-11-10 10:42:36 +0100 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-11-10 10:42:36 +0100 |
| commit | e3583dca51ce4b1e5d045147d939a0544622b194 (patch) | |
| tree | f52d1a89892f6678ea1d9fe2782e621661fb8d99 | |
| parent | 84916f24d22cc32b5f51bbc7794b37848469edc8 (diff) | |
| download | deck-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.js | 35 |
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(); |
