Skip to content

Commit 88f426c

Browse files
committed
perf: add code-splitting to reduce initial page size
1 parent 156a645 commit 88f426c

File tree

6 files changed

+103
-65
lines changed

6 files changed

+103
-65
lines changed

app/src/Routes.tsx

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
1-
import React from 'react';
1+
import React, { Suspense } from 'react';
22
import { Route, Router, Switch } from 'react-router';
33
import { useStore } from 'store';
4-
import AuthPage from 'components/auth/AuthPage';
5-
import HistoryPage from 'components/history/HistoryPage';
4+
import Loading from 'components/common/Loading';
65
import { Layout } from 'components/layout';
7-
import LoopPage from 'components/loop/LoopPage';
8-
import SettingsPage from 'components/settings/SettingsPage';
6+
7+
const LazyAuthPage = React.lazy(() => import('components/auth/AuthPage'));
8+
const LazyLoopPage = React.lazy(() => import('components/loop/LoopPage'));
9+
const LazyHistoryPage = React.lazy(() => import('components/history/HistoryPage'));
10+
const LazySettingsPage = React.lazy(() => import('components/settings/SettingsPage'));
911

1012
const Routes: React.FC = () => {
1113
const { router } = useStore();
1214

1315
return (
14-
<Router history={router.history}>
15-
<Switch>
16-
<Route path="/" exact component={AuthPage} />
17-
<Route>
18-
<Layout>
19-
<Switch>
20-
<Route path="/loop" component={LoopPage} />
21-
<Route path="/history" component={HistoryPage} />
22-
<Route path="/settings" component={SettingsPage} />
23-
</Switch>
24-
</Layout>
25-
</Route>
26-
</Switch>
27-
</Router>
16+
<Suspense fallback={<Loading delay={500} />}>
17+
<Router history={router.history}>
18+
<Switch>
19+
<Route path="/" exact component={LazyAuthPage} />
20+
<Route>
21+
<Layout>
22+
<Switch>
23+
<Suspense fallback={<Loading delay={500} />}>
24+
<Route path="/loop" component={LazyLoopPage} />
25+
<Route path="/history" component={LazyHistoryPage} />
26+
<Route path="/settings" component={LazySettingsPage} />
27+
</Suspense>
28+
</Switch>
29+
</Layout>
30+
</Route>
31+
</Switch>
32+
</Router>
33+
</Suspense>
2834
);
2935
};
3036

app/src/__tests__/Routes.spec.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,29 @@ describe('Routes Component', () => {
1111
};
1212

1313
it('should display the Auth page by default', async () => {
14-
const { getByText, store } = await render();
15-
expect(getByText('Shushtar')).toBeInTheDocument();
14+
const { findByText, store } = await render();
15+
expect(await findByText('Shushtar')).toBeInTheDocument();
1616
expect(store.router.location.pathname).toBe('/');
1717
});
1818

1919
it('should display the Loop page', async () => {
20-
const { getAllByText, store } = await render();
20+
const { findByText, store } = await render();
2121
store.uiStore.goToLoop();
22-
expect(getAllByText('Lightning Loop')).toHaveLength(2);
22+
expect(await findByText('Total Outbound Liquidity')).toBeInTheDocument();
2323
expect(store.router.location.pathname).toBe('/loop');
2424
});
2525

2626
it('should display the History page', async () => {
27-
const { getByText, store } = await render();
27+
const { findByText, store } = await render();
2828
store.uiStore.goToHistory();
29-
expect(getByText('Loop History')).toBeInTheDocument();
29+
expect(await findByText('Loop History')).toBeInTheDocument();
3030
expect(store.router.location.pathname).toBe('/history');
3131
});
3232

3333
it('should display the Settings page', async () => {
34-
const { getAllByText, store } = await render();
34+
const { findByText, store } = await render();
3535
store.uiStore.goToSettings();
36-
expect(getAllByText('Settings')).toHaveLength(2);
36+
expect(await findByText('My Node')).toBeInTheDocument();
3737
expect(store.router.location.pathname).toBe('/settings');
3838
});
3939
});

app/src/__tests__/components/loop/LoopPage.spec.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { Suspense } from 'react';
22
import { SwapStatus } from 'types/generated/loop_pb';
33
import { grpc } from '@improbable-eng/grpc-web';
44
import { fireEvent, waitFor } from '@testing-library/react';
@@ -21,7 +21,12 @@ describe('LoopPage component', () => {
2121
});
2222

2323
const render = () => {
24-
return renderWithProviders(<LoopPage />, store);
24+
const cmp = (
25+
<Suspense fallback={null}>
26+
<LoopPage />
27+
</Suspense>
28+
);
29+
return renderWithProviders(cmp, store);
2530
};
2631

2732
it('should display the page title', () => {
@@ -90,14 +95,14 @@ describe('LoopPage component', () => {
9095
});
9196

9297
it('should display swap wizard when Loop out is clicked', async () => {
93-
const { getByText } = render();
98+
const { getByText, findByText } = render();
9499
expect(getByText('Loop')).toBeInTheDocument();
95100
fireEvent.click(getByText('Loop'));
96101
store.channelStore.sortedChannels.slice(0, 3).forEach(c => {
97102
store.buildSwapStore.toggleSelectedChannel(c.chanId);
98103
});
99104
fireEvent.click(getByText('Loop Out'));
100-
expect(getByText('Step 1 of 2')).toBeInTheDocument();
105+
expect(await findByText('Step 1 of 2')).toBeInTheDocument();
101106
});
102107

103108
it('should display the swap wizard when Loop in is clicked', async () => {

app/src/components/common/Loading.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { observer } from 'mobx-react-lite';
3+
import loadingJson from 'assets/animations/loading.json';
4+
import { HeaderFour } from 'components/base';
5+
import Animation from 'components/common/Animation';
6+
import { styled } from 'components/theme';
7+
8+
const Styled = {
9+
Wrapper: styled.div`
10+
flex-grow: 1;
11+
display: flex;
12+
flex-direction: column;
13+
align-items: center;
14+
justify-content: center;
15+
height: 100%;
16+
`,
17+
Loader: styled(Animation)`
18+
width: 150px;
19+
height: 150px;
20+
`,
21+
Message: styled.div`
22+
text-align: center;
23+
`,
24+
};
25+
26+
interface Props {
27+
message?: string;
28+
delay?: number;
29+
}
30+
31+
const Loading: React.FC<Props> = ({ message, delay }) => {
32+
const [show, setShow] = useState(!delay);
33+
34+
useEffect(() => {
35+
if (delay) {
36+
const timeout = setTimeout(() => setShow(true), delay);
37+
return () => clearTimeout(timeout);
38+
}
39+
}, [delay]);
40+
41+
const { Wrapper, Loader, Message } = Styled;
42+
return show ? (
43+
<Wrapper>
44+
<Loader animationData={loadingJson} loop />
45+
{message && (
46+
<Message>
47+
<HeaderFour>{message}</HeaderFour>
48+
</Message>
49+
)}
50+
</Wrapper>
51+
) : null;
52+
};
53+
54+
export default observer(Loading);

app/src/components/loop/LoopPage.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import { styled } from 'components/theme';
88
import ChannelList from './ChannelList';
99
import LoopActions from './LoopActions';
1010
import LoopTiles from './LoopTiles';
11-
import ProcessingSwaps from './processing/ProcessingSwaps';
12-
import SwapWizard from './swap/SwapWizard';
11+
12+
const LazySwapWizard = React.lazy(() => import('./swap/SwapWizard'));
13+
const LazyProcessingSwaps = React.lazy(() => import('./processing/ProcessingSwaps'));
1314

1415
const Styled = {
1516
PageWrap: styled.div`
@@ -36,9 +37,9 @@ const LoopPage: React.FC = () => {
3637
return (
3738
<PageWrap>
3839
{uiStore.processingSwapsVisible ? (
39-
<ProcessingSwaps />
40+
<LazyProcessingSwaps />
4041
) : buildSwapStore.showWizard ? (
41-
<SwapWizard />
42+
<LazySwapWizard />
4243
) : (
4344
<>
4445
<PageHeader title={title} onExportClick={channelStore.exportChannels} />
Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,12 @@
11
import React from 'react';
22
import { observer } from 'mobx-react-lite';
3-
import loadingJson from 'assets/animations/loading.json';
43
import { usePrefixedTranslation } from 'hooks';
5-
import { HeaderFour } from 'components/base';
6-
import Animation from 'components/common/Animation';
7-
import { styled } from 'components/theme';
8-
9-
const Styled = {
10-
Wrapper: styled.div`
11-
flex-grow: 1;
12-
display: flex;
13-
flex-direction: column;
14-
align-items: center;
15-
justify-content: center;
16-
`,
17-
Loader: styled(Animation)`
18-
width: 150px;
19-
height: 150px;
20-
`,
21-
LoadingMessage: styled.div`
22-
text-align: center;
23-
`,
24-
};
4+
import Loading from 'components/common/Loading';
255

266
const SwapProcessingStep: React.FC = () => {
277
const { l } = usePrefixedTranslation('cmps.loop.swap.SwapProcessingStep');
288

29-
const { Wrapper, Loader, LoadingMessage } = Styled;
30-
return (
31-
<Wrapper>
32-
<Loader animationData={loadingJson} loop />
33-
<LoadingMessage>
34-
<HeaderFour>{l('loadingMsg')}</HeaderFour>
35-
</LoadingMessage>
36-
</Wrapper>
37-
);
9+
return <Loading message={l('loadingMsg')} />;
3810
};
3911

4012
export default observer(SwapProcessingStep);

0 commit comments

Comments
 (0)