I'd like to lazy load routes / create a chunk for each route but I can't figure out how to make it work. In Webpack I can use a dynamic import with a "magic comment" to name the chunk.
Something like this would be nice but magic comments are something I don't _really_ care about, I'd just like the output of my build to be split by route and to have the dynamic imports reference the .js file.
import { RouteRecordRaw } from "vue-router"
export const routes: Array<RouteRecordRaw> = [
{
name: "About",
path: "/about",
component: () => import(/* webpackChunkName: "about" */, "../views/About.vue")
}
]
This thread seems to indicate it works now using rollup-plugin-dynamic-import-variables but using a dynamic import in the router doesn't ouput what I'd expect -- is there something else I need to configure?
Nevermind... I just didn't read through the post / docs entirely.
@onx2 even still, I think it would be nice if you could share your findings for people coming from Google etc. and looking for an answer :)
Sure! I simply changed it to the following:
import { defineAsyncComponent } from "vue"
import { RouteRecordRaw } from "vue-router"
export const routes: Array<RouteRecordRaw> = [
{
name: "About",
path: "/about",
component: defineAsyncComponent(() => import("../views/About.vue"))
}
]
It's pretty nice to be able to dynamically generate async routes too (I think Webpack might be able to do this but I haven't tried).
// pseudo code
import * as routes from "./routes"
function generateRoutes() {
return Object.keys(routes).map((route) => ({
name: route,
path: `/${kebabCase(route)}`,
component: defineAsyncComponent(() => import(`./routes/${route}.vue`))
});
}
@onx2 does that work for you in production builds? During development it works fine, but in production it can't resolve the dynamic imports.
@onx2 does that work for you in production builds? During development it works fine, but in production it can't resolve the dynamic imports.
I haven't tested in a production environment but I can test serving the prod build locally and let you know. Are you trying to generate routes or hard code them?
@onx2 Vue router needs component to return a promise. So it should be instead:
import { defineAsyncComponent } from "vue"
import { RouteRecordRaw } from "vue-router"
export const routes: Array<RouteRecordRaw> = [
{
...
component: () => new Promise((resolve)=> resolve(defineAsyncComponent({
loader: () => import("whatever"),
loadingComponent: Spinner,
})
)
)
}
]
@sirdmon @MatthiasGrandl
Thanks for the heads up! I haven't had to time to do any testing or to keep up with the evolving API's -- does the following work for production as well? _(no options defineAsyncComponent)_
https://next.router.vuejs.org/guide/advanced/lazy-loading.html#lazy-loading-routes
The component (and components) option accepts a function that returns a Promise of a component and Vue Router will only fetch it when entering the page for the first time, then use the cached version.
import { defineAsyncComponent } from "vue"
import { RouteRecordRaw } from "vue-router"
export const routes: Array<RouteRecordRaw> = [
{
name: "About",
path: "/about",
component: () => new Promise(resolve => resolve(defineAsyncComponent(() => import("../views/About.vue"))))
}
]
This seems pretty verbose for lazy loading / dynamic imports. Does defineAsyncComponent not return what we need?
const thing = () => import("./components/HelloWorld.vue"); is defined as () => Promise<any> and defineAsyncComponent's type def is:
export declare function defineAsyncComponent<T extends Component = {
new (): ComponentPublicInstance;
}>(source: AsyncComponentLoader<T> | AsyncComponentOptions<T>): T;
So I would assume defineAsyncComponent(() => import("../views/About.vue")) to be invoked and defined as () => Promise<any>;?
A potentially helpful ref: https://v3.vuejs.org/guide/migration/async-components.html#_3-x-syntax
None of the mentioned aproaches work with vite build but do work with vite
vite version:
user@debian:~/hbadmin$ yarn vite -v
yarn run v1.22.5
warning package.json: No license field
$ /home/user/hbadmin/node_modules/.bin/vite -v
vite/1.0.0-rc.13 linux-x64 node-v15.0.1
Done in 2.07s.
vue-router version: 4.0.1
vue version: 3.0.4
router/index.js
import { createWebHistory, createRouter } from "vue-router";
import {defineAsyncComponent} from "vue"
const routes = [
{
path: "/",
name: "Home",
component: () => new Promise(resolve => resolve(defineAsyncComponent(() => import("/@/views/Home.vue"))))
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
Most helpful comment
Sure! I simply changed it to the following:
It's pretty nice to be able to dynamically generate async routes too (I think Webpack might be able to do this but I haven't tried).