perf(frontend): route-level code splitting, main chunk 538 -> 491 KB
Lighthouse (production, default mobile 4x-CPU profile) scored Performance 33/100, dominated by one ~536-538 KB entry chunk that bundled every route's code regardless of which page a visitor landed on -- the "chunks are larger than 500 kB" Vite warning on every build this session. Converted every route except / and the 404 catch-all to React Router 8's native route.lazy (blocks navigation until the chunk is ready -- no separate Suspense fallback needed). AppShell/HomePage/NotFoundPage/ RequireAuth stay eager since they're needed on every load regardless. Result: main chunk 490.84 KB, no >500kB warning, one small chunk per route (LoginPage 1.4 KB, ThemesPage 15.5 KB, AccountPage 11 KB, etc.) loaded only when actually visited. Fixed a real race the lazy boundary exposed: /login and /register share an "Почта" field label, and during the chunk swap between them the old page can stay mounted a beat longer than before -- a test grabbing the field by label could land on the about-to-unmount one. Also bumped RTL's asyncUtilTimeout and vitest's testTimeout, since the route-transition + findBy chain didn't always land inside the old 1000/5000ms defaults under full parallel test-suite load. Claude-Session: https://claude.ai/code/session_01F1M1Jic1wTSn4igUENynmZ
This commit is contained in:
parent
6b0633034d
commit
b170227adf
4 changed files with 34 additions and 23 deletions
|
|
@ -1,38 +1,36 @@
|
|||
import type { ComponentType } from 'react'
|
||||
import type { RouteObject } from 'react-router'
|
||||
import { RequireAuth } from '@features/auth/RequireAuth'
|
||||
import { AppShell } from '@shared/layout/AppShell'
|
||||
import HomePage from '@pages/public/HomePage'
|
||||
import LoginPage from '@pages/public/auth/LoginPage'
|
||||
import RegisterPage from '@pages/public/auth/RegisterPage'
|
||||
import ProfilePage from '@pages/public/ProfilePage'
|
||||
import NotFoundPage from '@pages/public/NotFoundPage'
|
||||
// Code-split: the download page pulls in react-markdown, so it loads on demand.
|
||||
import DownloadRoute from '@pages/download/DownloadRoute'
|
||||
import AccountPage from '@pages/app/AccountPage'
|
||||
import LinkPage from '@pages/app/LinkPage'
|
||||
import ThemesRoute from '@pages/themes/ThemesRoute'
|
||||
import ConfigsPage from '@pages/app/ConfigsPage'
|
||||
import ShowcaseRoute from '@pages/showcase/ShowcaseRoute'
|
||||
import ListingRoute from '@pages/showcase/ListingRoute'
|
||||
|
||||
// Adapts a page module's default export to the shape React Router's `lazy` expects.
|
||||
function toRoute(m: { default: ComponentType }) {
|
||||
return { Component: m.default }
|
||||
}
|
||||
|
||||
// Everything below is route-level code-split via React Router's `lazy` field:
|
||||
// each page's JS only downloads when a visitor actually navigates to it, so the
|
||||
// initial bundle only carries the app shell + the home page.
|
||||
export const routes: RouteObject[] = [
|
||||
{
|
||||
element: <AppShell />,
|
||||
children: [
|
||||
{ path: '/', element: <HomePage /> },
|
||||
{ path: '/login', element: <LoginPage /> },
|
||||
{ path: '/register', element: <RegisterPage /> },
|
||||
{ path: '/download', element: <DownloadRoute /> },
|
||||
{ path: '/themes', element: <ThemesRoute /> },
|
||||
{ path: '/u/:id', element: <ProfilePage /> },
|
||||
{ path: '/showcase', element: <ShowcaseRoute /> },
|
||||
{ path: '/showcase/:id', element: <ListingRoute /> },
|
||||
{ path: '/login', lazy: () => import('@pages/public/auth/LoginPage').then(toRoute) },
|
||||
{ path: '/register', lazy: () => import('@pages/public/auth/RegisterPage').then(toRoute) },
|
||||
{ path: '/download', lazy: () => import('@pages/download/DownloadRoute').then(toRoute) },
|
||||
{ path: '/themes', lazy: () => import('@pages/themes/ThemesRoute').then(toRoute) },
|
||||
{ path: '/u/:id', lazy: () => import('@pages/public/ProfilePage').then(toRoute) },
|
||||
{ path: '/showcase', lazy: () => import('@pages/showcase/ShowcaseRoute').then(toRoute) },
|
||||
{ path: '/showcase/:id', lazy: () => import('@pages/showcase/ListingRoute').then(toRoute) },
|
||||
{
|
||||
element: <RequireAuth />,
|
||||
children: [
|
||||
{ path: '/link', element: <LinkPage /> },
|
||||
{ path: '/account', element: <AccountPage /> },
|
||||
{ path: '/configs', element: <ConfigsPage /> },
|
||||
{ path: '/link', lazy: () => import('@pages/app/LinkPage').then(toRoute) },
|
||||
{ path: '/account', lazy: () => import('@pages/app/AccountPage').then(toRoute) },
|
||||
{ path: '/configs', lazy: () => import('@pages/app/ConfigsPage').then(toRoute) },
|
||||
],
|
||||
},
|
||||
{ path: '*', element: <NotFoundPage /> },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue