Optimizing Vue for Speed, Performance, and Core Web Vitals
!Warning: This post is over a year old. I don't always update old posts with new information, so some of this information may be out of date.
Last week I gave a talk at AlpineDay entitled "From Vue to Alpine: How & Why".
I put up my slides from my AlpineDay talk, "From Vue to Alpine: How & Why":https://t.co/xTzIl0FGun
— Matt Stauffer (@stauffermatt) June 10, 2021
And also the files I used to test performance:https://t.co/tB5EThfEEJ pic.twitter.com/Jv8P7iDBcv
In the talk I shared a few situations in which I've moved applications that were previously using Vue to use Alpine instead, for the sake of Google's Core Web Vitals. These sites were using Vue for light enhancements on top of a server-rendered app, and I found that Alpine is lighter to load and parse in these cases.
I still stand by everything I said in the talk. However, a large swath of the Internet discovered my slides, hadn't heard the talk, and assumed I was badmouthing Vue.
So, I wanted to write a post about how we can optimize our usage of Vue for this same scenario! How do we minimize Vue's impact on the Core Web Vitals?
When Vue is too heavy
In my talk, I described working on the Tighten website to improve its Core Web Vitals scores.
For that particular site, we were using Vue for some very small components, and the combination of Vue's loading time and the components' initial processing time in the browser led to a significant delay for loading the page.
I discovered I could solve our problem by replacing those components with Alpine components, and realized — and then gave a talk about this idea — that Alpine is an ideal fit, even for a Vue-loving agency like ours, for enhancements above vanilla JavaScript and below heavy dashboards and SPAs.
Gimme my Vue!
However, many of our sites — and likely yours, if you're reading this — are ideal for Vue, so we're not just going to drop it. Instead, let's look: can we optimize our page load speeds?
There's a whole group of answers that have to do with code splitting and async loading, which you can find a link to down at the bottom of this post. But there are two strategies that are very similar to what I talked about in my talk, so they're the ones I'm going to cover in this talk.
Making Vue load faster
If you define your Vue components inline in your HTML (rather than in single-file components), it turns out this requires a heavier (larger file download) and slower (more processing power spent) version of Vue. This version has an in-browser compiler, which causes the impact to load size and processing time.
I talked briefly with Evan You, the creator of Vue, who taught me that the "runtime-only" version (meaning, with no compiler) of Vue is 2/3rd the download size of the full Vue. He also gave me two ideas for how we can shrink Vue's load size and processing time.
1. Pre-compile your templates and use the "runtime" Vue build
As I mentioned above, if Vue is going to have to compile Vue component definitions from your HTML, it has to include an in-browser compiler, which makes the script file larger and the processing time take longer.
So, your first step is to use a build tool (like Laravel Mix), pre-compile your templates, and then use the "runtime-only" build of Vue.
How to pre-compile your templates
"Pre-compiling" in this scenario means using single-file .vue
components that you then process with your build tooling. These files are compiled into JavaScript, so the end user isn't delivered HTML that needs to be parsed, but a JavaScript file ready to be executed.
"Not pre-compiling" simply means placing your Vue template inline in your HTML; this may be convenient (and some times it's even necessary), but if you work this way you can't drop to the smaller Vue file.
Using the runtime-only build in Laravel Mix
In Laravel Mix, you can switch to the runtime-only build by passing {runtimeOnly: true}
to your mix.vue()
call:
mix.vue({runtimeOnly: true})
Using the runtime-only build from a CDN load
If you're using a CDN to load Vue (which I assume is unlikely if you're pre-compiling your templates, but what do I know?), your link likely looks something like this:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
However, you can get a minified version easily (which you should do no matter what):
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
And if you are pre-compiling your templates, you can ask for the runtime-only version by appending runtime
after vue
in the file name:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.runtime.min.js"></script>
Using the runtime-only build elsewhere
If you use other build tooling, you'll want to modify your build script from pulling the vue.whatever.js
file to the vue.runtime.whatever.js
file. You can take a look at Laravel Mix's source here to see how they do it.
2. For light enhancements, don't mount to the larger app
Evan also shared another tip for speeding up Vue, especially when it comes to the processing time it takes on each page load.
If you're working with a server-rendered app and just adding a light touch of Vue here and there, don't mount to the body or a master #div
. If you do, Vue has to parse your entire application's body content and replace it with a new DOM on every page load.
Rather, bind Vue individually to just the spots where it's needed. Move from this:
new Vue({
el: "#app",
});
to this:
new Vue({
el: "#hamburger",
});
new Vue({
el: "#sliders",
});
And more...
There are a ton of additional considerations you can look at to improve your Vue applications' performance. These are just two that have very specifically to do with initial load time and processing.
Here are a few other worth digging into. There's a fantastic series on VueSchool called Vue.js Performance, which I would recommend and have linked in several of these items.
- Conditional and lazy loading components (1, 2)
- Analyze your Webpack bundle size to look for bundle size offenders
- Look into SSR (server side rendering) to speed up the initial page load
- If you're using Laravel Mix, look into code splitting
- Consider using a system like Nuxt to get free code splitting and SSR
- Tree shaking
- All sorts of other things, I'm sure, which I don't even know about. Know more? Hit me up on Twitter
Comments? I'm @stauffermatt on Twitter
Tags: vuejs