@route-resource-preload/react
v1.0.0-beta.27
Published
Support automatic the preloading of resources ( JS / Component / Module-Federation / UMD / Svg / Png , Etc) and providing the best user experience.
Downloads
53
Maintainers
Readme
@route-resource-preload/react - Any react can be split
🚀 Focus on improving the first screen loading speed of applications and providing the best user experience, inspiration comes from the preloading of NextJS.
中文文档
Comparison
As we can see from the gif, the display time of the loading component is greatly reduced by route-resource-preload
relative to react.lazy
.
Why do you need route-resource-preload ?
Split modules loads as needed
, improving the first screen loading experience of your App.Minimize dynamic component loading time
and providing the best user experience.- Support
automatic the preloading of resources
( JS / Component / Module-Federation / UMD / Svg / Png , Etc) and providing the best user experience. - Support
manually to preload
. - Support
typescript
. - Support
React <Suspense>
.
Why route-resoure-preload over react.lazy?
route-resource-preload
support code splitting
of components, and support automatic preloading
and manual preloading
of components to avoid poor component interaction experience due to component rendering delays.
Why route-resource-preload over webpack-prefetch/preload and loadable-components-prefetch/preload?
- Control
when to preload in more detail
- Support preload
Module-Federation
- Support
More types
of resource (image/font/svg/css/js/...)
Online Demo Test
Component | Normal Lazy Load(ms) | Preload (ms) --- | --- | --- Simple Component (one-resource) | 150 | 1 Complex Component (six-resource) | 350 | 10
It can be seen from the table that preloading significantly improves the loading speed of components, especially for complex components, the improvement of loading speed is more obvious. This shows that in complex business scenarios,
preloading can significantly improve component loading speed and user experience
.
React Demo Source
Install
npm install @route-resource-preload/webpack-plugin @route-resource-preload/react
Using in react
Method 1 - Manually To Preload Single Component Based on Dynamic
import { dynamic } from '@route-resource-preload/react'
const Image = dynamic({
loader: () => import('Components'),
loading: (props) => <>loading...</>,
})
const handleClick = () => {
// execute preloading
Image.preload()
}
export default function Main(props){
return <div onClick={handleClick}>
<Image {...props} />
</div>
}
Method 2 - Manually To Preload Multiple Components
- Step 1: First, you need add
plugin
in your build config.
const RouteResourcePreloadPlugin = require('@route-resource-preload/webpack-plugin')
webpack: {
plugins: {
add: [
new RouteResourcePreloadPlugin({
// [the-preloading-flag]: ['path']
// project's components(modules)
modulePreloadMap: {
"flagA": ["../components/A"]
},
// module-federation's components(modules)
mfPreloadMap: {
"flagMF": ["ling_core/Components"]
},
// static assets (just like js/css/png/jpg/font, etc.)
assetPreloadMap: {
"flagA": ['https://domain.com/xxx.png']
}
})
]
},
}
- Step 2: Create a
Preloader
andrun
import { Preloader } from '@route-resource-preload/react'
const preloader = new Preloader()
// execute preloading
preloader.run('flagA')
Method 3 - Automatic Preloading.
- Step 1: First, you need add
plugin
in your build config.
const RouteResourcePreloadPlugin = require('@route-resource-preload/webpack-plugin')
webpack: {
plugins: {
add: [
new RouteResourcePreloadPlugin({
// [the-preloading-flag]: ['path']
// project's components(modules)
modulePreloadMap: {
"flagA": ["../components/A"]
},
// module-federation's components(modules)
mfPreloadMap: {
"flagMF": ["ling_core/Components"]
},
// static assets (just like js/css/png/jpg/font, etc.)
assetPreloadMap: {
"flagA": ['https://domain.com/xxx.png']
}
})
]
},
}
- Step 2:
Dynamic
import component and renderPreloadLink
import { dynamic, PreloadLink } from '@route-resource-preload/react'
// project's component
const ComponentA = dynamic({
loader: ()=>import('../components/A'),
loading: () => <>loading...</>
})
// module-federation's component
const Image = dynamic({
loader: ()=>import('your_lib/Components'),
loading: () => <>loading...</>,
submodule: 'Image' // may be you didn't export default, just like " export { Image, ...Others } " in js.
})
export default function Main(props){
return <>
<PreloadLink flag="flagA" onClick={()=>{
navigate('/A') // navigate comes from react-router-dom, you can custom your code.
}}
>
Preload Component A
</PreloadLink>
<PreloadLink flag="flagMF">
{/* Link comes from react-router-dom, you can custom your code. */}
<Link to="flagMF" >Preload MF</Link>
</PreloadLink>
</>
}
API
dynamic - Split your component code and load it dynamically
const Modal = dynamic({
loader: () => import('xxx/Modal'),
// loading: () => <>loading...</>,
// suspense: true,
// submodule: 'submodule',
// visible: true,
})
Param | Description | Type | Default Value | necessary
---- | ---- | ---- | ---- | ---
loader | dynamic import module | () => Promise<Record<string, T extends ComponentType>>| - | ✅
loading | A spinner for displaying loading state | ComponentType | - | ❌
submodule | maybe you didn't export default, you need it | string | - | ❌
visible | whether to render immediately after the components in the view are preloaded | boolean | true | ❌
suspense | use react <Suspense>
for displaying loading state | boolean | - | ❌
dynamic
will return a HOC withonEnd
prop, which will call back after the component is dynamically rendered to adapt to complex and changeable business scenarios, such as custom loading package elements/or computing component rendering time-consuming, etc.
function CommonLoading (props: { moduleName: string }) {
const { moduleName } = props
const [loading, setLoading] = useState(true)
const Com = useMemo(()=>dynamic({ loader: () => import(`${moduleName}`)}),[moduleName])
// custom loading
return <Spin spinning={loading}>
<Com onEnd={()=>{ setLoading(false)}} />
</Spin>
}
<CommonLoading moduleName={moduleName} />
Preloader - Manually to preload based on
flag
const preload = new Preloader(options)
preload.run('flag') // plugin flag
Param | Description | Type | Default Value | necessary ---- | ---- | ---- | ---- | --- publicPath | yout server publicPath | string | - | ❌
Preloader's
publicPath
is the same as RouteResourcePreloadPlugin'spublicPath
PreloadLink - Automatic the preloading of resources based on
flag
<PreloadLink flag="flagA" >
Preload Component
</PreloadLink>
Props | Description | Type | Default Value | necessary ---- | ---- | ---- | ---- | --- flag | the preloading flag | string | - | ✅ children | children ReactNode | ReactNode | - | ✅ action | trigger preload action | string (init / inview / hover) | hover | ❌ onClick | PreloadLink click event | () => void | - | ❌ className | PreloadLink classname | string | - | ❌ publicPath | yout server publicPath | string | - | ❌
PreloadLink's
publicPath
is the same as RouteResourcePreloadPlugin'spublicPath
Plugin
Webpack-RouteResourcePreloadPlugin
RouteResourcePreloadPlugin's
publicPath
is the same as PreloadLink'spublicPath
new RouteResourcePreloadPlugin({
// [the-preloading-flag]: ['path']
// project's components(modules)
modulePreloadMap: {
"flagA": ["../components/A"]
},
// module-federation's components(modules)
mfPreloadMap: {
"flagMF": ["xxx/Components"]
},
// static assets (just like js/css/png/jpg/font, etc.)
assetPreloadMap: {
"flagA": ['https://domain.com/xxx.png']
}
})
Params | Description | Type | Default Value | necessary ---- | ---- | ---- | ---- | --- modulePreloadMap | project's components(modules) | modulePreloadMap Object | - | ❌ mfPreloadMap | module-federation's components(modules) | mfPreloadMap Object | - | ❌ assetPreloadMap | static assets | assetPreloadMap Object | - | ❌ publicPath | your server publicPath | string | - | ❌
Others
init / inview / hover
value | Description --- | --- init | Trigger preload after PreloadLink rendering inview | Trigger preload after PreloadLink in the view hover | Trigger preload after your mouse hover in the PreloadLink
modulePreloadMap Object
{
"flagA": ["../components/A"],
// [the-preloading-flag]: ['your project's components path']
}
mfPreloadMap Object
{
"flagMF": ["ling_core/Components"]
// [the-preloading-flag]: ['your module-federation's components path']
}
assetPreloadMap Object
{
"flagA": ['https://domain.com/xxx.png']
// [the-preloading-flag]: ['your static assets link'] (image/font/svg/css/js/...)
}