From 07a1425fee069772061c9d7f4d9c30c198013516 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Mon, 25 May 2026 16:20:53 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F(frontend)=20lazy=20load=20ro?= =?UTF-8?q?utes=20to=20shrink=20the=20initial=20JS=20chunk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One of the best ways to reduce the size of the initially loaded chunk (index.js, around 2Mo before optimization) is to lazy load routes and features so their JS gets isolated in dedicated chunks and is loaded only when needed. For example, most of the JS under the legal terms page is never consulted by users. Likewise, when loading the home page, there is no need for all the feature-related JS required to display a videoconference. After this lazy-loading optimization, the initial chunk is now around 1.2Mo, a significant improvement. --- src/frontend/src/features/home/index.ts | 1 - .../src/features/home/routes/Home.tsx | 4 ++- .../features/legalsTerms/Accessibility.tsx | 4 ++- .../features/legalsTerms/LegalTermsRoute.tsx | 4 ++- .../features/legalsTerms/TermsOfService.tsx | 4 ++- src/frontend/src/features/recording/index.ts | 3 -- .../recording/routes/RecordingDownload.tsx | 4 ++- src/frontend/src/features/rooms/index.ts | 2 -- .../src/features/rooms/routes/Feedback.tsx | 4 ++- .../src/features/rooms/routes/Room.tsx | 4 ++- .../sdk/routes/CreateMeetingButton.tsx | 4 ++- .../src/features/sdk/routes/CreatePopup.tsx | 4 ++- src/frontend/src/routes.ts | 36 ++++++++++++------- 13 files changed, 50 insertions(+), 28 deletions(-) delete mode 100644 src/frontend/src/features/home/index.ts diff --git a/src/frontend/src/features/home/index.ts b/src/frontend/src/features/home/index.ts deleted file mode 100644 index bda6a40d..00000000 --- a/src/frontend/src/features/home/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Home as HomeRoute } from './routes/Home' diff --git a/src/frontend/src/features/home/routes/Home.tsx b/src/frontend/src/features/home/routes/Home.tsx index 63367796..3dc7d4d9 100644 --- a/src/frontend/src/features/home/routes/Home.tsx +++ b/src/frontend/src/features/home/routes/Home.tsx @@ -147,7 +147,7 @@ const IntroText = styled('div', { }, }) -export const Home = () => { +const Home = () => { const { t } = useTranslation('home') const { isLoggedIn } = useUser() @@ -273,3 +273,5 @@ export const Home = () => { ) } + +export default Home diff --git a/src/frontend/src/features/legalsTerms/Accessibility.tsx b/src/frontend/src/features/legalsTerms/Accessibility.tsx index 95015193..ccabbe89 100644 --- a/src/frontend/src/features/legalsTerms/Accessibility.tsx +++ b/src/frontend/src/features/legalsTerms/Accessibility.tsx @@ -3,7 +3,7 @@ import { H, P, A, Italic, Ul } from '@/primitives' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' -export const AccessibilityRoute = () => { +const AccessibilityRoute = () => { const { t } = useTranslation('accessibility', { keyPrefix: 'accessibility' }) return ( @@ -78,3 +78,5 @@ export const AccessibilityRoute = () => { ) } + +export default AccessibilityRoute diff --git a/src/frontend/src/features/legalsTerms/LegalTermsRoute.tsx b/src/frontend/src/features/legalsTerms/LegalTermsRoute.tsx index 1a9118e1..452a761c 100644 --- a/src/frontend/src/features/legalsTerms/LegalTermsRoute.tsx +++ b/src/frontend/src/features/legalsTerms/LegalTermsRoute.tsx @@ -4,7 +4,7 @@ import { css } from '@/styled-system/css' import { HStack } from '@/styled-system/jsx' import { useTranslation } from 'react-i18next' -export const LegalTermsRoute = () => { +const LegalTermsRoute = () => { const { t } = useTranslation('legals') const indentedStyle = css({ @@ -72,3 +72,5 @@ export const LegalTermsRoute = () => { ) } + +export default LegalTermsRoute diff --git a/src/frontend/src/features/legalsTerms/TermsOfService.tsx b/src/frontend/src/features/legalsTerms/TermsOfService.tsx index a49d694c..20d86b3a 100644 --- a/src/frontend/src/features/legalsTerms/TermsOfService.tsx +++ b/src/frontend/src/features/legalsTerms/TermsOfService.tsx @@ -12,7 +12,7 @@ const ensureArray = (value: any) => { } /* eslint-enable @typescript-eslint/no-explicit-any */ -export const TermsOfServiceRoute = () => { +const TermsOfServiceRoute = () => { const { t } = useTranslation('termsOfService') return ( @@ -199,3 +199,5 @@ export const TermsOfServiceRoute = () => { ) } + +export default TermsOfServiceRoute diff --git a/src/frontend/src/features/recording/index.ts b/src/frontend/src/features/recording/index.ts index a1e590c2..ce068219 100644 --- a/src/frontend/src/features/recording/index.ts +++ b/src/frontend/src/features/recording/index.ts @@ -14,6 +14,3 @@ export { RecordingMode, RecordingStatus } from './types' export { RecordingProvider } from './components/RecordingProvider' export { TranscriptSidePanel } from './components/TranscriptSidePanel' export { ScreenRecordingSidePanel } from './components/ScreenRecordingSidePanel' - -// routes -export { RecordingDownload as RecordingDownloadRoute } from './routes/RecordingDownload' diff --git a/src/frontend/src/features/recording/routes/RecordingDownload.tsx b/src/frontend/src/features/recording/routes/RecordingDownload.tsx index 2f766bdd..e50c3296 100644 --- a/src/frontend/src/features/recording/routes/RecordingDownload.tsx +++ b/src/frontend/src/features/recording/routes/RecordingDownload.tsx @@ -41,7 +41,7 @@ const BetaBadge = () => ( ) -export const RecordingDownload = () => { +const RecordingDownload = () => { const { t } = useTranslation('recording') const { data: configData } = useConfig() const { recordingId } = useParams() @@ -176,3 +176,5 @@ export const RecordingDownload = () => { ) } + +export default RecordingDownload diff --git a/src/frontend/src/features/rooms/index.ts b/src/frontend/src/features/rooms/index.ts index b3ae0e24..b7866573 100644 --- a/src/frontend/src/features/rooms/index.ts +++ b/src/frontend/src/features/rooms/index.ts @@ -1,5 +1,3 @@ -export { Room as RoomRoute } from './routes/Room' -export { FeedbackRoute } from './routes/Feedback' export { roomIdPattern, isRoomValid, diff --git a/src/frontend/src/features/rooms/routes/Feedback.tsx b/src/frontend/src/features/rooms/routes/Feedback.tsx index 70a3364d..7729bf6e 100644 --- a/src/frontend/src/features/rooms/routes/Feedback.tsx +++ b/src/frontend/src/features/rooms/routes/Feedback.tsx @@ -28,7 +28,7 @@ enum DisconnectReasonKey { ParticipantRemoved = 'participantRemoved', } -export const FeedbackRoute = () => { +const FeedbackRoute = () => { const { t } = useTranslation('rooms') const [, setLocation] = useLocation() @@ -78,3 +78,5 @@ export const FeedbackRoute = () => { ) } + +export default FeedbackRoute diff --git a/src/frontend/src/features/rooms/routes/Room.tsx b/src/frontend/src/features/rooms/routes/Room.tsx index 72da3bca..ab4d7134 100644 --- a/src/frontend/src/features/rooms/routes/Room.tsx +++ b/src/frontend/src/features/rooms/routes/Room.tsx @@ -21,7 +21,7 @@ const BaseRoom = ({ children }: { children: ReactNode }) => { ) } -export const Room = () => { +const Room = () => { const { isLoggedIn } = useUser() const [hasSubmittedEntry, setHasSubmittedEntry] = useState(false) @@ -74,3 +74,5 @@ export const Room = () => { ) } + +export default Room diff --git a/src/frontend/src/features/sdk/routes/CreateMeetingButton.tsx b/src/frontend/src/features/sdk/routes/CreateMeetingButton.tsx index 882bdbf4..bf37f938 100644 --- a/src/frontend/src/features/sdk/routes/CreateMeetingButton.tsx +++ b/src/frontend/src/features/sdk/routes/CreateMeetingButton.tsx @@ -17,7 +17,7 @@ import { useSearchParams } from 'wouter' const popupManager = new PopupManager() -export const CreateMeetingButton = () => { +const CreateMeetingButton = () => { const { t } = useTranslation('sdk', { keyPrefix: 'createMeeting' }) const [searchParams] = useSearchParams() @@ -182,3 +182,5 @@ export const CreateMeetingButton = () => { ) } + +export default CreateMeetingButton diff --git a/src/frontend/src/features/sdk/routes/CreatePopup.tsx b/src/frontend/src/features/sdk/routes/CreatePopup.tsx index 10822b7e..36fe20dd 100644 --- a/src/frontend/src/features/sdk/routes/CreatePopup.tsx +++ b/src/frontend/src/features/sdk/routes/CreatePopup.tsx @@ -9,7 +9,7 @@ import { PopupWindow } from '../utils/PopupWindow' const callbackIdHandler = new CallbackIdHandler() const popupWindow = new PopupWindow() -export const CreatePopup = () => { +const CreatePopup = () => { const { isLoggedIn } = useUser({ fetchUserOptions: { attemptSilent: false } }) const { mutateAsync: createRoom } = useCreateRoom() @@ -74,3 +74,5 @@ export const CreatePopup = () => { ) } + +export default CreatePopup diff --git a/src/frontend/src/routes.ts b/src/frontend/src/routes.ts index 5274b526..68fab424 100644 --- a/src/frontend/src/routes.ts +++ b/src/frontend/src/routes.ts @@ -1,15 +1,25 @@ -import { - FeedbackRoute, - RoomRoute, - flexibleRoomIdPattern, -} from '@/features/rooms' -import { HomeRoute } from '@/features/home' -import { LegalTermsRoute } from '@/features/legalsTerms/LegalTermsRoute' -import { AccessibilityRoute } from '@/features/legalsTerms/Accessibility' -import { TermsOfServiceRoute } from '@/features/legalsTerms/TermsOfService' -import { CreatePopup } from '@/features/sdk/routes/CreatePopup' -import { CreateMeetingButton } from '@/features/sdk/routes/CreateMeetingButton' -import { RecordingDownloadRoute } from '@/features/recording' +import { flexibleRoomIdPattern } from '@/features/rooms' +import { ComponentType, lazy, LazyExoticComponent } from 'react' + +const HomeRoute = lazy(() => import('@/features/home/routes/Home')) +const RecordingDownloadRoute = lazy( + () => import('@/features/recording/routes/RecordingDownload') +) +const CreatePopup = lazy(() => import('@/features/sdk/routes/CreatePopup')) +const CreateMeetingButton = lazy( + () => import('@/features/sdk/routes/CreateMeetingButton') +) +const LegalTermsRoute = lazy( + () => import('@/features/legalsTerms/LegalTermsRoute') +) +const TermsOfServiceRoute = lazy( + () => import('@/features/legalsTerms/TermsOfService') +) +const AccessibilityRoute = lazy( + () => import('@/features/legalsTerms/Accessibility') +) +const RoomRoute = lazy(() => import('@/features/rooms/routes/Room')) +const FeedbackRoute = lazy(() => import('@/features/rooms/routes/Feedback')) const roomIdRegex = new RegExp(`^[/](?${flexibleRoomIdPattern})$`) @@ -26,7 +36,7 @@ export const routes: Record< { name: RouteName path: RegExp | string - Component: () => JSX.Element + Component: LazyExoticComponent // eslint-disable-next-line @typescript-eslint/no-explicit-any to?: (...args: any[]) => string | URL }