Editor’s note: This Vue lazy loading tutorial was last updated on 29 April 2021.
In this Vue lazy loading tutorial, we’ll demonstrate how to lazily load the components in your Vue.js application. The aim of this demonstration is to help you understand how Vue.js handles lazy loading at the route level of abstraction with the help of webpack code splitting.
Here’s what we’ll cover:
Vue.js is a very progressive JavaScript framework created by Evan You and the Vue core team with contributions from over 230 open source community membes. At the time of writing, Vue.js has more than 183,000 stars on GitHub. It consists of an approachable core library that focuses on the view layer only and an ecosystem of supporting libraries designed to help you tackle complexity in large single-page applications.
Lazy loading is a pattern designed to delay the initialization of elements and objects until they are needed. Lazy loading means that a target DOM element, relative to a parent DOM element, is loaded and becomes visible (when there is an intersection between both elements, based on a set threshold value) only when a user scrolls through them on a webpage.
To understand lazy loading, you must first understand eager loading. Eager loading is the default approach to loading JavaScript code on to the DOM. For Vue.js, this means using the import statement to bring in a component into the app.vue
file. Lazy loading refers to an approach by which all the scripts are not loaded on the DOM as the application starts. Instead, they’re only loaded when requested, which makes the JavaScript bundle size very small at initial load.
Vue.js handles loading components lazily with routes, so on the DOM you can load components only when they are needed through routes. This is done by splitting each route’s components into chunks that are separate from the main chunk loaded on initialization. This keeps the bundle size sent down to the DOM from becoming too large. Vue.js combines the async component feature and webpack’s code splitting feature to lazy-load route components.
As your Vue.js project grows in size and complexity, the eager loading approach makes the JS bundle very cumbersome. This can become a problem for your end users who might be accessing your application on a mobile device or without fast-speed internet connections.
Lazy loading guarantees that your JavaScript bundle is fed to the DOM in an order of importance from the most-needed component to the least-needed ones. This approach ensures that you have control over the whole experience of the user, which includes the initial wait period when resources are loaded onto the DOM.
To demonstrate lazy loading in Vue.js, we’ll build an example Vue.js app with the Vue CLI and add routing during the configuration stage.
We’ll also add a third route manually to show the process for developers that are not familiar with the Vue CLI. That said, it’s always advisable to use the Vue CLI because secondary routes are already configured to be lazily loaded by default.
Open up a terminal in a directory of your choice and create a new project with this command:
vue create test_project
You’ll see a follow-up questionnaire like this:
? Please pick a preset: Manually select features ? Check the features needed for your project: ◉ Babel ◯ TypeScript ◯ Progressive Web App (PWA) Support ❯◉ Router ◯ Vuex ◯ CSS Pre-processors ◉ Linter / Formatter ◯ Unit Testing ◯ E2E Testing
Make sure to select the router option with the spacebar just as it is selected above. Then, to save space, you can choose to store all of the configs in the package.json
file. You’ll see a success message once the project is created. At this point, change the directory to the new project folder and run the application in the development environment:
cd test_project npm run serve
It has an about
component with the route navigation on the view. The two components, Home.vue
and About.vue
, are loaded on the DOM as soon as the application initializes. This is standard procedure and very good for small projects with minimal assets, but in large applications with a lot of components, this can be very slow to load. This is where code splitting comes in.
Open the router.js
file. It should look exactly like this:
import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' import About from './views/About.vue' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: About } ] })
This might look different for the about
component section because the Vue CLI includes lazy loading for secondary routes, such as the about
component in our example.
You have two routes now: a home
route that points to the home view and an about
route that points to the about view. Let’s add a third view and then register a route for it.
In your views
folder, create a new file and call it extra.vue
. Then, copy the contents of the about.vue
file into the extra.vue
file. It should look like this:
<template> <div class=”about”> <h1>This is an extra page</h1> </div> </template>
To register the route, open your router.js
file and add the extra code block under the routes array:
export default new Router({ routes: [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: About }, { path: '/extra', name: 'extra', component: Extra } ] })
The final step to get it to show in the DOM is to add it to the main App.vue
file with a router-link
.
Open your app.vue
file and change the template section to this code block below:
<template> <div id=”app”> <div id=”nav”> <router-link to=”/”>Home</router-link> | <router-link to=”/about”>About</router-link> | <router-link to=”/extra”>Extra</router-link> </div> <router-view/> </div> </template>
Now that all the routes are set up in our example Vue.js app, it’s time to configure all your routes to be lazily loaded on request.
Open your router.js
file and copy/paste the code block below into it:
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) function lazyLoad(view){ return() => import(`@/views/${view}.vue`) } export default new Router({ mode: 'history', base: process.env.BASE_URL, routes: [ { path: '/', name: 'home', component: lazyLoad('Home') }, { path: '/about', name: 'about', component: lazyLoad('About') }, { path: '/extra', name: 'extra', component: lazyLoad('extra') } ] })
Here’s a breakdown of what was done to make these views load lazily:
Initially, you may have noticed there were import statements for Vue.js, Router, Home, About, and extra. These statements are the main thing driving the eager loading of components, so when you change to the lazy loading approach, you have to remove those import statements.
lazyLoad
functionThe Vue lazyLoad
function was created to make the import statement clean. Without this function, every component would have a long import statement. With it, you can simply call the function and pass in the route as args.
The import statement that tells webpack to lazily load components must be embedded into the routes section instead of the import section at the start of the script.
To test the loading strategy, run the application again in development:
npm run serve
Open it up at http://localhost:8080/ in your browser and open developer tools. Click on the network section and choose the JS tab.
As you can see, the JavaScript chunks loaded on the DOM are split chronologically into numbers, where the first one (0.js
) is the home view, the second (1.js
) is the about view, which only gets added to the DOM on click, and the third (2.js
) is the extra view, which also gets added to the DOM on request.
At this stage, you can also verify that the lazy loading worked by building out the application for production with the command:
npm run build
These three chunks will be duly represented as separate independent and lazily loaded chunks by webpack.
This introductory tutorial is designed to show you how Vue.js handles lazy loading at the route level of abstraction with the help of webpack code splitting. The importance of lazy loading components might not be as apparent in small Vue.js projects, but as your project grows complex, it becomes advisable to implement lazy loading in your workflow for efficiency and optimal use of resources.
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.