Why we chose Astro over Nuxt

We've shipped dozens of Nuxt websites, so why build our own website with Astro?

When we started to build our new website we immediately reached for Nuxt 3. We knew we wanted it to be a static site, generated on the server (SSG) for speed, with the content written in markdown.

Being Nuxt + Vue specialists, Nuxt was a no-brainer. We built the whole site you see today with Vue components and MDC-flavoured markdown – an incredible format that enables you to embed Vue components right in your markdown.

We finished the site, yet throughout the build we had niggling issues with the user experience.

(You can see an old Nuxt version of the site here, password bs22)

Problem: Lag

We wanted to add pop with animation (both CSS & JavaScript) and we especially wanted to use Three.js to help us stand out from a standard website experience.

We wrote custom 3D hero section code for each page, using GLTF models exported from Blender, and brought to life with anime.js.

On our high-end dev computers, the site worked flawlessly, snappy and smooth.

While we knew Three.js would add weight to the page – even though the library is only around 150KB gzipped – it contains an absolute boatload of JavaScript.

We optimised using techniques like using cheap lights, disabling shadows and tiny textures, but we continued to suffer from lag and tab hangs on our feebler test devices.

Too much JavaScript

It boiled down to shipping just too much JavaScript for the devices to cope with.

Nuxt sends a small packet of JavaScript by default to enable cool things like preloading routes and page transitions, so despite being an SSG site there is always a baseline of code even before we add our own.

More concerning is an issue with the Vue 3 proxy reactivity system which is causing others all sorts of Three.js-related performance bother.

We’ve never experienced a performance problem with our other Nuxt sites, but with all our Three.js code, we were asking too much from both the browser and Vue.JS.

Solution: Astro

We’d been hearing a lot about Astro and their USP of zero-JS frontend architecture and we’d been keen to kick the tyres on it.

There were three compelling features that stood out to us:

  1. Bring your own tools – we could use all the Vue components we’d written
  2. MDX (rich markdown) – supported out of the box
  3. Astro islands – allows you to have chunks of live, encapsulated components

The first two features enabled us to quickly re-write our MDC markdown as MDX and re-use our Vue components almost as-is.

The islands feature was the thing we hoped would fix our perf woes.

Astro Islands

The great strength of Astro is that although our components are written in Vue single file components, Astro compiles away the JavaScript during the build leaving just html and css.

You can choose to mark components as ‘live’ by marking them as client:only and pass props down from Astro to Vue

<ThreeAnim client:only="vue" logos={logos} />

This reduced our final JavaScript by an order of magnitude from our Nuxt pages, allowing us to keep islands of heavy Three.js animations in a sea of lightweight html.

The site lagged no more.

Source: Islands Architecture: Jason Miller

So, would we use Astro over Nuxt again?

It totally depends on the project. For websites with interactive parts such as headless Shopify sites that have baskets, product configurators etc, or Single Page Apps like spike.news we’d always use Nuxt.

Our website brighton.dog is 2000+ pages of database-driven SSG Nuxt and it works perfectly, we’d be split 50-50 whether we’d build it in Nuxt or Astro were we starting it now.

For blogs and headless WordPress static marketing sites, we’d probably reach for Astro – we have been absolutely delighted by it.

Endnote: Things we missed from Nuxt

We adore Nuxt despite our foray into Astro world, and it made us appreciate a few things even more

  • Niceties like auto-imported components and Vue refs
  • No page transitions with Astro
  • MDX syntax is far more verbose than Nuxt MDC
  • Astro templating with JSX has worse devx than Vue
  • No pug support in Astro components
  • Nuxt has simpler data fetching, plus built-in server routes
  • Nuxt gives you the option to SSR or SSG allowing for more diverse applications 1

Overall, we are beyond grateful to be able to have two such formidable frameworks in our toolbox.

If you need a Nuxt website, or you’re keen to try out Astro do get in touch!

Footnotes

  1. Our bad, Astro does indeed provide SSR!