You don't need zero JS website for a perfect Lighthouse score
Lately, there has been a rise in popularity of frameworks like Astro, which introduce the "Islands architecture." As a result, many tech "influencers" are now flexing with their Lighthouse scores and screaming, "You don't need JS! Look at my perfect 100% score!"
People love to lecture others by making claims like "You don't need JS for a simple blog!" and while that can be true, what if someone needs it? What if someone needs state management for handling the theme of the page? What if someone likes the feeling of client-side navigation? JS was invented to solve specific problems and it's nothing wrong about it. My blog is a statically generated Nuxt project with client-side navigation (nuxt-router), and state management (pinia) and I'm not gonna change it. Why? Because I love the feeling of client-side navigation. I like the new View Transitions API. And guess what? I can achieve the same (or even better) performance results than similar pages made by frameworks like Astro which initially ships zero JS.
Here I want to give some most important tips about improving the performance of Nuxt projects. Of course, super interactive, SSR projects are far more difficult to optimize but I still think that these rules apply to projects of any size.
On this blog, I'm using Nuxt with Nuxt content which is amazing for generating pages from markdown files. Because I'm not using any dynamic data coming from an API, I can statically generate all pages during the build step. Because of that, we don't have to wait for the server to process the data (SSR) or for client site hydration (SPA). Nuxt also provides some cool built-in performance optimizations like prefetching when some resource is becoming visible on screen. By that, navigation between pages is ultra-fast and the feeling is incomparable to classic MPA.
Lighthouse adores well-optimized images so this is by far the most important thing. You have to be sure that you are using modern formats like webp or avif and serving images with proper sizes. Also, it's important to reserve the space for images to prevent layout shifts. For my project, I have used Nuxt Image and while it's still in beta it makes it easy to control the format and sizes of images.
Fonts are one of the biggest pain points in the context of performance optimization. I have decided to not use any CDN like Google Fonts but instead, I'm serving them myself. Also, I have used a cool package called Fontaine which reduces CLS by using local font fallbacks with crafted font metrics.
One of the biggest benefits of Vue are scoped styles working out of the box. It's important to write components related styles within SFC scoped styles block to avoid downloading unnecessary styles when they are not needed at specific routes. Writing optimal and clean CSS will obviously be beneficial to our overall score. Using some new CSS properties like content-visibility won't make a huge difference but we are aiming for perfection, right?
This may sound a bit general but we can't forget about well-tought code. If we are using a lot of external dependencies, we can check if there aren't many lighter alternatives. Example? Some people are still using moment.js for date formatting. Why not use a lightweight 2kb alternative instead? Writing clean, organized and maintainable code won't give us a huge score boost but we are trying to save every byte of data, right? 😉
I'm hosting my blog using Cloudflare Pages and the experience is amazing. By doing that I can take advantage of the ultra-fast global network provided by Cloudflare which helps serve static assets and caching.
Even if you have a simple blog but want to take advantage of client site navigation, interactive components, and state management you don't have to give it up because zero JS websites are trending right now. Just do your thing. Trust me, with some effort, you can optimize your project to near-perfect scores. And with final words, I want to praise the Vue and Nuxt ecosystem once again. It's unbelievable how phenomenal the developer experience is. The frameworks themselves, CLIs, tooling, extensions, and devtools. Everything is top-notch. I have managed to rewrite this blog from Gatsby to Nuxt within two days. Thank you Vue/Nuxt team! 💚