diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
index eaeeb096ba..ad4312efbf 100644
--- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
+++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
@@ -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 @@
+
+ (lazyDrawerOpen = false)}>
+
+
+
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
diff --git a/frontend/src/lib/components/apps/editor/RecomputeAllWrapper.svelte b/frontend/src/lib/components/apps/editor/RecomputeAllWrapper.svelte
index 83c1fef5be..46a464d71b 100644
--- a/frontend/src/lib/components/apps/editor/RecomputeAllWrapper.svelte
+++ b/frontend/src/lib/components/apps/editor/RecomputeAllWrapper.svelte
@@ -1,8 +1,6 @@
-{:else}
+{:else if $app.lazyInitRequire == undefined}
{#each $app?.subgrids?.[subGridId] ?? [] as item}
{/each}
diff --git a/frontend/src/lib/components/apps/editor/contextPanel/LazyModePanel.svelte b/frontend/src/lib/components/apps/editor/contextPanel/LazyModePanel.svelte
new file mode 100644
index 0000000000..0ae456e7f8
--- /dev/null
+++ b/frontend/src/lib/components/apps/editor/contextPanel/LazyModePanel.svelte
@@ -0,0 +1,50 @@
+
+
+
+
+ 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.
+
+ 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.
+
+ 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.
+
+
+
{
+ $app.lazyInitRequire = e.detail ? [] : undefined
+ code = JSON.stringify($app.lazyInitRequire)
+ }}
+ options={{
+ right: 'Lazy mode'
+ }}
+ />
+
+
+ {#if $app.lazyInitRequire}
+
+
+ {'e.g: ["a", "b"]'}, no need to put background runnables ids
+
+ {:else}
+ Without lazy mode, all components' initialization will be waited on the initial refresh.
+ {/if}
+
+
diff --git a/frontend/src/lib/components/apps/types.ts b/frontend/src/lib/components/apps/types.ts
index 7debc557f1..c20fe5e561 100644
--- a/frontend/src/lib/components/apps/types.ts
+++ b/frontend/src/lib/components/apps/types.ts
@@ -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>>
subgrids?: Record
theme: AppTheme | undefined
+ lazyInitRequire?: string[] | undefined
hideLegacyTopBar?: boolean | undefined
mobileViewOnSmallerScreens?: boolean | undefined
version?: number