- Apply consistent prefix naming: AE__, GUIDE__, PROJECT__, MODULE__, TODO__ - Move superseded/session docs to documentation/history/ - Migrate old/ directory contents to history/ with updated naming - README.md: replace stale Modules section with accurate current routes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.8 KiB
Performance Guidelines: Non-Blocking Load Pattern (SvelteKit + Dexie)
Overview
To ensure instant page transitions and a high-performance feel, the Aether platform utilizes a Non-Blocking Load Pattern (also known as Stale-While-Revalidate or SWR). This pattern leverages Dexie's liveQuery for reactive UI and SvelteKit's load functions for background data synchronization.
🚀 The Core Principle
Never block the load function with API calls if the data is already being observed by a liveQuery.
The page should render instantly using cached data from IndexedDB. Fresh data from the API should settle in the background and update the UI automatically via reactivity.
❌ Anti-Pattern (Blocking)
This pattern causes a "white screen" or "frozen UI" while the browser waits for the API response.
// +page.ts
export async function load({ params, parent }) {
const data = await parent();
const event_id = params.event_id;
// BAD: This blocks the navigation until the API responds.
const fresh_data = await events_func.load_ae_obj_id__event({
event_id: event_id,
try_cache: true
});
return { ...data, event_obj: fresh_data };
}
✅ Best Practice (Non-Blocking / SWR)
This pattern completes the navigation immediately.
// +page.ts
export async function load({ params, parent }) {
const data = await parent();
const event_id = params.event_id;
if (browser) {
// GOOD: Fire and forget.
// This function updates IndexedDB in the background.
events_func.load_ae_obj_id__event({
event_id: event_id,
try_cache: true
});
}
return data; // Navigation completes instantly
}
<!-- +page.svelte -->
<script lang="ts">
import { liveQuery } from 'dexie';
import { db_events } from '$lib/ae_events/db_events';
// UI reacts automatically when the background task finishes.
let lq__event_obj = $derived(
liveQuery(() => db_events.event.get(event_id))
);
</script>
{#if $lq__event_obj}
<h1>{$lq__event_obj.name}</h1>
{:else}
<p>Loading...</p>
{/if}
🛠️ When to use Await
Use await in load functions ONLY for:
- Critical Auth Checks: If you must verify a session before even showing a layout.
- Parent Data:
const data = await parent();is necessary to build the context. - Server-Side Rendering (SSR): If the data must be present in the initial HTML for SEO (rare for Aether feature modules).
📈 Performance Gains
By adopting this pattern across the Events module, we achieved:
- ~200-500ms reduction in perceived page load time.
- Elimination of waterfalls (sequential API calls).
- Better offline support, as the UI is always ready to show what's in the local cache.