aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/lazy.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-25 10:47:37 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-25 10:47:37 +0200
commit0bdce359c0bf19fa98f1b7f9975be32704abe1f0 (patch)
treec67c24b9751c3d8063fc9806a5d6650a3b8c03fb /packages/meshbay-hub/src/meshbay_hub/static/lazy.js
parent950f4aa6d107e127fb6dc0579beedbff0e6f1af5 (diff)
downloadmeshbay-0bdce359c0bf19fa98f1b7f9975be32704abe1f0.tar.gz
feat(client): fetch the media apps, the player, settings and search on first use
apps.js registers Videos, Music, Photos and every settings pane through lazy.js; the group page does the same for the video player and the settings panel, and the shell for the search page. The first download goes from 49 modules / 386 KB gzip to 37 / 289 KB; opening Music now fetches music-app.js and media-tiles.js and nothing of Videos. test_first_load_is_lean holds the eager graph; test_spa_imports checks that every on-demand load names an export that exists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/lazy.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/lazy.js41
1 files changed, 41 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/lazy.js b/packages/meshbay-hub/src/meshbay_hub/static/lazy.js
new file mode 100644
index 0000000..30a564c
--- /dev/null
+++ b/packages/meshbay-hub/src/meshbay_hub/static/lazy.js
@@ -0,0 +1,41 @@
+// A component whose code is fetched the first time it is shown.
+//
+// Every static `import` reachable from app.js is downloaded before anything
+// renders, whether or not the visitor ever opens it: the Videos app, the video
+// player and the search page used to cost a member who only chats. Wrapping a
+// component here moves its module out of that first download and into the
+// moment it is needed; once loaded it is the component itself, rendered with
+// the same props, and every later mount is immediate.
+//
+// A failed fetch (a network drop on a phone) is not remembered: the next time
+// the component is shown it asks again, rather than failing for the session.
+
+import { html, useState, useEffect } from './vendor/htm-preact.js';
+
+const SPINNER = html`<p class="page-message"><span class="spinner"></span></p>`;
+
+function lazy(load, name, placeholder = SPINNER) {
+ let Loaded = null;
+ let pending = null;
+
+ function Lazy(props) {
+ const [, setReady] = useState(Loaded !== null);
+ useEffect(() => {
+ if (Loaded) return undefined;
+ let alive = true;
+ if (!pending) {
+ pending = load().then(
+ (m) => { Loaded = m[name]; },
+ (e) => { pending = null; throw e; });
+ }
+ pending.then(() => { if (alive) setReady(true); }, () => {});
+ return () => { alive = false; };
+ }, []);
+ if (!Loaded) return placeholder;
+ return html`<${Loaded} ...${props} />`;
+ }
+ Lazy.displayName = `Lazy(${name})`;
+ return Lazy;
+}
+
+export { lazy };