Lazy Load Routes in Vue with webpack Dynamic Comments
The way routing works in JavaScript is usually that you specify which relative URL pattern you want for which component to render. So for /about
you want the component to render. Let’s take a look at how to do this in Vue/Vue Router with lazy loading, and do it as cleanly as possible. I use this little tip all the time in my own work.
A repo that includes everything covered in this post is available on GitHub.
You’ve probably seen Vue routes (URLs) like this:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import Login from '../views/Login.vue'
Vue.use(VueRouter)
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: About },
{ path: '/login', name: 'Login', component: Login }
]
const router = new VueRouter({
routes
})
export default router
That will load the component at the
/
route, the component at the
/about
route, and the component at the
/login
route.
That doesn’t do a very good job of code splitting though, since all three of those components will be bundled together rather than loaded dynamically as needed.
Here’s another way to do the same, only with code splitting with dynamic import statements and webpack chunk names:
const routes = [
{
path: '/',
name: 'Home',
component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')
},
{
path: '/login',
name: 'Login',
component: () => import(/* webpackChunkName: "Login" */ '../views/Login.vue')
}
]
This is perfectly fine and doesn’t have any major downsides, other than being a bit verbose and repetitive. Since we’re awesome developers, let’s do a bit of abstraction to help, using an array
that we’ll .map
over.
const routeOptions = [
{ path: '/', name: 'Home' },
{ path: '/about', name: 'About' },
{ path: '/login', name: 'Login' }
]
const routes = routeOptions.map(route => {
return {
...route,
component: () => import(`@/views/${route.name}.vue`)
}
})
const router = new VueRouter({
routes
})
Now we’ve reduced the use of the component
key by using the route name
as param in the import
function.
But what happens if we want to set the chunk name?
As far as I know, you can’t have dynamic comments in JavaScript without some kind of build step. So, we are sacrificing comments (webpackChunkName
) in favor of having to write less code in this case. It’s entirely up to you which you prefer.
Just kidding, let’s fix it.
As of webpack 2.6.0 , the placeholders [index]
and [request]
are supported, meaning we can set the name of the generated chunk like this:
// ...
const routeOptions = [
{ path: '/', name: 'Home' },
{ path: '/about', name: 'About' },
{ path: '/login', name: 'Login' }
]
const routes = routeOptions.map(route => {
return {
...route,
component: () => import(/* webpackChunkName: "[request]" */ `../views/${route.name}.vue`)
}
})
const router = new VueRouter({
routes
})
Nice! Now we have all the power, plus dynamically loaded routes with named chunks. And it works with Vue 2 and Vue 3. You can check it out by running npm run build
in the terminal:
Buuuuut, we can still take this one step further by grouping the lazy loaded routes into named chunks rather than individual components. For example, we can create groups that group our most important components together and the rest in another “not so important” group. We merely update the webpack chunk name in place of the [request]
placeholder we used earlier:
const routes = [
{
path: "/",
name: "Home",
component: () =>
import(/* webpackChunkName: "VeryImportantThings" */ "../views/Home.vue")
},
{
path: "/about",
name: "About",
component: () =>
import(/* webpackChunkName: "VeryImportantThings" */ "../views/About.vue")
},
{
path: "/login",
name: "Login",
component: () =>
import(/* webpackChunkName: "NotSoImportant" */ "../views/Login.vue")
},
{
path: "/contact",
name: "Contact",
component: () =>
import(/* webpackChunkName: "NotSoImportant" */ "../views/Contact.vue")
}
];
Now our four components are groups into two separate chunks.
There you have it! A technique for lazy loading routes in Vue, plus some ideas for how to name and group them together at build.
The post Lazy Load Routes in Vue with webpack Dynamic Comments appeared first on CSS-Tricks.
You can support CSS-Tricks by being an MVP Supporter.