A future focused async component loading library for React. Comes packed with loading phases to enable fine-grained performance optimisations.
Today, React's native solution for asynchronously loading components, React.lazy
, does not work on the server. To get around this, developers have had to invent their own solutions to the problem such as react-loadable
and loadable-components
. These libraries however will not be compatible with Suspense
out of the box and their APIs are quite different to the direction the React team are taking. It's also clear that this has become such a core part of building React apps at scale that it makes sense to rely on React to fill this requirement rather than third party libraries.
In addition to this we have to consider that, certainly from a performance point of view, not all components are created equal. It does not make sense to load components which are required for your user's first meaningful paint at the same time as those which are not. Doing so will impact your user's experience negatively. Likewise it is best to be able to opt-out of SSR for a component if you know that this will delay response times from the server significantly or if the component will not be able to be rendered in your Node environment.
React Loosely Lazy solves both of these problems with a server side compatible API that looks just like Suspense
, while also providing an opt-in, phase based loading mechanism.
- Same code on server and client, handling SSR transparently
- Loading priority support via phases
- Customisable deferred loading and phases definition
- Preloading support
- Works with both
React.render()
andReact.hydrate()
- Babel plugin that works on both client and server to ensure cleaner code and synchronous imports in Node
import { lazyForPaint, LazySuspense } from 'react-loosely-lazy';
const MyAsyncComponent = lazyForPaint(() => import('./MyComponent'));
const Loading = () => <div>loading...</div>;
const App = () => (
<LazySuspense fallback={Loading}>
<AsyncMyComponent />
</LazySuspense>
);
module: {
rules: [{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [...yourPresets],
plugins: [...yourOtherPlugins, ['react-loosely-lazy/babel-plugin']],
},
},
]
}]
}
module: {
rules: [{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [...yourPresets],
plugins: [...yourOtherPlugins, ['react-loosely-lazy/babel-plugin', { client: true }]],
},
},
]
}]
}
npm i react-loosely-lazy
# or
yarn add react-loosely-lazy
import { lazyForPaint, LazySuspense } from 'react-loosely-lazy';
const AsyncMyComponent = lazyForPaint(() => import('./MyComponent'));
const App = () => (
<LazySuspense fallback="...">
<AsyncMyComponent />
</LazySuspense>
);
import { lazyAfterPaint, LazySuspense } from 'react-loosely-lazy';
const AsyncMyComponent = lazyAfterPaint(() => import('./MyComponent'), {
ssr: false,
});
const App = () => (
<LazySuspense fallback={<MyComponentSkeleton />}>
<AsyncMyComponent />
</LazySuspense>
);
import { lazyAfterPaint, useLazyPhase, LazySuspense } from 'react-loosely-lazy';
const AsyncMyComponent = lazyAfterPaint(() => import('./MyComponent'));
const App = () => {
const { startNextPhase } = useLazyPhase();
// eg start loading MyComponent after the app is mounted
useEffect(() => {
startNextPhase();
}, [startNextPhase]);
return (
<LazySuspense fallback="...">
<AsyncMyComponent />
</LazySuspense>
);
};
import { lazy, LazyWait, LazySuspense } from 'react-loosely-lazy';
const AsyncMyComponent = lazy(() => import('./MyComponent'));
const App = () => {
const [shouldLoad, setLoad] = useState(false);
return (
<>
<button onClick={() => setLoad(true)}>Load</button>
<LazyWait until={shouldLoad}>
<LazySuspense fallback={shouldLoad ? <MyComponentSkeleton /> : null}>
<AsyncMyComponent />
</LazySuspense>
</LazyWait>
</>
);
};
Note: The examples are currently not working as intended so it's best not to use them for now. We will be fixing these shortly!
See react-loosely-lazy
in action: run npm run start
and then go and check: http://localhost:8080/
Thank you for considering a contribution to react-loosely-lazy
! Before doing so, please make sure to read our contribution guidelines.
To test your changes you can run the examples (with npm run start
).
Also, make sure you run npm run preversion
before creating you PR so you will double check that linting, types and tests are fine.
Copyright (c) 2020 Atlassian and others. Apache 2.0 licensed, see LICENSE file.