Generally, we as devs know that nobody has time to wait for our app to load. People are more likely to just leave as page load time goes up.
We don’t want to build slow apps, but there are many reasons why it happens anyway. Maybe there was no time or budget for „invisible“ things like performance. Maybe other technical challenges needed a lot of attention, and you had pressure to ship. Or your app just grew a lot over time!
Facing performance issues often makes developers feel guilty that they didn’t „build it better“, and worried that they don’t know enough to solve the issues. If you feel this way, let me tell you that there are a lot of quick wins and methods available to start optimizing.
In this article, we’re taking a look at the basics of performance optimization for Vue apps and guide you towards resources and tools that help you go deeper.
Performance has a big impact on user experience. People are using your app to get things done. A snappy app that delivers results and information fast will help users accomplish their goals while feeling efficient. It also boosts trust in your brand and app.
While I hope you like making people happy, contented users are also important for your business:
Happy users that don’t have to wait for your app or website to load are *less likely to bounce (= leave), and more likely to convert (= sign up and pay).
Additionally, performance impacts your ranking on search in two ways:
Not everyone is using your app / website on a brand-new MacBook Pro and on a flat-rate, high-speed network. Being mindful about size and CPU impact makes it possible and less costly for more people to access your app.
When we’re talking about performance, we’re usually talking about metrics measuring two important aspects:
So, what are we doing (or not doing) to make our app heavier to load and less responsive? There are many things that can impact performance, and it’s not just about the code you write as a frontend developer.
You’ll have to see the broader picture including the user and their hardware & network, your backend, server and also the design of your app (visual design and architecture-wise).
Read on for a summary of the most important factors and some tips on how to optimize!
How much bandwidth is needed to load your app? The larger, the slower.
<div class="brick__image-inner "
id="js-image-2350"
v-lazy-bg="'https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/26363/vite-2.jpg'"
style=" ">
</div>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/vite" class="brick__title">
Vite Plugin Vue
</a>
<span class="brick__tagline">
Frontend Build Tool
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/dev-tools">#Dev Tools</a>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
How much bandwidth is needed specifically to load images, videos and fonts? Are you smart about delivering only what is needed?
<div class="brick__image-inner "
id="js-image-3750"
v-lazy-bg="'https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/29018/vue-lazyload.jpg'"
style=" ">
</div>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/vue-lazyload" class="brick__title">
Vue Lazyload
</a>
<span class="brick__tagline">
Lazyload Images & Components
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/ui-components">#UI Components</a>
<a href="/image">#Image</a>
<a href="/utilities">#Utilities</a>
<span class="dots">...</span>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
<div class="brick__image-inner "
id="js-image-3065"
v-lazy-bg="'https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/31493/nuxt-image-3.jpg'"
style=" ">
</div>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/nuxt-image" class="brick__title">
Nuxt Image
</a>
<span class="brick__tagline">
Optimized Images for Nuxt
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/image">#Image</a>
<a href="/utilities">#Utilities</a>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
<div class="brick__image-inner "
id="js-image-3246"
v-lazy-bg="'https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/28212/nuxt-speedkit.jpg'"
style=" ">
</div>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/nuxt-speedkit" class="brick__title">
Nuxt Speedkit
</a>
<span class="brick__tagline">
Performance Optimization Module
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/ssr">#SSR</a>
<a href="/utilities">#Utilities</a>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
The network conditions of your users are halfway out of your control - but you can still account for them.
How efficiently does your (Vue) code do what you want it to do?
If you need to load content from a CMS or a third party API to display in your app, your frontend performance is inevitably bound to the amount and performance of those API calls. Also, requests for analytics apps, ad networks and similar services can be costly.
How costly is your app in terms of memory and CPU usage? Depending on the device your users are on, this may impact performance a lot for them.
<div class="brick__image-inner "
id="js-image-13"
v-lazy-bg="'https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/28356/nuxt-3.jpg'"
style="-webkit-background-size:contain;background-size:contain; background-position:center center;">
</div>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/nuxt-js" class="brick__title">
Nuxt.js
</a>
<span class="brick__tagline">
Intuitive Vue Application Framework
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/frameworks">#Frameworks</a>
<a href="/ssr">#SSR</a>
<a href="/static-site-generator">#Static site generator</a>
<span class="dots">...</span>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
<video
muted
autoplay
playsinline
loop
class="brick__video">
<source src="https://madewithcode-dozlxc08.on-forge.com/storage/31702/vue-virtual-scroller-k.mp4" type="video/mp4">
</video>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/vue-virtual-scroller" class="brick__title">
Vue Virtual Scroller
</a>
<span class="brick__tagline">
Blazing fast scrolling for any amount of data
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/utilities">#Utilities</a>
<a href="/loading">#Loading</a>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
How snappy does the app feel to the user? Your user’s perception of how long it takes your app to load is actually even more important than the objective load time. It can be impacted by how loading resources is prioritized, handled and communicated.
<video
muted
autoplay
playsinline
loop
class="brick__video">
<source src="https://madewithcode-dozlxc08.on-forge.com/storage/31280/vue-content-loader-k.mp4" type="video/mp4">
</video>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/vue-content-loader" class="brick__title">
Vue Content Loader
</a>
<span class="brick__tagline">
SVG Loading Placeholder
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/ui-components">#UI Components</a>
<a href="/animation">#Animation</a>
<a href="/loading">#Loading</a>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
<video
muted
autoplay
playsinline
loop
class="brick__video">
<source src="https://madewithcode-dozlxc08.on-forge.com/storage/31164/epic-spinners-k.mp4" type="video/mp4">
</video>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/epic-spinners" class="brick__title">
Epic spinners
</a>
<span class="brick__tagline">
Loading Spinner Collection
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/ui-components">#UI Components</a>
<a href="/animation">#Animation</a>
<a href="/loading">#Loading</a>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
To check your app’s current performance (and get some insights about possible improvements) you can use the following tools:
<video
muted
autoplay
playsinline
loop
class="brick__video">
<source src="https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/2405/vue-devtools-v3.mp4" type="video/mp4">
</video>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/vue-devtools-v3" class="brick__title">
Vue Devtools
</a>
<span class="brick__tagline">
Debugging Tools for Vue Apps
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/dev-tools">#Dev Tools</a>
<a href="/testing">#Testing</a>
<a href="/browser-extension">#Browser extension</a>
<span class="dots">...</span>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
For more insights on bundle size:
If you want to make performance a priority, it makes sense to set yourself budgets for the most important metrics like pagespeed and bundle size, and measure your app against them regularly.
Bundle size budgeting
To keep your bundle size in check, you can use CLI tools like siddharthkp/bundlesize to set up automated checks for your build pipeline. Tools like Packtracker (#madewithvuejs!) offer an additional dashboard visualizing bundle size over time.
<video
muted
autoplay
playsinline
loop
class="brick__video">
<source src="https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/3258/packtracker-k.mp4" type="video/mp4">
</video>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/packtracker" class="brick__title">
Packtracker
</a>
<span class="brick__tagline">
Webpack Bundle Monitoring
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/webapps">#Webapps</a>
<a href="/dev-tools">#Dev Tools</a>
<a href="/analytics">#Analytics</a>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
Lighthouse audits & performance budgets
The Lighthouse CI CLI tool and GitHub action lets you analyze your app continuously in your workflows and set up performance budgets for the metrics you care about.
If you want to take it a step further, performance monitoring helps you keep track of your app’s performance over time and notifies you about issues as soon as they crop up.
Monitoring services provide insights about where and how to solve issues. They track your app as a whole, and help you identify the source of issues – is your frontend, backend, or API xyz at fault? Sentry is our weapon of choice. We use their Vue and Laravel SDKs, but they support almost every other stack as well!
<div class="brick__image-inner "
id="js-image-50"
v-lazy-bg="'https://madewithnetworkfra.fra1.digitaloceanspaces.com/spatie-space-production/29802/sentry-vue-7.jpg'"
style=" ">
</div>
</div>
<div class="brick__caption">
<div class="brick__caption-upper">
<a href="https://madewithvuejs.com/sentry-for-vue" class="brick__title">
Sentry for Vue
</a>
<span class="brick__tagline">
Vue Error & Performance Monitoring
</span>
</div>
<div class="brick__caption-lower">
<div class="pull-left">
<a href="/dev-tools">#Dev Tools</a>
<a href="/integration">#Integration</a>
<a href="/testing">#Testing</a>
<span class="dots">...</span>
</div>
<div class="pull-right">
<div class="brick__views">
<svg class="svg-inline u__va--middle" width="20px" height="13px" viewBox="0 0 20 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>icon-eye-dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-313.000000, -230.000000)" fill-rule="nonzero" fill="#435B71">
<g id="icon-eye-dark" transform="translate(313.000000, 230.000000)">
<path d="M9.57827924,0.0932647368 C5.40166592,0.0977121053 2.23909537,3.28527789 0.162366374,6.09013053 C-0.0164829778,6.33193046 -0.0164829778,6.66216481 0.162366374,6.90396474 C2.23923803,9.71401737 5.40085034,12.9011726 9.57827924,12.9068174 C9.57872397,12.9068178 9.57916871,12.9068178 9.57961345,12.9068174 C13.7562192,12.90237 16.9187977,9.71477 18.9955264,6.90995158 C19.1743758,6.66815165 19.1743758,6.3379173 18.9955264,6.09611737 C16.9186536,3.28603053 13.7570499,0.0989094737 9.57961345,0.0932647368 C9.57916871,0.0932643033 9.57872397,0.0932643033 9.57827924,0.0932647368 L9.57827924,0.0932647368 Z M9.57827924,1.46168579 L9.57961345,1.46168579 C12.8675916,1.46681737 15.5988249,3.96846211 17.5569468,6.50236737 C15.5985806,9.03230421 12.8660264,11.5341884 9.57961345,11.5383963 C6.29104758,11.5339489 3.55933568,9.03192789 1.60094367,6.49771474 C3.55930832,3.96777789 6.29185563,1.46589368 9.57827718,1.46168579 L9.57827924,1.46168579 Z" id="Shape"></path>
<path d="M9.57894737,3.42075158 C7.88659608,3.42075158 6.5,4.80737263 6.5,6.49969895 C6.5,8.19205947 7.88659608,9.57864632 9.57894737,9.57864632 C11.2712987,9.57864632 12.6578947,8.19205947 12.6578947,6.49969895 C12.6578947,4.80737263 11.2712987,3.42075158 9.57894737,3.42075158 Z M9.57894737,4.78917263 C10.5317492,4.78917263 11.2894737,5.54690158 11.2894737,6.49969895 C11.2894737,7.45249632 10.5317492,8.21022526 9.57894737,8.21022526 C8.62614555,8.21022526 7.86842105,7.45249632 7.86842105,6.49969895 C7.86842105,5.54690158 8.62614555,4.78917263 9.57894737,4.78917263 Z" id="Shape"></path>
</g>
</g>
</g>
0
</div>
To get started, we can recommend the free 🎓️ Vueschool course on how to implement application monitoring with Sentry, including a chapter about performance monitoring.
Find more infos about advanced Vue.js performance monitoring in our follow-up article!