feat: lazy mode

This commit is contained in:
Ruben Fiszel
2025-02-11 20:38:13 +01:00
parent bb11bfe874
commit 7c4b8a7e1d
6 changed files with 92 additions and 25 deletions
@@ -31,7 +31,8 @@
FileClock,
Sun,
Moon,
SunMoon
SunMoon,
Zap
} from 'lucide-svelte'
import { createEventDispatcher, getContext } from 'svelte'
import { Pane, Splitpanes } from 'svelte-splitpanes'
@@ -92,6 +93,7 @@
import { isCloudHosted } from '$lib/cloud'
import { base } from '$lib/base'
import ClipboardPanel from '$lib/components/details/ClipboardPanel.svelte'
import LazyModePanel from './contextPanel/LazyModePanel.svelte'
async function hash(message) {
try {
@@ -175,6 +177,7 @@
let inputsDrawerOpen = fromHub
let historyBrowserDrawerOpen = false
let debugAppDrawerOpen = false
let lazyDrawerOpen = false
let deploymentMsg: string | undefined = undefined
function closeSaveDrawer() {
@@ -871,6 +874,13 @@
action: () => {
debugAppDrawerOpen = true
}
},
{
displayName: 'Lazy mode',
icon: Zap,
action: () => {
lazyDrawerOpen = true
}
}
]
@@ -1267,6 +1277,11 @@
</DrawerContent>
</Drawer>
<Drawer bind:open={lazyDrawerOpen} size="800px">
<DrawerContent title="Lazy Mode" on:close={() => (lazyDrawerOpen = false)}>
<LazyModePanel />
</DrawerContent>
</Drawer>
<Drawer bind:open={$jobsDrawerOpen} size="900px">
<DrawerContent
noPadding
@@ -1,7 +1,7 @@
<script lang="ts">
import { getContext, onMount } from 'svelte'
import type { AppEditorContext, AppViewerContext } from '../types'
import { allItems } from '../utils'
import type { App, AppEditorContext, AppViewerContext } from '../types'
import { allItems, BG_PREFIX } from '../utils'
import RecomputeAllButton from './RecomputeAllButton.svelte'
const { runnableComponents, app, initialized, recomputeAllContext } =
@@ -13,10 +13,21 @@
let firstLoad = false
let progressTimer: NodeJS.Timeout | undefined = undefined
$: !firstLoad &&
$initialized.initializedComponents?.length ==
allItems($app.grid, $app.subgrids).length + ($app.hiddenInlineScripts?.length ?? 0) &&
refresh()
$: !firstLoad && canInitializeAll($initialized?.initializedComponents, $app) && refresh()
function canInitializeAll(initialized: string[] | undefined, app: App) {
if (app.lazyInitRequire == undefined) {
return (
initialized?.length ==
allItems(app.grid, app.subgrids).length + (app.hiddenInlineScripts?.length ?? 0)
)
} else {
return (
app.hiddenInlineScripts?.every((x, i) => initialized?.includes(BG_PREFIX + i)) &&
app.lazyInitRequire?.every((x) => initialized?.includes(x))
)
}
}
$: $recomputeAllContext.componentNumber =
Object.values($runnableComponents).filter((x) => x.autoRefresh).length ?? 0
@@ -1,8 +1,6 @@
<script lang="ts">
import { getContext } from 'svelte'
import type { AppViewerContext } from '../types'
import { dfs } from './appUtils'
import { deepEqual } from 'fast-equals'
import { Loader2 } from 'lucide-svelte'
import Popover from '$lib/components/Popover.svelte'
import { twMerge } from 'tailwind-merge'
@@ -11,16 +9,8 @@
export let containerClass: string | undefined = undefined
export let containerStyle: string | undefined = undefined
const { selectedComponent, app, connectingInput, allIdsInPath, bgRuns, recomputeAllContext } =
const { connectingInput, bgRuns, recomputeAllContext } =
getContext<AppViewerContext>('AppViewerContext')
let previousSelectedIds: string[] | undefined = undefined
$: if (!deepEqual(previousSelectedIds, $selectedComponent)) {
previousSelectedIds = $selectedComponent
$allIdsInPath = ($selectedComponent ?? [])
.flatMap((id) => dfs($app.grid, id, $app.subgrids ?? {}))
.filter((x) => x != undefined) as string[]
}
</script>
<div
@@ -329,7 +329,7 @@
{/if}
</div>
</div>
{:else}
{:else if $app.lazyInitRequire == undefined}
{#each $app?.subgrids?.[subGridId] ?? [] as item}
<Component render={false} component={item.data} id={item.id} />
{/each}
@@ -0,0 +1,50 @@
<script lang="ts">
import { getContext } from 'svelte'
import type { AppViewerContext } from '../../types'
import Alert from '$lib/components/common/alert/Alert.svelte'
import Toggle from '$lib/components/Toggle.svelte'
import JsonEditor from '$lib/components/JsonEditor.svelte'
import Section from '$lib/components/Section.svelte'
const { app } = getContext<AppViewerContext>('AppViewerContext')
let code = JSON.stringify($app.lazyInitRequire)
</script>
<div class="flex flex-col gap-8" style="all:none;">
<Alert type="info" title="Lazy mode for large apps performance">
Lazy mode is a feature that allows you to lazy render components which is ideal for apps with
many components where most are not directly visible to the user.
<br />
When lazy mode is enabled, components are not rendered until they are needed. This can significantly
improve the performance of your app, especially on mobile devices.
<br />
You can enable lazy mode below, but you will need to declare the list of components whose initialization
is expected to see initialized before the initial refresh of the app happens.
</Alert>
<Toggle
label="Lazy mode"
value={Boolean($app.lazyInitRequire)}
on:change={(e) => {
$app.lazyInitRequire = e.detail ? [] : undefined
code = JSON.stringify($app.lazyInitRequire)
}}
options={{
right: 'Lazy mode'
}}
/>
<Section label="Component ids to wait the initialization of before the initial refresh">
{#if $app.lazyInitRequire}
<JsonEditor bind:value={$app.lazyInitRequire} {code} />
<span class="text-tertiary text-xs">
{'e.g: ["a", "b"]'}, no need to put background runnables ids
</span>
{:else}
<span class="text-tertiary"
>Without lazy mode, all components' initialization will be waited on the initial refresh.</span
>
{/if}
</Section>
</div>
+7 -6
View File
@@ -139,13 +139,13 @@ export type HiddenRunnable = {
export type AppTheme =
| {
type: 'path'
path: string
}
type: 'path'
path: string
}
| {
type: 'inlined'
css: string
}
type: 'inlined'
css: string
}
export type App = {
grid: GridItem[]
@@ -162,6 +162,7 @@ export type App = {
css?: Partial<Record<AppCssItemName, Record<string, ComponentCssProperty>>>
subgrids?: Record<string, GridItem[]>
theme: AppTheme | undefined
lazyInitRequire?: string[] | undefined
hideLegacyTopBar?: boolean | undefined
mobileViewOnSmallerScreens?: boolean | undefined
version?: number