Less noise, more data. Get the biggest data report on software developer careers in South Africa.

Dev Report mobile

5 tools that ship less JavaScript and elevate user experience

15 August 2023 , by Kelvin Omereshone

Building on the web is becoming more and more ambitious. We’ve moved past the days when we had just static pages and now have full interactive applications hosted on the web. What this means is that we’re shipping more JavaScript than ever - an issue that can negatively affect the user’s experience. Here are the tools I use to ship less JavaScript and improve user experience while maintaining developer experience.


As a JavaScript developer with six years of experience, I realised that the more interactive and app-like my web pages are, the more JavaScript they will need. This makes sense because JavaScript is what powers that rich interactive user experience. However, shipping more JavaScript comes at a cost: the user’s browser will have to download and execute all the JavaScript you’ve shipped.

You may think this is trivial, but the speed at which it takes for users to download and execute JavaScript depends on their devices and internet connectivity. When you consider the fact that more and more people use the web on their mobile devices and that part of the world doesn't enjoy fast internet connectivity or use low-end devices, then you’d realise that shipping less JavaScript makes a lot of difference to their experience when they visit your website or web application.

How do we deal with this? How do we still build on the web with JavaScript but ship little or less JavaScript to our users to make sure their experiences don’t suffer in terms of the performance of those apps? Well, there are a couple of strategies and technologies that exist today to help us ship JavaScript wisely, while maintaining great developer experience when building these web applications.

Here are the tools and strategies I use to help me ship less JavaScript.

#1 Inertia.js and the modern monolith

Back in 2021, I built Sailscast, a platform to learn full-stack JavaScript for web development. At the time, I went with what was popular, which was building a Single Page Application (SPA) and an API. The technology stack I used for the SPA was Vue.js with Nuxt.js, and for the API, I utilised Sails.js.

After building with this stack, I couldn't help but see that some of the promises of SPAs did not add up:

  • While users are able to see a page quickly since all the routing is done on the client side, they are usually only seeing a skeleton and loading spinner at first. What's the use of this if it just ships more JavaScript to show and animate these elements?
  • Building Sailscast with SPAs meant that I had to maintain two codebases - one for the front end and one for the back end. This implies double routing, as you will need to provide the API endpoint to get the content certain pages need. And, of course, those pages are set up with client-side routing, which means more JavaScript.
  • Building SPAs the traditional way requires a state management library, which is not only hard but translates into using more JavaScript.

I started thinking if there was a better way. I like building SPAs, especially with Vue.js, but I also like traditional MVC server-side frameworks like Sails, Rails, and Laravel. The idea I had was a way to have both - a server-side-centric workflow that still uses a modern UI framework like Vue.js for my pages.

While I was thinking about this idea, I stumbled upon a project from the Laravel ecosystem by Jonathan Reinink called Inertia.js. Inertia.js was said to be the modern way to build SPAs without needing an API. I knew then this was what I was looking for, and here is why: Like me, Jonathan wanted a way of building SPAs without some of the above problems plaguing them. He wanted a single codebase, and the SPA should be server-driven with a robust MVC framework.

Long story short, I went ahead and built a server-side Inertia adapter for Sails and rewrote Sailscasts to use Inertia.js. And with that, I named this stack The Boring JavaScript Stack.

By shipping less JavaScript with Inertia.js and utilising its other features, I was able to see a list of benefits for both user experience and developer experience:

Load pages with the content and say goodbye to endless loading spinners

The way Inertia.js works is that it functions as a lightweight routing library. When a user makes a request to an inertia-powered web app by clicking on a link to visit a page, Inertia.js intercepts that request and makes an AJAX request to your server-side framework (in my case, Sails).

Your server-side code will then respond with the component name for the new page alongside the data the page needs as props.

This means that when a user visits a SPA powered by Inertia.js, all the critical content is loaded immediately on the page without the need for a loading spinner or basic skeleton. Meaning that you don’t need to ship JavaScript to animate the spinner - an element that usually only appears on a screen for maybe 2 seconds and has no benefit for the user.

No more flash of unauthenticated content

Have you ever noticed when you visit a SPA that has authenticated pages, you will see a flash of unauthenticated content? For example, a login button flashes before a dashboard button takes its place on the navbar?

This usually happens when the client-side JavaScript takes a while to make the conditional check, which results in that flash of unauthenticated content. This is not a great experience for users because the shift in UI is often noticeable and degrades their experience of the site.

This is no longer a problem with Inertia.js because before the page is rendered, the data it needs is sent down the wire as props, so the page already knows it’s an authenticated page; hence no flashes.

Little or no state management on the client

Let’s face it, state management on the client is hard. With this modern monolith powered by Inertia.js, the states needed by a page are returned with the page as props, meaning that you may not need a client-side state management library.

Sailscasts doesn’t currently use any client-side state management library. At first, I felt like I was doing something wrong. But when I saw popular web development frameworks like Remix confirming that you don’t need a state management library, I felt reassured.

A single codebase

This is more developer experience than it is user experience, but having a single codebase (a modern monolith) made me move quickly. Maintenance of the codebase improved, and also context switching dropped immensely.

Single routing

I no longer need to route both in the client and on the server as all routing is done server-side. This is a no-brainer for me, as I prefer that the server handles the route definitions.

If you are interested in learning more about this case study, you can watch my Sailsconf 2022 talk.

You can also check out Sailscasts, Laracasts, and Fathom Analytics as great examples of web apps using Inertia.js.

#2 Astro, static sites and island architectures

With the rise of SPA and “Reactizations” (using React for everything), we’ve sort of abandoned good old static sites.

While SPAs have their place and can be used for web applications like dashboards, SaaS web applications, etc, static sites can be more useful for websites that focus on content - such as blogs, documentation and marketing websites. This is because static pages load faster due to zero or little JavaScript.

You might like the modern component-driven design that frameworks like React and Vue.js popularised, but I wonder if there is a better way to have the same workflow but ship zero or little JavaScript by default.

This is possible today with Astro. I recently took two of my websites - dominuskelvin.dev and The Sailscasts Blog from both being SPAs that were statically generated with Nuxt.js and Gridsome, respectively, to static pages generated by Astro. I wrote extensively about my experience with the rewrite on my blog.

Here are some of the core benefits I experienced with Astro:

Zero JavaScript by default with the help of island architecture

Astro works by letting me author my website using JavaScript, and then when I build for production, it generates static HTML that can be served via a CDN - or however I want to host my web pages.

You may then be wondering what happens when I need interactivity in an Astro website. Astro made this possible via Islands. Islands are sections of your pages that are partially hydrated, allowing them to be interactive.

Astro does this by letting me bring my framework components of choice into Astro pages and then make them interactive only when the user needs them. For example, I could use Vue.js, React, Svelte or Solid components and make them usable when the page has finished loading or when they are visible to the user.

Modern workflow with Astro components

I know we enjoy the component-driven architecture made popular by React, and we fall into the temptation of passively building everything as a React SPA. With Astro, you get the developer experience you have come to love in frameworks like React and Vue.js with Astro components - a JSX-inspired way of authoring Astro pages.

Out-of-the-box SEO and support for Markdown

One drawback with SPA is that they aren’t great for SEO, and for content-focused websites, SEO is gold. With Astro, since everything is HTML by default, you get amazing SEO out-of-the-box.

I also love authoring content with Markdown, and Astro comes with first-party support of Markdown out-of-the-box. This means, for example, you can use GitHub as your CMS because your content will already be in markdown files.

Of course, Inertia.js and Astro aren’t the only tools out there to help you ship less JavaScript and improve the user experience of your websites or web applications. Here are some more tools that you can test out:

#3 Qwik and Resumability

Qwik is a new take on server-side rendering for interactive web applications and uses the concept of resumability, the opposite of hydration. While traditional SSR/SSG methods involve rendering an app twice - first on the server and then on the client for interactivity through hydration - Qwik's resumability avoids this redundancy.

What resumability brings to the table is that instead of doing double work via hydration, your client-side interaction can resume execution from where the server left off. This infers that Qwik will only resume interactivity on the client in a lazy way and only re-render the portions of the app that changes because of fine-grained reactivity with signals.

Qwik is an interesting approach when you want to build a web app, but you want the benefit of SEO via rendering first on the server and a more performant way of handling interactivity on the client.

For examples of Qwik usage, check out Builder.io, Reflect, and Soundy.

#4 React Server Components

React Server Components (RSC) is a new approach for building React apps that ships zero JavaScript to the client by default, and the developer can now turn on client-side JavaScript when they want to for the interactive portion of their web apps.

Personally, I really like the idea of React coming up with an architecture that prioritises the performance of applications built with React, and this proves my point that shipping a lot of JavaScript to your users comes at a cost. A cost big enough that React had to rethink and come up with an architecture that prioritises shipping less JavaScript.

#5 Partytown and third-party JavaScript

We’ve been talking about the JavaScript you write so far, but what about things like analytics? For example, Mixpanel, Google Analytics, etc. Is there a way our users don’t have to pay a price for our business needs? Partytown solves that problem by running your third-party JavaScript in a web worker.

Partytown’s use of web workers for this task is really impressive, as web workers were made to let you run scripts in the background. So any scripts that are not core to the user experience, resource-heavy or degrade the user experience are offloaded to a web worker, and Partytown makes that seamless.


I think that what really matters at the end of the day as we build our web apps and websites is the ease with which the users can get things done and the experience they have in utilising what we’ve built.

The strategies and technologies discussed here present you with steps you can take today to ship JavaScript responsibly to your users at page load time or when they are interacting with your web apps.

Also worthy of note is that the technologies cited here are not the only ways to implement or employ these strategies, but they are references based on what I’ve used or I am interested in. You may want to check out Marko from eBay, for example, on how they have been shipping less JavaScript for years now.

Further reading

Kelvin Omereshone is the lead maintainer of Sails , JavaScript engineer and Developer Advocate at Treblle. He loves Helping developers build business on JavaScript and teaches full-stack JavaScript at sailscasts.com.

Read more


Recent posts

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.