---
title: Faster Nuxt sites on Netlify
description: >-
  From Nuxt and Netlify we get a lot performance out-of-the-box. But we can make
  things even faster by tuning Nuxt and Netlify to work together!
language: English
url: 'https://voorhoe.de/en/blog/faster-nuxt-sites-on-netlify/'
---

Blog

# Faster Nuxt sites on Netlify

By [Frank](/en/team/frank.md)

8 May 2020

* [Cache assets forever](#cache-assets-forever)
* [Split assets from app bundle](#split-assets-from-app-bundle)
* [Remove unused features](#remove-unused-features)
* [Serve modern bundles](#serve-modern-bundles)
* [More performance optimisations](#more-performance-optimisations)

Tuning Nuxt and Netlify to work together

Nuxt and Netlify both aim to make user experiences as fast and smooth as possible. From Nuxt’s homepage:

> "With Nuxt.js, your application will be optimized out of the box. \[…] To squeeze every unnecessary bit out of your app Nuxt includes a bundle analyzer and lots of opportunities to fine-tune your app."

\- Why Nuxt?

Netlify, as a platform, has a world-wide Content Delivery Network (CDN) and a [smart resource caching strategy](https://www.netlify.com/blog/2017/02/23/better-living-through-caching/) setting *max-age=0, must-revalidate, public*, effectively telling the browser to cache all resources but to check-in with the server to verify it’s still fresh.

So with Nuxt and Netlify we get a lot performance out-of-the-box. But we can make things even faster by tuning Nuxt and Netlify to work together. This is how:

* Cache assets forever
* Split assets from app bundle
* Remove unused Nuxt features
* Serve modern bundles

Nuxt is powered by Vue.js. Do you want to become a Vue master? During our two day hands-on workshop we’ll teach you everything you need to know to build large performant web apps with Vue.

[Join our Vue masterclass](https://www.voorhoede.nl/vuemaster)

## Cache assets forever

Nuxt does a great job by hashing all of its JavaScript bundles, making sure each bundle has a unique filename. When the bundle content changes, the filename changes as well. This enables us to cache them forever! Nuxt serves bundles from the */\_nuxt/* folder. Let’s configure Netlify to cache files in this folder forever:

```
# static/_headers

# docs: https://www.netlify.com/docs/headers-and-basic-auth/#multi-key-header-rules
/_nuxt/*
  Cache-Control: max-age=365000000
  Cache-Control: immutable
```

This strategy can be applied for other assets as well. Basically, all fonts and images can be cached. Nuxts *assets* folder comes into the picture here. Let’s try to move as many assets as possible from the *static* folder to the *assets* folder. Assets in this folder are hashed and end up in the */\_nuxt/* folder after a build, just like our bundles. Now all these assets will be cached forever too!

## Split assets from app bundle

Now that we’re talking about assets, there is one kind of asset that impacts your performance more than you would think: SVG icons. There’s a good chance you’ve set up *vue-svg-loader* to load your icons. And there’s good reason to: having SVGs inlined in the html output enables us to do cool things like overwriting styling properties from our CSS and animating them.

However, this loading strategy comes with a price: our icons are included in our *app.js* bundle. Therefore our icons impact the critical path for our site to load and become interactive.

Fortunately, we can solve this by using [Nuxt SVG sprite](https://github.com/nuxt-community/svg-sprite-module): a module that sprites all your SVG assets together and serves them as one SVG file. This single SVG file gets hashed and ends up in the */\_nuxt/*  folder, so Netlify will leverage caching on our icons as well!

The Nuxt SVG sprite module provides great developer experience, by injecting a global component to use your icons in your templates:

```
<svg-icon name="sample" />
```

This will output the following HTML:

```
<svg xmlns="http://www.w3.org/2000/svg">
    <use href="/_nuxt/722f7bfaeddba2b3577b8f83c9ce5ed0.svg#i-sample" xlink:href="/_nuxt/722f7bfaeddba2b3577b8f83c9ce5ed0.svg#i-sample"></use>
</svg>
```

The effect of the `<use>` tag is [like the original SVG nodes are cloned](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use), enabling us to still treat it like an inline SVG for styling purposes, without affecting our critical path.

If you need IE11 support, be aware [IE11 doesn’t support the `<use>` tag with external URI’s](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use#Browser_compatibility). This can be solved by using svg4everybody: a package to fall back to loading sprites over XHR and injecting them into the HTML.

## Remove unused features

By default your Nuxt websites ships an *app.js* bundle containing all core features. But what if we don’t use some of these features? It’s a waste to let users download and parse these excessive kilobytes of JavaScript.

![Nuxt app.js size (48kb default vs 42kb with fetch and validate disabled)](https://www.datocms-assets.com/6524/1587475328-xwunpzpw.jpeg)

Nuxt app.js size (48kb default vs 42kb with fetch and validate disabled)

Since [Nuxt 2.10.0](https://nuxtjs.org/guide/release-notes#v2.10.0) an undocumented, powerful and yet dangerous feature has been released. It’s now possible to disable unused features in Nuxt. To research how much we can shave off our *app.js*, I created an empty Nuxt project and disabled *fetch* and *validate*. By doing so, our *app.js* bundle size reduced from 48kb to 42kb (13%).

![Nuxt app.js size (48kb default vs 28kb with all core features disabled)](https://www.datocms-assets.com/6524/1587475484-bnlrsbxg.jpeg)

Nuxt app.js size (48kb default vs 28kb with all core features disabled)

By disabling all Nuxt features, we were able to bring it down to 28kb(42%). Of course there’s no point in disabling all Nuxt features, but it’s nice to see we’re able to shave off that much.

Nuxt’s core contributor [mentioned feature detection might be used in Nuxt 3](https://github.com/nuxt/nuxt.js/pull/6287#issuecomment-525258448) to automagically enable features once you’re using them. So this optimisation might be automated in the future. Awesome!

## Serve modern bundles

You can run nuxt generate **--****modern**[to tell Nuxt to output two versions of each JavaScript bundle](https://nuxtjs.org/api/configuration-modern): a legacy one and a modern one. The generated HTML will now contain two script tags per bundle:

```
<script nomodule="" src="/_nuxt/a230eea68ca24259c016.js" defer=""></script>
<script type="module" src="/_nuxt/0ce5ca1f220b7ebc1f9a.js" defer=""></script>
```

[Legacy browser’s don't support JavaScript modules](https://caniuse.com/#feat=es6-module). Therefore they won’t load the modern bundles. Modern browsers supporting esmodules,[ won’t load the legacy scripts](https://v8.dev/features/modules#browser) since Nuxt attaches a nomodule attribute. This enables us to serve code optimised for the users browser!

![Total bundle sizes (114kb without modern flag vs 104kb with modern flag)](https://www.datocms-assets.com/6524/1587475797-artboard.jpg)

Total bundle sizes (114kb without modern flag vs 104kb with modern flag)

For voorhoede.nl, we’ve been able to reduce our total JavaScript footprint from 114 kilobytes to 104 kilobytes (9% reduction).

Please notice Nuxt now builds a doubled number of JavaScript bundles, increasing your build minutes usage on Netlify. If this is problematic, check out our blog post 10x faster Nuxt builds on Netlify.

## More performance optimisations

Want to make your Nuxt apps even faster? Here’s a few more suggestions of what you could do:

* Make sure to use the woff2 format and font-display: swap for your fonts
* Add brotli: [planned for Netlify](https://www.youtube.com/watch?v=IWPDI01DsAo\&feature=youtu.be\&t=1638)(no timeline), use Cloudflare for now
* Add [extra caching with a Service Worker](https://www.voorhoede.nl/en/blog/instant-static-web-pages-with-service-worker/)[(PWA)](https://www.voorhoede.nl/en/blog/instant-static-web-pages-with-service-worker/)
* Lazy load heavy parts using dynamic imports. Markus Oberlehner wrote an [excellent blog post](https://markus.oberlehner.net/blog/how-to-drastically-reduce-estimated-input-latency-and-time-to-interactive-of-ssr-vue-applications/) about this.
* Note: using server push(for font files, etc) is no longer encouraged due to [Netlify disabling server push after experiencing issues](https://community.netlify.com/t/conditional-headers-based-on-user-agent/415/7). It’s uncertain when and if Netlify will re-enable server push.

Have fun making the web faster!

[← All blog posts](/en/blog.md)

## Also in love with the web?

For us, that’s about technology and user experience. Fast, available for all, enjoyable to use. And fun to build. This is how our team bands together, adhering to the same values, to make sure we achieve a solid result for clients both large and small. Does that fit you?

[Join our team](/en/jobs.md)

[Return to top](#top)
