diff --git a/apps/nextjs/src/components/layout/header/lazy-spotlight.tsx b/apps/nextjs/src/components/layout/header/lazy-spotlight.tsx
index aff8496e9..5fbc9f5ed 100644
--- a/apps/nextjs/src/components/layout/header/lazy-spotlight.tsx
+++ b/apps/nextjs/src/components/layout/header/lazy-spotlight.tsx
@@ -1,14 +1,21 @@
"use client";
import { useEffect, useState } from "react";
+import dynamic from "next/dynamic";
import { useHotkeys } from "@mantine/hooks";
import { hotkeys } from "@homarr/definitions";
-import { Spotlight } from "@homarr/spotlight/component";
import { hasPendingSpotlightOpen, openSpotlight, spotlightOpenEvent } from "@homarr/spotlight/open";
+const loadSpotlight = () => import("@homarr/spotlight/component");
+const Spotlight = dynamic(() => loadSpotlight().then(({ Spotlight: Component }) => Component), {
+ ssr: false,
+ loading: () => null,
+});
+
export const LazySpotlight = () => {
const [isMounted, setIsMounted] = useState(false);
+ const [isPreloaded, setIsPreloaded] = useState(false);
useHotkeys(
isMounted
@@ -25,27 +32,41 @@ export const LazySpotlight = () => {
);
useEffect(() => {
+ let isActive = true;
const mount = () => setIsMounted(true);
window.addEventListener(spotlightOpenEvent, mount);
if (hasPendingSpotlightOpen()) mount();
+ const preload = () => {
+ void loadSpotlight().then(
+ () => {
+ if (isActive) setIsPreloaded(true);
+ },
+ () => undefined,
+ );
+ };
let idleId: number | undefined;
const delayId = window.setTimeout(() => {
- idleId = window.requestIdleCallback?.(mount, { timeout: 1_000 });
- if (idleId === undefined) mount();
+ idleId = window.requestIdleCallback?.(preload, { timeout: 1_000 });
+ if (idleId === undefined) preload();
}, 1_000);
return () => {
+ isActive = false;
window.removeEventListener(spotlightOpenEvent, mount);
window.clearTimeout(delayId);
if (idleId !== undefined) window.cancelIdleCallback?.(idleId);
};
}, []);
- return isMounted ? (
+ return isMounted || isPreloaded ? (
<>
-
-
-
+ {isPreloaded && }
+ {isMounted && (
+ <>
+
+
+ >
+ )}
>
) : null;
};