Parallel-load inactive sections alongside JS to cut startup time

Previously all 11 section HTMLs had to complete before JS loading began.
Now only the active section loads first (needed before JS runs so event
listeners find their DOM elements). The other 10 sections fetch in parallel
with utils + settings; an explicit await before the 9-module feature batch
guarantees all section HTML is injected before any feature module sets up
its DOM listeners. On a local server the HTML files finish well before
settings.js completes, so the await is typically instant.

Sequential steps cut from: sections(11∥) + utils + settings + features + ...
                        to: section(1) + max(utils+settings, sections(10∥)) + features + ...

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mARTin-B78 2026-05-29 20:21:35 +02:00
parent 34870fed27
commit c122089ef8

View File

@ -7,9 +7,12 @@
's-llms', 's-conversation',
];
// Determine which section to show first (same logic as nav.js)
var _savedSection = localStorage.getItem('ttsvc_section');
var _activeSection = (_savedSection && SECTIONS.indexOf(_savedSection) !== -1)
? _savedSection : 's-voices';
// ── Fetch app version once for JS cache-busting ──────────────────────────
// JS files are served with ?v=<version> so the browser can cache them
// aggressively. Sections use Date.now() to always get fresh HTML.
var _appVersion = 'dev';
try {
var _vr = await fetch('/api/version');
@ -17,35 +20,50 @@
_appVersion = _vd.version || _appVersion;
} catch (_) {}
// ── 1. Fetch all section HTML partials in parallel ────────────────────────
var _ts = Date.now(); // sections always fresh during a session
await Promise.all(SECTIONS.map(async function (id) {
function _inject(id, html) {
var el = document.getElementById(id);
if (el) el.innerHTML = html;
}
// ── 1. Load ONLY the active section before anything else ─────────────────
// Feature modules set up DOM event listeners — the active section's elements
// must exist when JS runs. Other sections are loaded in step 2.
try {
var _ar = await fetch('/static/sections/' + _activeSection + '.html?v=' + _ts);
if (!_ar.ok) throw new Error(_ar.status + ' ' + _ar.statusText);
_inject(_activeSection, await _ar.text());
} catch (e) {
var _ael = document.getElementById(_activeSection);
if (_ael) _ael.innerHTML =
'<p style="color:var(--red);padding:24px">Failed to load section <b>' +
_activeSection + '</b>: ' + e.message + '</p>';
}
// ── 2. Fetch remaining sections in background (parallel with JS loading) ──
// These run concurrently with utils + settings below. Because section HTML
// files are much smaller than JS, they finish before the feature-module batch
// needs them.
var _bgSections = Promise.all(
SECTIONS.filter(function (id) { return id !== _activeSection; })
.map(async function (id) {
try {
var res = await fetch('/static/sections/' + id + '.html?v=' + _ts);
if (!res.ok) throw new Error(res.status + ' ' + res.statusText);
var el = document.getElementById(id);
if (el) el.innerHTML = await res.text();
_inject(id, await res.text());
} catch (e) {
console.error('[loader] section', id, 'failed:', e.message);
var el = document.getElementById(id);
if (el) el.innerHTML =
'<p style="color:var(--red);padding:24px">Failed to load section <b>' +
id + '</b>: ' + e.message + '</p>';
}
}));
})
);
// ── 2. Load JS in parallel batches ────────────────────────────────────────
// ── 3. Load JS in parallel batches ────────────────────────────────────────
// Scripts with async=false are FETCHED in parallel but EXECUTED in DOM
// insertion order — safe for modules that share a global scope.
//
// Batch order:
// A) utils.js — defines $, toast, escHtml; needed by everything
// B) settings.js — declares _appSettings; needed before features read it
// C) Feature modules — parallel fetch + ordered execute
// D) init.js — calls loadSettings() + initBenchmarkSampleControls()
// E) Post-init modules — parallel fetch + ordered execute
// F) nav.js — navigation overrides; must be last
function _load(src) {
return new Promise(function (resolve, reject) {
var s = document.createElement('script');
@ -58,8 +76,6 @@
}
function _loadBatch(srcs) {
// Append all <script async=false> at once → browser fetches all in parallel
// and executes them in the order they were appended.
return Promise.all(srcs.map(_load));
}
@ -67,6 +83,12 @@
await _load('/static/js/utils.js');
await _load('/static/js/settings.js');
// Wait for background sections BEFORE feature modules run.
// Feature modules set up event listeners on DOM elements; all section HTML
// must already be injected. On a local server the sections finish well before
// settings.js completes, so this await is typically instant.
await _bgSections;
// C — feature modules (9 files fetched in parallel, executed in order)
await _loadBatch([
'/static/js/voice-inspector.js',