A lazy-loading aware version of react router DOM.
SPA are great but bundle easily become huge. Lazy loading can mitigate the problem, but you loose responsiveness. Preloading components can workaround this.
react-router-dom-lazy solves this problem by making the routing and navigation aware of lazy loadable components and preloads them if a link enters the viewport, or you hover it. This anticipates the loading before navigation time, improving application responsiveness.
npm i --save react-router-dom-lazy
Most of the apis are identical to react-router-dom
so you just need to
change the import to start using it.
You need to wrap the application with the Provider
import { PreloadProvider } from 'react-router-dom-lazy';
ReactDOM.render(
<React.StrictMode>
<PreloadProvider>
<Router>
<App />
</Router>
</PreloadProvider>
</React.StrictMode>,
document.getElementById('root'),
);
To import a lazy component page use lazyWithPreload
instead of lazy. This function wraps
React.lazy
, adding an imperative load function.
import { lazyWithPreload } from 'react-router-dom-lazy';
const PageA = lazyWithPreload(() => import('./PageA'));
react-router does not support non direct-child
route component at v5 inside a switch. If you want to use a switch with preloadable routes
you need to import a Switch wrapper from react-router-dom-lazy
;
import { lazyWithPreload, PreloadingSwitch as Switch } from 'react-router-dom-lazy';
import { Route } from 'react-router-dom';
const PageA = lazyWithPreload(() => import('./PageA'));
const PageB = lazyWithPreload(() => import('./PageB'));
...
return (
<Suspense>
<Switch>
<Route component={PageA}
path="/a" />
<Route component={PageB}
path="/b" />
</Switch>
</Suspense>
);
Configure your routing the way you are used to! You can not use render
and children as in react-router-dom
, because they will not use preloading.
import { lazyWithPreload, Switch } from 'react-router-dom-lazy';
import { Route } from 'react-router-dom';
const PageA = lazyWithPreload(() => import('./PageA'));
const PageB = lazyWithPreload(() => import('./PageB'));
...
return (
<Suspense>
<Switch>
<Route component={PageA}
path="/a" />
<Route component={PageB}
path="/b" />
</Switch>
</Suspense>
);
Link is exactly the same as react-router-dom plus you can disable preloading or change preloading behaviour at link level. By default, link is the preloading starting point: based on the viewport visibility of it and by onHover.
import { Link } from 'react-router-dom-lazy';
<Link to="/a">
a
</Link>
You can completely disable preloading of a link.
import { Link } from 'react-router-dom-lazy';
<Link to="/a" preload={false}>
a
</Link>
Or you can disable just a behaviour, for a page that is maybe less visited by the user, it is not necessary to load it when the link become visibile, and you can keep the hover only.
import { Link } from 'react-router-dom-lazy';
<Link to="/a" preloadWhenVisible={false}>
a
</Link>
If you are in a menu section, and you want to avoid that all the links visible will be preloaded instantly, you can override preloading props at any point in the tree, and all the children will use that config
<PreloadConfig config={{ intersectionEnabled: false }}>
<Link to="/a">
a
</Link>
</PreloadConfig>
Do you have a custom link component? do you want to use preloading in a custom way? No problem we got this case covered by exposing a preloading hook that you can use wherever you want