You don't need zero JS website for a perfect Lighthouse score

Created by human

Zero JS trend

The world of Javascript is constantly evolving, with paradigm shifts occurring from time to time. We've seen this with the rise and fall in popularity of MPA, SPA, SSR, and SSG architectures. Single Page Applications (SPA) became very popular and almost every web app created within a certain timeframe was designed as an SPA. Now we are reinventing the wheel by moving things back to the server. In my opinion, every approach has its place and no single approach is the best. Some websites can be completely static, while others require server-side rendering, and some are best suited as SPAs. Each rendering mode has its own use cases, and I don't like bold statements like "SPAs were a mistake".

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!"

This has led to a point where we now feel guilty for using JavaScript. However, we shouldn't.

Don't be afraid of JS

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.

[Performance]

With the right mindset and some performance-oriented optimizations, you don't have to be afraid of shipping Javascript even for a simple blog.

Performance tips

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.

1. Static generation

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.

2. Image optimization

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.

3. Fonts optimization

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.

4. Scoped and optimal styles

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?

5. Optimal Javascript

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? 😉

6. Cloudflare Pages

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.

Summary

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! 💚

© Copyright 2024 Michał Kuncio