Skip to content

Commit 369c27a

Browse files
Merge pull request #335 from topcoder-platform/TCA-505-reduce-js-bundle-size
TCA-505 reduce js bundle size
2 parents 2dfa001 + d336b8f commit 369c27a

File tree

15 files changed

+124
-57
lines changed

15 files changed

+124
-57
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,36 @@ These routes then need to be added to the routes file for the parent tools/utils
272272
Simply adding the routes to one of thes files above will register the tool/util
273273
with the application and will display the new component.
274274

275+
### Lazy loading and code splitting
276+
277+
When loading a route component, please use the `lazyLoad()` method defined in the application lib.
278+
279+
| param | description|
280+
| ----- | ---------- |
281+
| `moduleImport: () => Promise<any>` | Function which imports the desired module |
282+
| `namedExport?: string` | The name of the exported module (if the module has named exports) |
283+
284+
Eg:
285+
```
286+
// Lazy load the WelcomePage component
287+
const WelcomePage: LazyLoadedComponent = lazyLoad(() => import('./welcome'), 'WelcomePage')
288+
...
289+
// Use the component as route element
290+
export const learnRoutes: Array<PlatformRoute> = [
291+
{
292+
children: [
293+
{
294+
children: [],
295+
element: <WelcomePage />,
296+
...
297+
},
298+
...
299+
]
300+
}
301+
]
302+
```
303+
304+
275305
### Platform Route
276306

277307
The PlatformRoute model has several useful options:

src-ts/lib/route-provider/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export * from './platform-route.model'
33
export * from './route-context-data.model'
44
export { default as routeContext } from './route.context'
55
export * from './route.provider'
6+
export * from './router.utils'

src-ts/lib/route-provider/route.provider.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import {
44
ReactElement,
55
ReactNode,
66
SetStateAction,
7+
Suspense,
78
useContext,
89
useEffect,
910
useState,
1011
} from 'react'
1112
import { Location, Route, useLocation } from 'react-router-dom'
1213

1314
import { authUrlLogin } from '../functions'
15+
import { LoadingSpinner } from '../loading-spinner'
1416
import { profileContext, ProfileContextData } from '../profile-provider'
1517

1618
import { PlatformRoute } from './platform-route.model'
@@ -154,9 +156,11 @@ export const RouteProvider: FC<RouteProviderProps> = (props: RouteProviderProps)
154156
])
155157

156158
return (
157-
<routeContext.Provider value={routeContextData}>
158-
{props.children}
159-
</routeContext.Provider>
159+
<Suspense fallback={<LoadingSpinner />}>
160+
<routeContext.Provider value={routeContextData}>
161+
{props.children}
162+
</routeContext.Provider>
163+
</Suspense>
160164
)
161165
}
162166

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { get } from 'lodash'
2+
import { ComponentType, lazy, LazyExoticComponent } from 'react'
3+
4+
export type LazyLoadedComponent = LazyExoticComponent<ComponentType<any>>
5+
6+
export type LazyLoadType = (
7+
moduleImport: () => Promise<any>,
8+
namedExport?: string
9+
) => LazyLoadedComponent
10+
11+
/**
12+
* Utility wrapper around react's `lazy` method,
13+
* it allows importing default and named exports from modules using the same unique method
14+
* (while react's `lazy` method only allows to import default exports)
15+
*/
16+
export const lazyLoad: LazyLoadType = (moduleImport: () => Promise<any>, namedExport: string = 'default') => (
17+
lazy(() => moduleImport().then(m => ({default: get(m, namedExport)})))
18+
)

src-ts/tools/dev-center/DevCenter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
RouteContextData,
77
} from '../../lib'
88

9-
export const toolTitle: string = 'Dev Center'
9+
import { toolTitle } from './dev-center.routes'
1010

1111
const DevCenter: FC<{}> = () => {
1212

src-ts/tools/dev-center/dev-center-pages/community-app/getting-started/GettingStartedGuide.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Breadcrumb, BreadcrumbItemModel, ContentLayout } from '../../../../../l
44
import useMarkdown from '../../../dev-center-lib/hooks/useMarkdown'
55
import MarkdownDoc from '../../../dev-center-lib/MarkdownDoc'
66
import LayoutDocHeader from '../../../dev-center-lib/MarkdownDoc/LayoutDocHeader'
7-
import { toolTitle } from '../../../DevCenter'
7+
import { toolTitle } from '../../../dev-center.routes'
88

99
import gettingStartedGuide from './GettingStartedGuide.md'
1010
import styles from './GettingStartedGuide.module.scss'

src-ts/tools/dev-center/dev-center.routes.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { PlatformRoute } from '../../lib'
1+
import { lazyLoad, LazyLoadedComponent, PlatformRoute } from '../../lib'
22

3-
import GettingStartedGuide from './dev-center-pages/community-app/getting-started/GettingStartedGuide'
4-
import DevCenterLandingPage from './dev-center-pages/community-app/landing-page/DevCenterLandingPage'
5-
import DevCenter, { toolTitle } from './DevCenter'
3+
const GettingStartedGuide: LazyLoadedComponent = lazyLoad(() => import('./dev-center-pages/community-app/getting-started/GettingStartedGuide'))
4+
const DevCenterLandingPage: LazyLoadedComponent = lazyLoad(() => import('./dev-center-pages/community-app/landing-page/DevCenterLandingPage'))
5+
const DevCenter: LazyLoadedComponent = lazyLoad(() => import('./DevCenter'))
6+
7+
export const toolTitle: string = 'Dev Center'
68

79
export const devCenterRoutes: Array<PlatformRoute> = [
810
{

src-ts/tools/gamification-admin/gamification-admin.routes.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { PlatformRoute, UserRole } from '../../lib'
1+
import { lazyLoad, LazyLoadedComponent, PlatformRoute, UserRole } from '../../lib'
22

3-
import GamificationAdmin, { toolTitle } from './GamificationAdmin'
4-
import BadgeDetailPage from './pages/badge-detail/BadgeDetailPage'
5-
import BadgeListingPage from './pages/badge-listing/BadgeListingPage'
6-
import CreateBadgePage from './pages/create-badge/CreateBadgePage'
3+
import { toolTitle } from './GamificationAdmin'
4+
5+
const GamificationAdmin: LazyLoadedComponent = lazyLoad(() => import('./GamificationAdmin'))
6+
const BadgeDetailPage: LazyLoadedComponent = lazyLoad(() => import('./pages/badge-detail/BadgeDetailPage'))
7+
const BadgeListingPage: LazyLoadedComponent = lazyLoad(() => import('./pages/badge-listing/BadgeListingPage'))
8+
const CreateBadgePage: LazyLoadedComponent = lazyLoad(() => import('./pages/create-badge/CreateBadgePage'))
79

810
export const baseDetailPath: string = '/badge-detail'
911
export const createBadgePath: string = '/create-badge'

src-ts/tools/learn/learn.routes.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { authUrlLogin, PlatformRoute } from '../../lib'
1+
import { authUrlLogin, lazyLoad, LazyLoadedComponent, PlatformRoute } from '../../lib'
22

3-
import { MyCertificate, UserCertificate } from './course-certificate'
4-
import { CourseCompletedPage } from './course-completed'
5-
import { CourseDetailsPage } from './course-details'
6-
import { FreeCodeCamp } from './free-code-camp'
7-
import { default as Learn, toolTitle } from './Learn'
3+
import { toolTitle } from './Learn'
84
import { LearnConfig } from './learn-config'
9-
import { MyLearning } from './my-learning'
10-
import { WelcomePage } from './welcome'
5+
6+
const WelcomePage: LazyLoadedComponent = lazyLoad(() => import('./welcome'), 'WelcomePage')
7+
const CourseDetailsPage: LazyLoadedComponent = lazyLoad(() => import('./course-details'), 'CourseDetailsPage')
8+
const CourseCompletedPage: LazyLoadedComponent = lazyLoad(() => import('./course-completed/'), 'CourseCompletedPage')
9+
const MyCertificate: LazyLoadedComponent = lazyLoad(() => import('./course-certificate'), 'MyCertificate')
10+
const UserCertificate: LazyLoadedComponent = lazyLoad(() => import('./course-certificate'), 'UserCertificate')
11+
const FreeCodeCamp: LazyLoadedComponent = lazyLoad(() => import('./free-code-camp'), 'FreeCodeCamp')
12+
const MyLearning: LazyLoadedComponent = lazyLoad(() => import('./my-learning'), 'MyLearning')
13+
const LandingLearn: LazyLoadedComponent = lazyLoad(() => import('./Learn'))
1114

1215
export enum LEARN_PATHS {
1316
certificate = '/certificate',
@@ -112,7 +115,7 @@ export const learnRoutes: Array<PlatformRoute> = [
112115
title: 'My Learning',
113116
},
114117
],
115-
element: <Learn />,
118+
element: <LandingLearn />,
116119
memberOnly: true,
117120
route: rootRoute,
118121
title: toolTitle,

src-ts/tools/work/work.routes.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
import { Navigate } from 'react-router-dom'
22

3-
import { contactSupportPath, PlatformRoute } from '../../lib'
3+
import { contactSupportPath, lazyLoad, LazyLoadedComponent, PlatformRoute } from '../../lib'
44

5-
import { dashboardTitle, default as WorkComponent, toolTitle } from './Work'
5+
import { dashboardTitle, toolTitle } from './Work'
66
import { Work, WorkIntakeFormRoutes, WorkStatus, WorkType } from './work-lib'
77
import { WorkLoginPrompt } from './work-login-prompt'
8-
import { WorkNotLoggedIn } from './work-not-logged-in'
9-
import {
10-
BugHuntIntakeForm,
11-
IntakeForms,
12-
intakeFormsTitle,
13-
Review,
14-
} from './work-self-service'
15-
import SaveAfterLogin from './work-self-service/intake-forms/save-after-login/SaveAfterLogin'
16-
import { WorkTable } from './work-table'
17-
import { WorkThankYou } from './work-thank-you'
8+
import { intakeFormsTitle } from './work-self-service'
9+
10+
const WorkComponent: LazyLoadedComponent = lazyLoad(() => import('./Work'))
11+
const WorkNotLoggedIn: LazyLoadedComponent = lazyLoad(() => import('./work-not-logged-in'), 'WorkNotLoggedIn')
12+
const BugHuntIntakeForm: LazyLoadedComponent = lazyLoad(() => import('./work-self-service'), 'BugHuntIntakeForm')
13+
const IntakeForms: LazyLoadedComponent = lazyLoad(() => import('./work-self-service'), 'IntakeForms')
14+
const Review: LazyLoadedComponent = lazyLoad(() => import('./work-self-service'), 'Review')
15+
const SaveAfterLogin: LazyLoadedComponent = lazyLoad(() => import('./work-self-service/intake-forms/save-after-login/SaveAfterLogin'))
16+
const WorkTable: LazyLoadedComponent = lazyLoad(() => import('./work-table'), 'WorkTable')
17+
const WorkThankYou: LazyLoadedComponent = lazyLoad(() => import('./work-thank-you'), 'WorkThankYou')
1818

1919
export const rootRoute: string = '/work'
2020
export const selfServiceRootRoute: string = '/self-service'
2121
export const selfServiceStartRoute: string = `${selfServiceRootRoute}/wizard`
2222
export const dashboardRoute: string = `${rootRoute}/dashboard`
2323

2424
export function workDashboardRoute(active: string): string {
25-
return `${dashboardRoute}/${active}`
25+
return `${dashboardRoute}/${active}`
2626
}
2727

2828
export function workDetailOrDraftRoute(selectedWork: Work): string {

src-ts/utils/contact-support/ContactSupport.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
formOnReset
1010
} from '../../lib'
1111

12-
export const toolTitle: string = 'Contact Support'
12+
import { toolTitle } from './contact-support.routes'
1313

1414
const ContactSupport: FC<{}> = () => {
1515

src-ts/utils/contact-support/contact-support.routes.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { contactSupportPath, PlatformRoute } from '../../lib'
1+
import { contactSupportPath, lazyLoad, LazyLoadedComponent, PlatformRoute } from '../../lib'
22

3-
import { default as ContactSupport, toolTitle } from './ContactSupport'
3+
export const toolTitle: string = 'Contact Support'
4+
5+
const ContactSupport: LazyLoadedComponent = lazyLoad(() => import('./ContactSupport'))
46

57
export const contactSupportRoutes: Array<PlatformRoute> = [
68
{

src-ts/utils/home/home.routes.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { PlatformRoute } from '../../lib'
1+
import { lazyLoad, LazyLoadedComponent, PlatformRoute } from '../../lib'
22

3-
import { default as Home } from './Home'
3+
const Home: LazyLoadedComponent = lazyLoad(() => import('./Home'))
44

55
export const homeRoute: string = ''
66

src-ts/utils/settings/settings.routes.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { ToolTitle } from '../../config'
2-
import { PlatformRoute } from '../../lib'
2+
import { lazyLoad, LazyLoadedComponent, PlatformRoute } from '../../lib'
33

4-
import { Account } from './account'
5-
import Settings from './Settings'
4+
const Account: LazyLoadedComponent = lazyLoad(() => import('./account'), 'Account')
5+
const Settings: LazyLoadedComponent = lazyLoad(() => import('./Settings'))
66

77
export const settingsRoutes: Array<PlatformRoute> = [
88
{

src/App.jsx

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ import "react-responsive-modal/styles.css";
55
import { profileContext } from "../src-ts";
66

77
import { UNDER_MAINTENANCE } from "./constants";
8-
import IntakeForm from "./IntakeForm";
9-
import WorkItem from "./routes/WorkItems";
108
import { ScrollToTop } from "./ScrollToTop";
119
import styles from "./styles/main.module.scss";
12-
import UnderMaintenance from "./routes/UnderMaintenance";
10+
import { lazyLoad, LoadingSpinner } from "../src-ts/lib";
11+
import { Suspense } from "react";
12+
13+
const WorkItem = lazyLoad(() => import("./routes/WorkItems"));
14+
const IntakeForm = lazyLoad(() => import("./IntakeForm"));
15+
const UnderMaintenance = lazyLoad(() => import("./routes/UnderMaintenance"));
1316

1417

1518
const App = () => {
@@ -40,16 +43,18 @@ const App = () => {
4043
return (
4144
<div className={styles["topcoder-platform-ui"]}>
4245
<ScrollToTop path="/">
43-
<Routes>
44-
<Route
45-
element={<IntakeForm />}
46-
path="/self-service/*"
47-
/>
48-
<Route
49-
element={<WorkItem />}
50-
path="/self-service/work-items/:workItemId"
51-
/>
52-
</Routes>
46+
<Suspense fallback={<LoadingSpinner />}>
47+
<Routes>
48+
<Route
49+
element={<IntakeForm />}
50+
path="/self-service/*"
51+
/>
52+
<Route
53+
element={<WorkItem />}
54+
path="/self-service/work-items/:workItemId"
55+
/>
56+
</Routes>
57+
</Suspense>
5358
</ScrollToTop>
5459
</div >
5560
);

0 commit comments

Comments
 (0)