Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⚡️ perf: make app page as static route to improve performance #5478

Merged
merged 3 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ const nextConfig: NextConfig = {
permanent: false,
source: '/repos',
},
{
destination: '/files',
permanent: false,
source: '/repos',
},
],
// when external packages in dev mode with turbopack, this config will lead to bundle error
serverExternalPackages: isProd ? ['@electric-sql/pglite'] : undefined,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@
"vitest": "~1.2.2",
"vitest-canvas-mock": "^0.3.3"
},
"packageManager": "pnpm@9.15.4",
"packageManager": "pnpm@10.2.0",
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Center } from 'react-layout-kit';
import BrandWatermark from '@/components/BrandWatermark';
import { metadataModule } from '@/server/metadata';
import { translation } from '@/server/translation';
import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import Category from './features/Category';
import UserBanner from './features/UserBanner';
Expand All @@ -17,10 +18,10 @@ export const generateMetadata = async () => {
});
};

const Page = async () => {
const mobile = await isMobileDevice();
const Page = async (props: DynamicLayoutProps) => {
const isMobile = await RouteVariants.getIsMobile(props);

if (!mobile) return redirect('/chat');
if (!isMobile) return redirect('/chat');

return (
<>
Expand All @@ -36,3 +37,5 @@ const Page = async () => {
Page.displayName = 'Me';

export default Page;

export const dynamic = 'force-static';
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Cell, { CellProps } from '@/components/Cell';
import { isDeprecatedEdition } from '@/const/version';
import { ProfileTabs } from '@/store/global/initialState';
import { useUserStore } from '@/store/user';
import { authSelectors } from '@/store/user/slices/auth/selectors';
import { authSelectors } from '@/store/user/selectors';

const Category = memo(() => {
const [isLogin, enableAuth, isLoginWithClerk, signOut] = useUserStore((s) => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { redirect } from 'next/navigation';

import { metadataModule } from '@/server/metadata';
import { translation } from '@/server/translation';
import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import Category from './features/Category';

Expand All @@ -15,14 +16,16 @@ export const generateMetadata = async () => {
});
};

const Page = async () => {
const mobile = await isMobileDevice();
const Page = async (props: DynamicLayoutProps) => {
const isMobile = await RouteVariants.getIsMobile(props);

if (!mobile) return redirect('/profile');
if (!isMobile) return redirect('/profile');

return <Category />;
};

Page.displayName = 'MeProfile';

export default Page;

export const dynamic = 'force-static';
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { redirect } from 'next/navigation';

import { metadataModule } from '@/server/metadata';
import { translation } from '@/server/translation';
import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import Category from './features/Category';

Expand All @@ -15,14 +16,16 @@ export const generateMetadata = async () => {
});
};

const Page = async () => {
const mobile = await isMobileDevice();
const Page = async (props: DynamicLayoutProps) => {
const isMobile = await RouteVariants.getIsMobile(props);

if (!mobile) return redirect('/settings/common');
if (!isMobile) return redirect('/settings/common');

return <Category />;
};

Page.displayName = 'MeSettings';

export default Page;

export const dynamic = 'force-static';
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { SideNav } from '@lobehub/ui';
import { parseAsBoolean, useQueryState } from 'nuqs';
import { memo } from 'react';
import { Suspense, memo } from 'react';

import { useActiveTabKey } from '@/hooks/useActiveTabKey';
import { useGlobalStore } from '@/store/global';
Expand All @@ -14,11 +14,16 @@ import BottomActions from './BottomActions';
import PinList from './PinList';
import TopActions from './TopActions';

const Nav = memo(() => {
const Top = () => {
const [isPinned] = useQueryState('pinned', parseAsBoolean);
const sidebarKey = useActiveTabKey();

return <TopActions isPinned={isPinned} tab={sidebarKey} />;
};

const Nav = memo(() => {
const inZenMode = useGlobalStore(systemStatusSelectors.inZenMode);
const { showPinList } = useServerConfigStore(featureFlagsSelectors);
const [isPinned] = useQueryState('pinned', parseAsBoolean);

return (
!inZenMode && (
Expand All @@ -27,10 +32,10 @@ const Nav = memo(() => {
bottomActions={<BottomActions />}
style={{ height: '100%', zIndex: 100 }}
topActions={
<>
<TopActions isPinned={isPinned} tab={sidebarKey} />
<Suspense>
<Top />
{showPinList && <PinList />}
</>
</Suspense>
}
/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import dynamic from 'next/dynamic';
import { usePathname } from 'next/navigation';
import qs from 'query-string';
import { PropsWithChildren, memo } from 'react';

import { withSuspense } from '@/components/withSuspense';
import { useShowMobileWorkspace } from '@/hooks/useShowMobileWorkspace';
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';

Expand All @@ -24,8 +24,7 @@ const MOBILE_NAV_ROUTES = new Set([
const Layout = memo(({ children }: PropsWithChildren) => {
const showMobileWorkspace = useShowMobileWorkspace();
const pathname = usePathname();
const { url } = qs.parseUrl(pathname);
const showNav = !showMobileWorkspace && MOBILE_NAV_ROUTES.has(url);
const showNav = !showMobileWorkspace && MOBILE_NAV_ROUTES.has(pathname);

const { showCloudPromotion } = useServerConfigStore(featureFlagsSelectors);

Expand All @@ -40,4 +39,4 @@ const Layout = memo(({ children }: PropsWithChildren) => {

Layout.displayName = 'MobileMainLayout';

export default Layout;
export default withSuspense(Layout);
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useLayoutEffect } from 'react';

import { withSuspense } from '@/components/withSuspense';
import { useQueryRoute } from '@/hooks/useQueryRoute';

/**
Expand All @@ -10,7 +11,7 @@ import { useQueryRoute } from '@/hooks/useQueryRoute';
* @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
*/

const ChangelogModalFallback = () => {
const ChangelogModal = () => {
const router = useQueryRoute();

useLayoutEffect(() => {
Expand All @@ -20,4 +21,4 @@ const ChangelogModalFallback = () => {
return null;
};

export default ChangelogModalFallback;
export default withSuspense(ChangelogModal);
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Fragment, Suspense } from 'react';
import { Flexbox } from 'react-layout-kit';
import urlJoin from 'url-join';

import Pagination from '@/app/@modal/(.)changelog/modal/features/Pagination';
import Pagination from '@/app/[variants]/@modal/(.)changelog/modal/features/Pagination';
import StructuredData from '@/components/StructuredData';
import { serverFeatureFlags } from '@/config/featureFlags';
import { BRANDING_NAME } from '@/const/branding';
Expand All @@ -13,7 +13,8 @@ import { ldModule } from '@/server/ld';
import { metadataModule } from '@/server/metadata';
import { ChangelogService } from '@/server/services/changelog';
import { translation } from '@/server/translation';
import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import GridLayout from './features/GridLayout';
import Post from './features/Post';
Expand All @@ -28,12 +29,12 @@ export const generateMetadata = async () => {
});
};

const Page = async () => {
const Page = async (props: DynamicLayoutProps) => {
const hideDocs = serverFeatureFlags().hideDocs;

if (hideDocs) return notFound();

const mobile = await isMobileDevice();
const isMobile = await RouteVariants.getIsMobile(props);
const { t, locale } = await translation('metadata');
const changelogService = new ChangelogService();
const data = await changelogService.getChangelogIndex();
Expand All @@ -49,7 +50,7 @@ const Page = async () => {
return (
<>
<StructuredData ld={ld} />
<Flexbox gap={mobile ? 16 : 48}>
<Flexbox gap={isMobile ? 16 : 48}>
{data?.map((item) => (
<Fragment key={item.id}>
<Suspense
Expand All @@ -60,7 +61,7 @@ const Page = async () => {
</GridLayout>
}
>
<Post locale={locale} mobile={mobile} {...item} />
<Post locale={locale} mobile={isMobile} {...item} />
</Suspense>
</Fragment>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import ChatHydration from './features/ChatHydration';
import ChatInput from './features/ChatInput';
import ChatList from './features/ChatList';
import ThreadHydration from './features/ThreadHydration';
import ZenModeToast from './features/ZenModeToast';

const ChatConversation = async () => {
const mobile = await isMobileDevice();
const ChatConversation = async (props: DynamicLayoutProps) => {
const isMobile = await RouteVariants.getIsMobile(props);

return (
<>
<ZenModeToast />
<ChatList mobile={mobile} />
<ChatInput mobile={mobile} />
<ChatList mobile={isMobile} />
<ChatInput mobile={isMobile} />
<ChatHydration />
<ThreadHydration />
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React, { Suspense, lazy } from 'react';

import Loading from '@/components/Loading/BrandTextLoading';
import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import Desktop from './_layout/Desktop';
import Mobile from './_layout/Mobile';

const PortalBody = lazy(() => import('@/features/Portal/router'));

const Inspector = async () => {
const mobile = await isMobileDevice();
const Inspector = async (props: DynamicLayoutProps) => {
const isMobile = await RouteVariants.getIsMobile(props);

const Layout = mobile ? Mobile : Desktop;
const Layout = isMobile ? Mobile : Desktop;

return (
<Suspense fallback={<Loading />}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// import TopicListContent from './features/TopicListContent';
import React, { Suspense, lazy } from 'react';

import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import Desktop from './_layout/Desktop';
import Mobile from './_layout/Mobile';
Expand All @@ -10,14 +11,14 @@ import SystemRole from './features/SystemRole';

const TopicContent = lazy(() => import('./features/TopicListContent'));

const Topic = async () => {
const mobile = await isMobileDevice();
const Topic = async (props: DynamicLayoutProps) => {
const isMobile = await RouteVariants.getIsMobile(props);

const Layout = mobile ? Mobile : Desktop;
const Layout = isMobile ? Mobile : Desktop;

return (
<>
{!mobile && <SystemRole />}
{!isMobile && <SystemRole />}
<Layout>
<Suspense fallback={<SkeletonList />}>
<TopicContent />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { MobileNavBar } from '@lobehub/ui/mobile';
import { memo, useState } from 'react';

import { useInitAgentConfig } from '@/app/(main)/chat/(workspace)/_layout/useInitAgentConfig';
import { useInitAgentConfig } from '@/app/[variants]/(main)/chat/(workspace)/_layout/useInitAgentConfig';
import { INBOX_SESSION_ID } from '@/const/session';
import { useQueryRoute } from '@/hooks/useQueryRoute';
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { BRANDING_NAME } from '@/const/branding';
import { ldModule } from '@/server/ld';
import { metadataModule } from '@/server/metadata';
import { translation } from '@/server/translation';
import { isMobileDevice } from '@/utils/server/responsive';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';

import PageTitle from '../features/PageTitle';
import Changelog from './features/ChangelogModal';
Expand All @@ -21,9 +22,9 @@ export const generateMetadata = async () => {
});
};

const Page = async () => {
const Page = async (props: DynamicLayoutProps) => {
const { hideDocs, showChangelog } = serverFeatureFlags();
const mobile = await isMobileDevice();
const mobile = await RouteVariants.getIsMobile(props);
const { t } = await translation('metadata');
const ld = ldModule.generate({
description: t('chat.description', { appName: BRANDING_NAME }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Suspense, lazy } from 'react';

import CircleLoading from '@/components/Loading/CircleLoading';
import ServerLayout from '@/components/server/ServerLayout';
import { DynamicLayoutProps } from '@/types/next';

import Desktop from './_layout/Desktop';
import Mobile from './_layout/Mobile';
Expand All @@ -12,10 +13,10 @@ const SessionListContent = lazy(() => import('./features/SessionListContent'));

const Layout = ServerLayout({ Desktop, Mobile });

const Session = () => {
const Session = (props: DynamicLayoutProps) => {
return (
<Suspense fallback={<CircleLoading />}>
<Layout>
<Layout {...props}>
<Suspense fallback={<SkeletonList />}>
<SessionListContent />
</Suspense>
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ const Layout = ServerLayout<LayoutProps>({ Desktop, Mobile });
Layout.displayName = 'ChatLayout';

export default Layout;

export const dynamic = 'force-static';
Loading
Loading