Merge pull request #632 from bigcapitalhq/split-lazy-loading

feat: Optimize loading perf. by splitting big chunks and lazy loading them
This commit is contained in:
Ahmed Bouhuolia
2024-08-29 21:27:40 +02:00
committed by GitHub
9 changed files with 162 additions and 154 deletions

View File

@@ -1,4 +1,5 @@
// @ts-nocheck // @ts-nocheck
import { lazy, Suspense } from 'react';
import { Router, Switch, Route } from 'react-router'; import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history'; import { createBrowserHistory } from 'history';
import { QueryClientProvider, QueryClient } from 'react-query'; import { QueryClientProvider, QueryClient } from 'react-query';
@@ -11,25 +12,26 @@ import 'moment/locale/es-us';
import AppIntlLoader from './AppIntlLoader'; import AppIntlLoader from './AppIntlLoader';
import { EnsureAuthenticated } from '@/components/Guards/EnsureAuthenticated'; import { EnsureAuthenticated } from '@/components/Guards/EnsureAuthenticated';
import GlobalErrors from '@/containers/GlobalErrors/GlobalErrors'; import GlobalErrors from '@/containers/GlobalErrors/GlobalErrors';
import DashboardPrivatePages from '@/components/Dashboard/PrivatePages';
import { Authentication } from '@/containers/Authentication/Authentication';
import LazyLoader from '@/components/LazyLoader';
import { SplashScreen, DashboardThemeProvider } from '../components'; import { SplashScreen, DashboardThemeProvider } from '../components';
import { queryConfig } from '../hooks/query/base'; import { queryConfig } from '../hooks/query/base';
import { EnsureUserEmailVerified } from './Guards/EnsureUserEmailVerified';
import { EnsureAuthNotAuthenticated } from './Guards/EnsureAuthNotAuthenticated';
import { EnsureUserEmailNotVerified } from './Guards/EnsureUserEmailNotVerified'; import { EnsureUserEmailNotVerified } from './Guards/EnsureUserEmailNotVerified';
const EmailConfirmation = LazyLoader({ const DashboardPrivatePages = lazy(
loader: () => import('@/containers/Authentication/EmailConfirmation'), () => import('@/components/Dashboard/PrivatePages'),
}); );
const RegisterVerify = LazyLoader({ const AuthenticationPage = lazy(
loader: () => import('@/containers/Authentication/RegisterVerify'), () => import('@/containers/Authentication/AuthenticationPage'),
}); );
const OneClickDemoPage = LazyLoader({ const EmailConfirmation = lazy(
loader: () => import('@/containers/OneClickDemo/OneClickDemoPage'), () => import('@/containers/Authentication/EmailConfirmation'),
}); );
const RegisterVerify = lazy(
() => import('@/containers/Authentication/RegisterVerify'),
);
const OneClickDemoPage = lazy(
() => import('@/containers/OneClickDemo/OneClickDemoPage'),
);
/** /**
* App inner. * App inner.
@@ -38,36 +40,27 @@ function AppInsider({ history }) {
return ( return (
<div className="App"> <div className="App">
<DashboardThemeProvider> <DashboardThemeProvider>
<Router history={history}> <Suspense fallback={'Loading...'}>
<Switch> <Router history={history}>
<Route path={'/one_click_demo'} children={<OneClickDemoPage />} /> <Switch>
<Route path={'/auth/register/verify'}> <Route path={'/one_click_demo'} children={<OneClickDemoPage />} />
<EnsureAuthenticated> <Route path={'/auth/register/verify'}>
<EnsureUserEmailNotVerified> <EnsureAuthenticated>
<RegisterVerify /> <EnsureUserEmailNotVerified>
</EnsureUserEmailNotVerified> <RegisterVerify />
</EnsureAuthenticated> </EnsureUserEmailNotVerified>
</Route> </EnsureAuthenticated>
</Route>
<Route path={'/auth/email_confirmation'}> <Route
<EmailConfirmation /> path={'/auth/email_confirmation'}
</Route> children={<EmailConfirmation />}
/>
<Route path={'/auth'}> <Route path={'/auth'} children={<AuthenticationPage />} />
<EnsureAuthNotAuthenticated> <Route path={'/'} children={<DashboardPrivatePages />} />
<Authentication /> </Switch>
</EnsureAuthNotAuthenticated> </Router>
</Route> </Suspense>
<Route path={'/'}>
<EnsureAuthenticated>
<EnsureUserEmailVerified>
<DashboardPrivatePages />
</EnsureUserEmailVerified>
</EnsureAuthenticated>
</Route>
</Switch>
</Router>
<GlobalErrors /> <GlobalErrors />
</DashboardThemeProvider> </DashboardThemeProvider>

View File

@@ -1,35 +1,37 @@
// @ts-nocheck // @ts-nocheck
import React from 'react'; import React, { lazy } from 'react';
import { Switch, Route } from 'react-router'; import { Switch, Route } from 'react-router';
import Dashboard from '@/components/Dashboard/Dashboard'; import Dashboard from '@/components/Dashboard/Dashboard';
import SetupWizardPage from '@/containers/Setup/WizardSetupPage';
import EnsureOrganizationIsReady from '../Guards/EnsureOrganizationIsReady';
import EnsureOrganizationIsNotReady from '../Guards/EnsureOrganizationIsNotReady';
import { PrivatePagesProvider } from './PrivatePagesProvider'; import { PrivatePagesProvider } from './PrivatePagesProvider';
import EnsureOrganizationIsReady from '../Guards/EnsureOrganizationIsReady';
import { EnsureAuthenticated } from '../Guards/EnsureAuthenticated';
import { EnsureUserEmailVerified } from '../Guards/EnsureUserEmailVerified';
import '@/style/pages/Dashboard/Dashboard.scss'; import '@/style/pages/Dashboard/Dashboard.scss';
const SetupWizardPage = lazy(
() => import('@/containers/Setup/WizardSetupPage'),
);
/** /**
* Dashboard inner private pages. * Dashboard inner private pages.
*/ */
export default function DashboardPrivatePages() { export default function DashboardPrivatePages() {
return ( return (
<PrivatePagesProvider> <EnsureAuthenticated>
<Switch> <EnsureUserEmailVerified>
<Route path={'/setup'}> <PrivatePagesProvider>
<EnsureOrganizationIsNotReady> <Switch>
<SetupWizardPage /> <Route path={'/setup'} children={<SetupWizardPage />} />
</EnsureOrganizationIsNotReady> <Route path="/">
</Route> <EnsureOrganizationIsReady>
<Dashboard />
<Route path="/"> </EnsureOrganizationIsReady>
<EnsureOrganizationIsReady> </Route>
<Dashboard /> </Switch>
</EnsureOrganizationIsReady> </PrivatePagesProvider>
</Route> </EnsureUserEmailVerified>
</Switch> </EnsureAuthenticated>
</PrivatePagesProvider>
); );
} }

View File

@@ -1,22 +0,0 @@
// @ts-nocheck
import * as React from 'react';
import * as Loadable from 'react-loadable';
const Loader = (config) =>
Loadable({
loading: (props) => {
if (props.error) {
/* tslint:disable */
console.error(`======= DefaultLoader Error =======`);
console.error(props.error);
console.error(`======= DefaultLoader Error =======`);
/* tslint:enable */
return null;
}
return null;
},
delay: 250,
...config
});
export default Loader;

View File

@@ -1,21 +1,33 @@
// @ts-nocheck // @ts-nocheck
import React from 'react'; import React, { Suspense } from 'react';
import { Route, Switch } from 'react-router-dom'; import { Route, Switch } from 'react-router-dom';
import preferencesRoutes from '@/routes/preferences'; import { getPreferenceRoutes } from '@/routes/preferences';
import { Spinner } from '@blueprintjs/core';
import { Box } from '../Layout';
export default function DashboardContentRoute() { export default function DashboardContentRoute() {
const preferencesRoutes = getPreferenceRoutes();
return ( return (
<Route pathname="/preferences"> <Route pathname="/preferences">
<Switch> <Suspense
{preferencesRoutes.map((route, index) => ( fallback={
<Route <Box style={{ padding: 20 }}>
key={index} <Spinner size={20} />
path={`${route.path}`} </Box>
exact={route.exact} }
component={route.component} >
/> <Switch>
))} {preferencesRoutes.map((route, index) => (
</Switch> <Route
key={index}
path={`${route.path}`}
exact={route.exact}
component={route.component}
/>
))}
</Switch>
</Suspense>
</Route> </Route>
); );
} }

View File

@@ -2,10 +2,12 @@
import { Route, Switch, useLocation } from 'react-router-dom'; import { Route, Switch, useLocation } from 'react-router-dom';
import BodyClassName from 'react-body-classname'; import BodyClassName from 'react-body-classname';
import styled from 'styled-components'; import styled from 'styled-components';
import { Suspense } from 'react';
import { TransitionGroup, CSSTransition } from 'react-transition-group'; import { TransitionGroup, CSSTransition } from 'react-transition-group';
import { Spinner } from '@blueprintjs/core';
import authenticationRoutes from '@/routes/authentication'; import authenticationRoutes from '@/routes/authentication';
import { Icon, FormattedMessage as T } from '@/components'; import { Box, Icon, FormattedMessage as T } from '@/components';
import { AuthMetaBootProvider } from './AuthMetaBoot'; import { AuthMetaBootProvider } from './AuthMetaBoot';
import '@/style/pages/Authentication/Auth.scss'; import '@/style/pages/Authentication/Auth.scss';
@@ -20,7 +22,15 @@ export function Authentication() {
</AuthLogo> </AuthLogo>
<AuthMetaBootProvider> <AuthMetaBootProvider>
<AuthenticationRoutes /> <Suspense
fallback={
<Box style={{ marginTop: '5rem' }}>
<Spinner size={30} />
</Box>
}
>
<AuthenticationRoutes />
</Suspense>
</AuthMetaBootProvider> </AuthMetaBootProvider>
</AuthInsider> </AuthInsider>
</AuthPage> </AuthPage>

View File

@@ -0,0 +1,10 @@
import { EnsureAuthNotAuthenticated } from "@/components/Guards/EnsureAuthNotAuthenticated";
import { Authentication } from "./Authentication";
export default function AuthenticationPage() {
return (
<EnsureAuthNotAuthenticated>
<Authentication />
</EnsureAuthNotAuthenticated>
);
}

View File

@@ -2,14 +2,17 @@
import React from 'react'; import React from 'react';
import SetupRightSection from './SetupRightSection'; import SetupRightSection from './SetupRightSection';
import SetupLeftSection from './SetupLeftSection'; import SetupLeftSection from './SetupLeftSection';
import EnsureOrganizationIsNotReady from '@/components/Guards/EnsureOrganizationIsNotReady';
import '@/style/pages/Setup/SetupPage.scss'; import '@/style/pages/Setup/SetupPage.scss';
export default function WizardSetupPage() { export default function WizardSetupPage() {
return ( return (
<div class="setup-page"> <EnsureOrganizationIsNotReady>
<SetupLeftSection /> <div class="setup-page">
<SetupRightSection /> <SetupLeftSection />
</div> <SetupRightSection />
</div>
</EnsureOrganizationIsNotReady>
); );
}; }

View File

@@ -1,43 +1,35 @@
// @ts-nocheck // @ts-nocheck
import LazyLoader from '@/components/LazyLoader'; import { lazy } from 'react';
const BASE_URL = '/auth'; const BASE_URL = '/auth';
export default [ export default [
{ {
path: `${BASE_URL}/login`, path: `${BASE_URL}/login`,
component: LazyLoader({ component: lazy(() => import('@/containers/Authentication/Login')),
loader: () => import('@/containers/Authentication/Login'),
}),
}, },
{ {
path: `${BASE_URL}/send_reset_password`, path: `${BASE_URL}/send_reset_password`,
component: LazyLoader({ component: lazy(
loader: () => import('@/containers/Authentication/SendResetPassword'), () => import('@/containers/Authentication/SendResetPassword'),
}), ),
}, },
{ {
path: `${BASE_URL}/reset_password/:token`, path: `${BASE_URL}/reset_password/:token`,
component: LazyLoader({ component: lazy(() => import('@/containers/Authentication/ResetPassword')),
loader: () => import('@/containers/Authentication/ResetPassword'),
}),
}, },
{ {
path: `${BASE_URL}/invite/:token/accept`, path: `${BASE_URL}/invite/:token/accept`,
component: LazyLoader({ component: lazy(() => import('@/containers/Authentication/InviteAccept')),
loader: () => import('@/containers/Authentication/InviteAccept'),
}),
}, },
{ {
path: `${BASE_URL}/register/email_confirmation`, path: `${BASE_URL}/register/email_confirmation`,
component: LazyLoader({ component: lazy(
loader: () => import('@/containers/Authentication/EmailConfirmation'), () => import('@/containers/Authentication/EmailConfirmation'),
}), ),
}, },
{ {
path: `${BASE_URL}/register`, path: `${BASE_URL}/register`,
component: LazyLoader({ component: lazy(() => import('@/containers/Authentication/Register')),
loader: () => import('@/containers/Authentication/Register'),
}),
}, },
]; ];

View File

@@ -1,88 +1,96 @@
// @ts-nocheck // @ts-nocheck
import { lazy } from 'react'; import { lazy } from 'react';
import General from '@/containers/Preferences/General/General';
import Users from '../containers/Preferences/Users/Users';
import Roles from '../containers/Preferences/Users/Roles/RolesForm/RolesFormPage';
import Accountant from '@/containers/Preferences/Accountant/Accountant';
import Currencies from '@/containers/Preferences/Currencies/Currencies';
import Item from '@/containers/Preferences/Item';
// import SMSIntegration from '../containers/Preferences/SMSIntegration';
import DefaultRoute from '../containers/Preferences/DefaultRoute';
import Warehouses from '../containers/Preferences/Warehouses';
import Branches from '../containers/Preferences/Branches';
import Invoices from '../containers/Preferences/Invoices/PreferencesInvoices';
import { PreferencesCreditNotes } from '../containers/Preferences/CreditNotes/PreferencesCreditNotes';
import { PreferencesEstimates } from '@/containers/Preferences/Estimates/PreferencesEstimates';
import { PreferencesReceipts } from '@/containers/Preferences/Receipts/PreferencesReceipts';
import BillingPage from '@/containers/Subscriptions/BillingPage';
const BASE_URL = '/preferences'; const BASE_URL = '/preferences';
export default [ export const getPreferenceRoutes = () => [
{ {
path: `${BASE_URL}/general`, path: `${BASE_URL}/general`,
component: General, component: lazy(() => import('@/containers/Preferences/General/General')),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/users`, path: `${BASE_URL}/users`,
component: Users, component: lazy(() => import('../containers/Preferences/Users/Users')),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/invoices`, path: `${BASE_URL}/invoices`,
component: Invoices, component: lazy(
() => import('../containers/Preferences/Invoices/PreferencesInvoices'),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/credit-notes`, path: `${BASE_URL}/credit-notes`,
component: PreferencesCreditNotes, component: lazy(() =>
import(
'../containers/Preferences/CreditNotes/PreferencesCreditNotes'
).then((module) => ({ default: module.PreferencesCreditNotes })),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/estimates`, path: `${BASE_URL}/estimates`,
component: PreferencesEstimates, component: lazy(() =>
import('@/containers/Preferences/Estimates/PreferencesEstimates').then(
(module) => ({ default: module.PreferencesEstimates }),
),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/receipts`, path: `${BASE_URL}/receipts`,
component: PreferencesReceipts, component: lazy(() =>
import('@/containers/Preferences/Receipts/PreferencesReceipts').then(
(module) => ({ default: module.PreferencesReceipts }),
),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/roles`, path: `${BASE_URL}/roles`,
component: Roles, component: lazy(
() =>
import('../containers/Preferences/Users/Roles/RolesForm/RolesFormPage'),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/roles/:id`, path: `${BASE_URL}/roles/:id`,
component: Roles, component: lazy(
() =>
import('../containers/Preferences/Users/Roles/RolesForm/RolesFormPage'),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/currencies`, path: `${BASE_URL}/currencies`,
component: Currencies, component: lazy(
() => import('@/containers/Preferences/Currencies/Currencies'),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/warehouses`, path: `${BASE_URL}/warehouses`,
component: Warehouses, component: lazy(() => import('../containers/Preferences/Warehouses')),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/branches`, path: `${BASE_URL}/branches`,
component: Branches, component: lazy(() => import('../containers/Preferences/Branches')),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/accountant`, path: `${BASE_URL}/accountant`,
component: Accountant, component: lazy(
() => import('@/containers/Preferences/Accountant/Accountant'),
),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/items`, path: `${BASE_URL}/items`,
component: Item, component: lazy(() => import('@/containers/Preferences/Item')),
exact: true, exact: true,
}, },
// { // {
@@ -92,12 +100,12 @@ export default [
// }, // },
{ {
path: `${BASE_URL}/billing`, path: `${BASE_URL}/billing`,
component: BillingPage, component: lazy(() => import('@/containers/Subscriptions/BillingPage')),
exact: true, exact: true,
}, },
{ {
path: `${BASE_URL}/`, path: `${BASE_URL}/`,
component: DefaultRoute, component: lazy(() => import('../containers/Preferences/DefaultRoute')),
exact: true, exact: true,
}, },
]; ];