Code Monkey home page Code Monkey logo

wudu8 / route-resource-preload Goto Github PK

View Code? Open in Web Editor NEW

This project forked from awesomedevin/route-resource-preload

0.0 0.0 0.0 10.6 MB

πŸš€ Focus on improving the first screen loading speed of applications and providing the best user experience, inspiration comes from the preloading of NextJS. (https://web.dev/route-prefetching-in-nextjs/)

Home Page: https://route-resource-preload.netlify.app

License: MIT License

JavaScript 7.76% TypeScript 92.24%

route-resource-preload's Introduction

route-resource-preload - Any code 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

Based-on-react.lazy-normal-loading-effect.gif

Based-on-route-resource-preload-effect.gif

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 ?

Why route-resoure-preload over react.lazy?

  • Support automatic preloading and manual preloading of components to avoid poor component interaction experience due to component rendering delays.
  • Support code-splitting and preloading of non-component
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.

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']
        }
      })
    ]
  },
}
  1. 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']
        }
      })
    ]
  },
}
  1. 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,
})
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 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
Param Description Type Default Value necessary
publicPath yout server publicPath string - ❌

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>
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'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']
  }
})
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/...)
}

Stargazers

Stargazers repo roster for @AwesomeDevin/route-resource-preload

Forkers

Forkers repo roster for @AwesomeDevin/route-resource-preload

route-resource-preload's People

Contributors

awesomedevin avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.