Problem scenario

In large single-page applications, for the consideration of performance and the requirement of first-screen loading speed, we generally use webpack’s code splitting and vue-Router’s lazy loading function to divide our code into modules, and only load a module from the server when needed.

However, this solution also has its problems. When the network environment is poor, we visit a routing module for the first time, and it takes a certain amount of time to load the resources of the module, our application will be in a state of no response during this period of time, resulting in poor user experience.

The solution

In this case, on the one hand, we can reduce the volume of routing module code and shorten the loading time by CDN storage for static resources; on the other hand, we can use asynchronous components on routing components to display loading and error states, so that users can get clear operation feedback. Vue official documentation – Dynamic Components & Asynchronous components

The specific implementation

  1. Declare methods that return a Promise object based on the Vue dynamic component factory function
* @param {Object} AsyncView () {import();'@/components/home/Home.vue')
 * @returnObject} returns a Promise Object */functionLazyLoadView (AsyncView) {const AsyncHandler = () => ({// Load component (should be a 'Promise' object) component: AsyncView, // AsyncView loading: require('@/components/public/RouteLoading.vue').default, // error: require('@/components/public/RouteError.vue').default, // display the component delay time when loading. The default value is 200 (ms) delay: 200, // If timeout is provided and component loading times out, // The component used when loading failed is used. Default: 'Infinity' timeout: 10000});return Promise.resolve({
    functional: true,
    render (h, { data, children }) {
      returnh(AsyncHandler, data, children); }}); }Copy the code
  1. The introduction of the routing
const helloWorld = () => lazyLoadView(import('@/components/helloWorld'))
Copy the code
  1. Vue – used in the router
routes: [
    {
        path: '/helloWorld',
        name: 'helloWorld',
        component: helloWorld
    }
]
Copy the code

At this point, the transformation has been completed. When you load a component’s resources for the first time (you can set the network speed to slow 3G, which is more obvious), the content of the component you are loading will be displayed. When the component is not loaded within the timeout period, the content of the error component will be displayed. In the case of low-speed network or disconnection, image resources in the ERROR component may fail to be loaded.)

The problem with routing hook failures when using asynchronous components

After reconstructing the route import mode using the configuration in this article, there will be a problem that the route hook cannot be used. This problem is also found just now. After reviewing the data, IT is found that the vue-Router does not support this method at present. The official explanation:

> WARNING: Components loaded with this strategy will **not** have access to
in-component guards, such as `beforeRouteEnter`, `beforeRouteUpdate`, and
`beforeRouteLeave`. If you need to use these, you must either use route-level
guards instead or lazy-load the component directly, without handling loading
state.
Copy the code

Link: github.com/vuejs/vue-r…

A solution to hook failure using asynchronous components

  1. Pages that need to use routed hooks abandon asynchronous loading and use plain lazy loading
  2. Use created, mounted, and other created hooks to replace routing hooks.