1.0.0-beta.23 β€’ Published 9 months ago

@route-resource-preload/webpack-plugin v1.0.0-beta.23

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

@route-resource-preload/webpack-plugin - Any code can be split

Build Size Version

πŸš€ 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

ComponentNormal Lazy Load(ms)Preload (ms)
Simple Component (one-resource)1501
Complex Component (six-resource)35010

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

  1. 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']
            }
          })
        ]
      },
    }
  2. Step 2: Create a Preloader and run

    import { Preloader } from '@route-resource-preload/react'
    
    const preloader = new Preloader()
    
    // execute preloading
    preloader.run('flagA')

Method 3 - Automatic Preloading.

  1. 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']
            }
          })
        ]
      },
    }
  2. Step 2: Dynamic import component and render PreloadLink

    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,
})
ParamDescriptionTypeDefault Valuenecessary
loaderdynamic import module() => Promise<Record<string, T extends ComponentType>>-βœ…
loadingA spinner for displaying loading stateComponentType-❌
submodulemaybe you didn't export default, you need itstring-❌
visiblewhether to render immediately after the components in the view are preloadedbooleantrue❌
suspenseuse react <Suspense> for displaying loading stateboolean-❌

dynamic will return a HOC with onEnd 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
ParamDescriptionTypeDefault Valuenecessary
publicPathyout server publicPathstring-❌

Preloader's publicPath is the same as RouteResourcePreloadPlugin's publicPath

  • PreloadLink - Automatic the preloading of resources based on flag

<PreloadLink  flag="flagA"  >
  Preload Component
</PreloadLink>
PropsDescriptionTypeDefault Valuenecessary
flagthe preloading flagstring-βœ…
childrenchildren ReactNodeReactNode-βœ…
actiontrigger preload actionstring (init / inview / hover)hover❌
onClickPreloadLink click event() => void-❌
classNamePreloadLink classnamestring-❌
publicPathyout server publicPathstring-❌

PreloadLink's publicPath is the same as RouteResourcePreloadPlugin's publicPath

Plugin

  • Webpack-RouteResourcePreloadPlugin

    RouteResourcePreloadPlugin's publicPath is the same as PreloadLink's publicPath

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']
  }
})
ParamsDescriptionTypeDefault Valuenecessary
modulePreloadMapproject's components(modules)modulePreloadMap Object-❌
mfPreloadMapmodule-federation's components(modules)mfPreloadMap Object-❌
assetPreloadMapstatic assetsassetPreloadMap Object-❌
publicPathyour server publicPathstring-❌

Others

  • init / inview / hover

    valueDescription
    initTrigger preload after PreloadLink rendering
    inviewTrigger preload after PreloadLink in the view
    hoverTrigger 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/...)
}
1.0.0-beta.23

9 months ago

1.0.0-beta.20

1 year ago

1.0.0-beta.21

1 year ago

1.0.0-beta.19

1 year ago

1.0.0-beta.18

1 year ago

1.0.0-beta.17

1 year ago

1.0.0-beta.16

1 year ago

1.0.0-beta.15

1 year ago

1.0.0-beta.14

1 year ago

1.0.0-beta.13

1 year ago

1.0.0-beta.12

1 year ago

1.0.0-beta.11

1 year ago

1.0.0-beta.10

1 year ago

1.0.0-beta.9

1 year ago

1.0.0-beta.8

1 year ago

1.0.0-beta.7

1 year ago

1.0.0-beta.6

1 year ago

1.0.0-beta.5

1 year ago

1.0.0-beta.4

1 year ago

1.0.0-beta.3

1 year ago

1.0.0-beta.2

1 year ago

1.0.0-beta.1

1 year ago