From 4058a8014111aa09df342d61c437863c446a8d39 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 13 Aug 2025 14:24:13 -0600 Subject: [PATCH] lazy load dev tools --- .../features/global/LazyGlobalErrorCard.tsx | 15 +++++- .../src/components/ui/modal/ModalBase.tsx | 2 +- .../BusterNotifications.tsx | 4 +- .../tanstack-devtools-impl.tsx | 31 +++++++++++ .../tanstack-dev-tools/tanstack-devtools.tsx | 53 +++++++++++-------- apps/web-tss/vite.config.ts | 16 ++++++ 6 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools-impl.tsx diff --git a/apps/web-tss/src/components/features/global/LazyGlobalErrorCard.tsx b/apps/web-tss/src/components/features/global/LazyGlobalErrorCard.tsx index a5ce5e45f..ebd977992 100644 --- a/apps/web-tss/src/components/features/global/LazyGlobalErrorCard.tsx +++ b/apps/web-tss/src/components/features/global/LazyGlobalErrorCard.tsx @@ -1,5 +1,5 @@ import type { ErrorRouteComponent } from '@tanstack/react-router'; -import { lazy, Suspense } from 'react'; +import { lazy, Suspense, useEffect, useState } from 'react'; // Lazy load the GlobalErrorCard component const GlobalErrorCard = lazy(() => @@ -13,6 +13,19 @@ const ErrorLoadingFallback = () =>
; // Wrapper component that handles lazy loading with Suspense export const LazyGlobalErrorCard: ErrorRouteComponent = (props) => { + // Track if we're on the client side + const [isClient, setIsClient] = useState(false); + + useEffect(() => { + // Set to true only after mount (client-side only) + setIsClient(true); + }, []); + + // During SSR, render the fallback directly to avoid hydration mismatch + if (!isClient) { + return ; + } + return ( }> diff --git a/apps/web-tss/src/components/ui/modal/ModalBase.tsx b/apps/web-tss/src/components/ui/modal/ModalBase.tsx index b68564423..4f3831b89 100644 --- a/apps/web-tss/src/components/ui/modal/ModalBase.tsx +++ b/apps/web-tss/src/components/ui/modal/ModalBase.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import { Xmark } from '@/components/ui/icons'; import { cn } from '@/lib/utils'; -import { Button } from '../buttons'; +import { Button } from '../buttons/Button'; const Dialog = DialogPrimitive.Root; diff --git a/apps/web-tss/src/context/BusterNotifications/BusterNotifications.tsx b/apps/web-tss/src/context/BusterNotifications/BusterNotifications.tsx index 866e8bf26..263ea42d6 100644 --- a/apps/web-tss/src/context/BusterNotifications/BusterNotifications.tsx +++ b/apps/web-tss/src/context/BusterNotifications/BusterNotifications.tsx @@ -4,7 +4,7 @@ import type React from 'react'; import type { PropsWithChildren } from 'react'; import { type ExternalToast, toast } from 'sonner'; import { createContext, useContextSelector } from 'use-context-selector'; -// import { ConfirmModal } from '@/components/ui/modal/ConfirmModal'; +import { ConfirmModal } from '@/components/ui/modal/ConfirmModal'; import { Toaster } from '@/components/ui/toaster/Toaster'; import { useOpenConfirmModal } from './useConfirmModal'; @@ -134,7 +134,7 @@ export const BusterNotificationsProvider: React.FC = ({ child {children} - {/* */} + ); }; diff --git a/apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools-impl.tsx b/apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools-impl.tsx new file mode 100644 index 000000000..1bff661ed --- /dev/null +++ b/apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools-impl.tsx @@ -0,0 +1,31 @@ +import { TanstackDevtools as TanstackDevtoolsBase } from '@tanstack/react-devtools'; +import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'; +import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; +import type React from 'react'; +import StoreDevtools from './demo-store-devtools'; + +// The actual devtools component implementation +const TanstackDevtoolsImpl: React.FC = () => { + return ( + , + }, + { + name: 'Tanstack Router', + render: , + }, + StoreDevtools, + ]} + /> + ); +}; + +export default TanstackDevtoolsImpl; diff --git a/apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools.tsx b/apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools.tsx index 074820a7e..4f5a755a1 100644 --- a/apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools.tsx +++ b/apps/web-tss/src/integrations/tanstack-dev-tools/tanstack-devtools.tsx @@ -1,28 +1,37 @@ -import { TanstackDevtools as TanstackDevtoolsBase } from '@tanstack/react-devtools'; -import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'; -import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; import type React from 'react'; -import StoreDevtools from './demo-store-devtools'; +import { lazy, Suspense, useEffect, useState } from 'react'; +import { useHotkeys } from 'react-hotkeys-hook'; +// Lazy load the actual devtools component +const LazyTanstackDevtools = lazy(() => + import('./tanstack-devtools-impl').then((mod) => ({ + default: mod.default, + })) +); + +// Export component with Suspense wrapper export const TanstackDevtools: React.FC = () => { + // Track if we're on the client side + const [mounted, setMounted] = useState(false); + const [useDevTools, setUseDevTools] = useState(false); + + useEffect(() => { + // Set to true only after mount (client-side only) + setMounted(true); + }, []); + + useHotkeys('shift+alt+d', () => { + setUseDevTools(true); + }); + + // Only render in development and on the client + if (!mounted || !useDevTools) { + return null; + } + return ( - , - }, - { - name: 'Tanstack Router', - render: , - }, - StoreDevtools, - ]} - /> + + + ); }; diff --git a/apps/web-tss/vite.config.ts b/apps/web-tss/vite.config.ts index 8e838f476..61494029d 100644 --- a/apps/web-tss/vite.config.ts +++ b/apps/web-tss/vite.config.ts @@ -35,6 +35,22 @@ const config = defineConfig({ if (id.includes('node_modules/@supabase')) { return 'vendor-supabase'; } + + if (id.includes('components/ui/icons')) { + return 'vendor-icons'; + } + + if (id.includes('components/ui')) { + return 'vendor-ui'; + } + + if (id.includes('zod')) { + return 'vendor-zod'; + } + + if (id.includes('@tanstack')) { + return 'vendor-tanstack'; + } }, }, },