Using async components with loading and error components in Vue Router

1.5k Views Asked by At

I am trying to do the following:

import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import LoadingComponent from '@/components/Loading.vue';

Vue.use(Router);

const router = new Router({
    routes: [
        {
            path: "/",
            name: "home",
            component: Home
        },
        {
            path: "/about",
            name: "about",
            component: () => ({
                component: import("./views/About.vue"),
                loading: LoadingComponent,
                delay: 1
            })
        }
    ]
});

export default router;

However loading component is never showing, even when I set network to Slow 3G. This happens only when I use async components in router, everywhere else loading components shows after delay.

Is this not supported by Vue Router or am I doing something wrong?

1

There are 1 best solutions below

0
On

I came across the answer to this question by digging through github issues on vue-router. It turns out you can't just use async components like the docs imply you can.

To quote from here: https://github.com/vuejs/vue-router/pull/2140/files?short_path=7d99926#diff-7d999265ce5b22152fdffee108ca6385

Routes can currently only resolve to a single component in Vue Router. So to make this work, you'll need a helper function to create an intermediary component, like this:

const lazyLoadRoute = AsyncView => {
    const AsyncHandler = () => ({
        component: AsyncView,
        loading: Spinner
    });

    return Promise.resolve({
        functional: true,
        render(h, {data, children}) {
            // Transparently pass any props or children
            // to the view component.
            return h(AsyncHandler, data, children);
        }
    });
};

which you would then be able to use with Vue Router like so:

const router = new Router({
    routes: [
        {
            path: "/",
            name: "home",
            component: Home
        },
        {
            path: "/about",
            name: "about",
            component: () => lazyLoadRoute(import("./views/About.vue"))
        }
    ]
});

Hope this is helpful for anyone else who's trying to find this like I was!