Skip to content

Commit 66f6e1d

Browse files
authored
Merge pull request #702 from back4app/implementSuspense
Implement suspense
2 parents 36ed919 + 07ac7d7 commit 66f6e1d

File tree

4 files changed

+72
-15
lines changed

4 files changed

+72
-15
lines changed

src/dashboard/Dashboard.js

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import AppData from './AppData.react';
1212
import AppsIndex from './Apps/AppsIndex.react';
1313
import AppsManager from 'lib/AppsManager';
1414
import Browser from './Data/Browser/Browser.react';
15-
import CloudCode from './Data/CloudCode/B4ACloudCode.react';
15+
// import CloudCode from './Data/CloudCode/B4ACloudCode.react';
1616
import AppOverview from './Data/AppOverview/AppOverview.react';
1717
import Config from './Data/Config/Config.react';
1818
import FourOhFour from 'components/FourOhFour/FourOhFour.react';
1919
import GeneralSettings from './Settings/GeneralSettings.react';
20-
import GraphQLConsole from './Data/ApiConsole/GraphQLConsole.react';
20+
// import GraphQLConsole from './Data/ApiConsole/GraphQLConsole.react';
2121
// import HostingSettings from './Settings/HostingSettings.react';
2222
import HubConnections from './Hub/HubConnections.react';
2323
import IndexManager from './IndexManager/IndexManager.react'
@@ -36,7 +36,7 @@ import { get } from 'lib/AJAX';
3636
import { setBasePath } from 'lib/AJAX';
3737
import ServerSettings from 'dashboard/ServerSettings/ServerSettings.react';
3838
import { Helmet } from 'react-helmet';
39-
import Playground from './Data/Playground/Playground.react';
39+
// import Playground from './Data/Playground/Playground.react';
4040
import axios from 'lib/axios';
4141
// import moment from 'moment';
4242
import B4aConnectPage from './B4aConnectPage/B4aConnectPage.react';
@@ -49,7 +49,7 @@ import PushDetails from './Push/PushDetails.react';
4949
import PushIndex from './Push/PushIndex.react';
5050
import PushNew from './Push/PushNew.react';
5151
// import PushSettings from './Settings/PushSettings.react';
52-
import React, { useCallback, useEffect, useMemo, useState } from 'react';
52+
import React, { useCallback, useEffect, useMemo, useState, Suspense, lazy } from 'react';
5353
import RestConsole from './Data/ApiConsole/RestConsole.react';
5454
// import SchemaOverview from './Data/Browser/SchemaOverview.react';
5555
import SecuritySettings from './Settings/SecuritySettings.react';
@@ -66,6 +66,10 @@ import back4app2 from '../lib/back4app2';
6666
import { initializeAmplitude } from 'lib/amplitudeEvents';
6767
import { setUser as setSentryUser } from '@sentry/react';
6868

69+
const LazyGraphQLConsole = lazy(() => import('./Data/ApiConsole/GraphQLConsole.react'));
70+
const LazyPlayground = lazy(() => import('./Data/Playground/Playground.react'));
71+
const LazyCloudCode = lazy(() => import('./Data/CloudCode/B4ACloudCode.react'));
72+
6973
const ShowSchemaOverview = false; //In progress features. Change false to true to work on this feature.
7074

7175
// class Empty extends React.Component {
@@ -150,6 +154,44 @@ const waitForScriptToLoad = async conditionFn => {
150154
throw new Error('Script not loaded yet!');
151155
};
152156

157+
const preloadMap = {
158+
cloudCode: () => import('./Data/CloudCode/B4ACloudCode.react'),
159+
graphqlConsole: () => import('./Data/ApiConsole/GraphQLConsole.react'),
160+
playground: () => import('./Data/Playground/Playground.react'),
161+
};
162+
163+
// Preload all routes with proper error handling and logging
164+
const preloadRoute = async (routeName, preloadFn) => {
165+
try {
166+
await preloadFn();
167+
console.log(`Successfully preloaded route: ${routeName}`);
168+
} catch (err) {
169+
console.error(`Error preloading route ${routeName}:`, err);
170+
}
171+
};
172+
173+
// Preload all routes in parallel
174+
const preloadAllRoutes = () => {
175+
console.log('Preloading routes...');
176+
return Promise.all(
177+
Object.entries(preloadMap).map(([routeName, preloadFn]) =>
178+
preloadRoute(routeName, preloadFn)
179+
)
180+
);
181+
};
182+
183+
const LoadingComponent = () => (
184+
<div className={baseStyles.center} style={{ background: '#0F1C32' }}>
185+
<B4aLoader />
186+
</div>
187+
);
188+
189+
const LazyComponentWrapper = ({ children }) => (
190+
<Suspense fallback={<LoadingComponent />}>
191+
{children}
192+
</Suspense>
193+
);
194+
153195
class Dashboard extends React.Component {
154196
constructor(props) {
155197
super();
@@ -167,6 +209,11 @@ class Dashboard extends React.Component {
167209
}
168210

169211
componentDidMount() {
212+
// Start preloading routes immediately but don't block on it
213+
preloadAllRoutes().finally(() => {
214+
console.log('Route preloading complete');
215+
});
216+
170217
get('/parse-dashboard-config.json').then(({ apps, newFeaturesInLatestVersion = [], user }) => {
171218
fetchHubUser().then(userDetail => {
172219
user.createdAt = userDetail.createdAt;
@@ -390,8 +437,8 @@ class Dashboard extends React.Component {
390437
const ApiConsoleRoute = (
391438
<Route element={<ApiConsole />}>
392439
<Route path="rest" element={<RestConsole />} />
393-
<Route path="graphql" element={<GraphQLConsole />} />
394-
<Route path="js_console" element={<Playground />} />
440+
<Route path="graphql" element={<LazyComponentWrapper><LazyGraphQLConsole /></LazyComponentWrapper>} />
441+
<Route path="js_console" element={<LazyComponentWrapper><LazyPlayground /></LazyComponentWrapper>} />
395442
<Route index element={<Navigate replace to="rest" />} />
396443
</Route>
397444
);
@@ -407,7 +454,7 @@ class Dashboard extends React.Component {
407454
<Route path="browser/:className" element={<BrowserRoute />} />
408455
<Route path="browser" element={<BrowserRoute />} />
409456

410-
<Route path="cloud_code" element={<CloudCode />} />
457+
<Route path="cloud_code" element={<LazyComponentWrapper><LazyCloudCode /></LazyComponentWrapper>} />
411458
<Route path="webhooks" element={<Webhooks />} />
412459

413460
<Route path="jobs">{JobsRoute}</Route>

src/dashboard/Data/AppOverview/AppOverview.react.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* This source code is licensed under the license found in the LICENSE file in
77
* the root directory of this source tree.
88
*/
9-
import React from 'react';
9+
import React, { Suspense, lazy } from 'react';
1010
import DashboardView from 'dashboard/DashboardView.react';
1111
import styles from 'dashboard/Data/AppOverview/AppOverview.scss';
1212
import { withRouter } from 'lib/withRouter';
@@ -18,11 +18,12 @@ import AppSecurityCard from './AppSecurityCard.react';
1818
import AppPerformanceCard from './AppPerformanceCard.react';
1919
import AppLoadingText from './AppLoadingText.react';
2020
import B4aTooltip from 'components/Tooltip/B4aTooltip.react';
21-
import ConnectAppModal from './ConnectAppModal.react';
21+
// import ConnectAppModal from './ConnectAppModal.react';
2222
import OnboardingBoxes from './OnboardingBoxes.react';
2323
import AccountManager from 'lib/AccountManager';
2424
import { amplitudeLogEvent } from 'lib/amplitudeEvents';
2525

26+
const LazyConnectAppModal = lazy(() => import('./ConnectAppModal.react'));
2627
@withRouter
2728
class AppOverview extends DashboardView {
2829
constructor() {
@@ -73,6 +74,10 @@ class AppOverview extends DashboardView {
7374
this.loadCardInformation();
7475
}
7576

77+
componentDidMount() {
78+
import('./ConnectAppModal.react');
79+
}
80+
7681
copyText(copyText = '') {
7782
if (navigator) {
7883
navigator.clipboard.writeText(copyText);
@@ -303,7 +308,9 @@ class AppOverview extends DashboardView {
303308
</div>
304309

305310
{this.state.showConnectAppModal && (
306-
<ConnectAppModal closeModal={() => this.setState({ showConnectAppModal: false })} />
311+
<Suspense fallback={'Loading...'}>
312+
<LazyConnectAppModal closeModal={() => this.setState({ showConnectAppModal: false })} />
313+
</Suspense>
307314
)}
308315
</div>
309316
);

src/dashboard/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ import './instrument';
99
import 'core-js/stable';
1010
import 'regenerator-runtime/runtime';
1111
import Immutable from 'immutable';
12-
import installDevTools from 'immutable-devtools';
12+
// import installDevTools from 'immutable-devtools';
1313
import React from 'react';
1414
import ReactDOM from 'react-dom';
1515
import Dashboard from './Dashboard';
1616

1717
require('stylesheets/fonts.scss');
1818
require('graphiql/graphiql.min.css');
19-
installDevTools(Immutable);
19+
20+
if (process.env.NODE_ENV !== 'production') {
21+
const installDevTools = require('immutable-devtools');
22+
installDevTools(Immutable);
23+
}
2024

2125
const path = window.PARSE_DASHBOARD_PATH || '/';
2226
ReactDOM.render(<Dashboard path={path} />, document.getElementById('browser_mount'));

webpack/homolog.config.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ const TerserPlugin = require('terser-webpack-plugin');
55
configuration.plugins.push(
66
new webpack.DefinePlugin({
77
'process.env': {
8-
'NODE_ENV': JSON.stringify('homolog'),
9-
'SENTRY_ENV': JSON.stringify('homolog')
8+
'NODE_ENV': JSON.stringify('homolog')
109
}
1110
}),
1211
new webpack.SourceMapDevToolPlugin({
@@ -38,4 +37,4 @@ configuration.optimization = {
3837
]
3938
}
4039

41-
module.exports = configuration;
40+
module.exports = configuration;

0 commit comments

Comments
 (0)