0

In our React application's App.js file, lazy loading components that are not needed on the initial page load definitely helps with the speed of our first page load. However, it also seems to have a negative impact on the rest of the website's performance, because all of the lazy-loaded pages now still need to be loaded the first time a user visits each respective page:

const ConfController = lazy(() => import('./containers/StatsPages/Conference/ConfController'));

<Suspense fallback={ourLoadingSpinner}>
    <Routes>
        <Route exact path='/' element={<HomePage />} />
        <Route exact path='/stats/:competitionId/conferences/:conferenceId/:view' element={<ConfController />} />
        ...
    </Routes>
</Suspense>

The first time a user visits ConfController, or any of the other 2-dozen components that are lazy-loaded, they get hit with a brief-but-not-frictionless ourLoadingSpinner for a fraction of a second. I guess this is the lazy-loading trade-off? Initial page-load speed vs these other minor loads every time a lazy-loaded page finally needs to load. I almost feel like I'd rather the website take an extra second to load, rather than have all of these fraction-of-a-second loads on all other pages.

I'm envisioning a middle ground solution, where pages don't necessarily load immediately the first time the website is visited (to benefit the initial load time), however these pages do get loaded in the background a few seconds shortly later (to avoid the suspense loading fallback every time a different page is visited for the first time). Some solution that is beneficial for our initial page load time, while also loading the components before most or all of them are actually visited by the user, to avoid the Suspense fallback loading.

Canovice
  • 9,012
  • 22
  • 93
  • 211

1 Answers1

1

It seems duplicative as this solution seems to load the component twice, but the below code does eliminate the ourLoadingSpinner from running when we navigate to the ConfController page.

const ConfController = lazy(() => import('./containers/StatsPages/Conference/ConfController'));

useEffect(() => {
    import('./containers/StatsPages/Conference/ConfController').then(module => {
        module.default.preload();
        // module.preload();
    });
}, []);

Seems to work with both module.preload(); and module.default.preload();. Can anyone identify any issues with this solution? It seems like it gives us the best of both quick initial load times, as well as no downstream negative performance? Simply loads the lazy-loaded pages after the initial page-load / after the component has mounted?

Edit: at the time of posting the above solution, we had not realized that we were getting errors in the console for module.default.preload() is not a function, and module.preload() is not a function. The following updated code using the @loadable/component npm package appears to be working better:

// const ConfController = lazy(() => import('./containers/StatsPages/Conference/ConfController'));
import loadable from '@loadable/component';
const ConfController = loadable(() => import('./containers/StatsPages/Conference/ConfController'));

function App() {
    useEffect(() => {
        ConfController.preload();
    }, []);
    ... 
}
Canovice
  • 9,012
  • 22
  • 93
  • 211