How Qwik’s Astro Integration Beats Both React and Vanilla JS

In this post I’ll be talking about the new @qwikdev/astro integration. I believe it to be the solution I’ve been looking for to flatten out a bump I encountered while developing my personal website.

As you’ve probably guessed, my site is built using Astro and is broadly “static”; but, as is often the case, even the most static of websites inevitably need some kind of interactivity, which is commonly enabled using JavaScript.

In my case, it’s to handle the sidebar navigation. It’s only a very small amount of interactivity, but there are a number of HTML elements that need to be referenced so that CSS class names can be added or removed to achieve the desired effect when a user clicks the menu icon.

 

Benefits of Using Astro

Astro, among other great things, ships zero JavaScript to the client (browser) by default; but, depending on what you’re building, you can choose which pages include JavaScript and which pages don’t.

What this means for the end-user experience is that pages will load super fast, because JavaScript is only included on the pages where it’s really needed.

However, when you need JavaScript to enable some kind of interactivity, you have two options…or so I thought.

Choose Your JavaScript Wisely

If you require any kind of interactivity in your site, you can either:

  1. Write Vanilla JavaScript using inline script elements, which are very lightweight but can become difficult to maintain (not to mention gross to look at, and write); or
  2. Use a JavaScript framework like React, Svelte or Vue etc., which will add additional bloat to the page but will likely be easier to maintain.

Using a framework is great, of course but if I’m using a framework to enable interactivity for my sidebar navigation, the framework’s runtime would need to be included on every page and could negatively impact my site’s performance — not to mention, taking this approach kind of defeats the point of using Astro in the first place!

Instead, I’ve currently opted for the Vanilla JavaScript approach, which does work but I didn’t have fun writing it. Also, when I was recently advised of a bug, I had to go back over some hard to follow, gross-looking code and figure out what was going wrong. But just last week I spotted this tweet from Steve Sewell, CEO of Builder.io and creator of Qwik. It was announcing the new Astro integration. I hadn’t used Qwik before, but Steve makes some compelling points in his video and upon first glance, it would appear to be the answer I’ve been looking for!

A Simple Sample

To put the theory into practice, I experimented with three approaches to building an interactive sidebar navigation and have prepared a slightly stripped-down version of my site’s sidebar navigation.

There’s a branch for each of my experiments available on the following GitHub links.

  1. Vanilla Js – main branch: https://github.com/PaulieScanlon/simple-sidebar-navigation-astro
  2. React – feat/add-react: https://github.com/PaulieScanlon/simple-sidebar-navigation-astro/tree/feat/add-react
  3. Qwik – feat/add-qwik: https://github.com/PaulieScanlon/simple-sidebar-navigation-astro/tree/feat/add-qwik

The component I’ll be referring to in the code below is called <Layout />, and can be found in src/layouts/layout.astro | .jsxon each of the branches.

1. Vanilla JavaScript

You can see the src code for this example here: src/layouts/layout.astro

In the code snippet below you’ll see there are ~36 lines of code that make the sidebar navigation work! This kind of JavaScript can become difficult to maintain and there are a number of areas where things could go wrong.

Where Things Can Go Wrong

To give you an example. If I use the lightbox as an example (the lightbox is the semi-transparent black color that is visible when the navigation is open), you should be able to see just how many fiddly little things are involved when using Vanilla JavaScript.

From grabbing a reference to the id, creating variables to hold the different class names (I’m using Tailwind by the way), then there’s the classList methods to add and remove styles, plus the eventListener that needs to be attached to the DOM element.


HTML:


If at any point I make a change to any one of those lines of JavaScript or accidentally remove the id from the HTML element, the navigation would break, making it impossible for people to use my site!

That said, the one thing this approach has got going for it is that it’s super lightweight. Vanilla JavaScript, or JavaScript that the browser can natively understand, doesn’t require any additional runtimes to be downloaded for it to work.

2. React

You can see the src code for this example here: src/layouts/layout.jsx

By contrast, if I enable the same functionality using React, you’ll see how much cleaner and easier it is to read. There are just ~5 lines of code to change a state value, which in turn causes React to re-render the HTML, and a ternary operator can be used to decide which classes should be present in the HTML when React has finished hydrating the page.


HTML:


The good parts about using React are that the JavaScript part is super simple, and the class names are now easier to read because everything is all in one place in the HTML. The downside is that by using React i’ve added an additional ~47kb of JavaScript to every page of my website.

3. Qwik

You can see the src code for this example here: src/layouts/layout.jsx

As before with React, there are ~5 lines of code to change the state value. The HTML setup is very similar to React, where a ternary operator is used to control which class names are used.


HTML:


However, and this is the big one for me, by using Qwik instead of React, I’m only adding an additional ~2kb of JavaScript to every page of my website!

The Results

Below are the results of the overall page size (which includes HTML and CSS) for each of the methods mentioned above:

  1. Vanilla JS: 9.7kb
  2. React: 56.8kb
  3. Qwik: 11.2kb

Qwik, in my opinion, is the best of both worlds — it’s less verbose to write than Vanilla JavaScript and is considerably lighter compared to React.

What I also like about the Qwik approach is that the JavaScript is inlined, like it would have been had I written it using the Vanilla method. So there’s no actual .js files downloaded when you look in the Network tab of your browser’s dev tools.

Qwik - inline script

There’s More to Qwik

But that’s not all. Qwik uses a very different approach to handling updates to React. But rather than try to explain it, the Qwik docs have covered it very well here: Resumable vs. Hydration.

Another thing I like about this approach is that there are no client directives required. For example, when using React you need to tell Astro that the component (in this case, Layout) is client:only, which means Astro will skip rendering it on the server, and hopefully it’s clear why JavaScript that enables interactivity in the browser doesn’t need to be rendered on the server.


Whereas, when using Qwik it would simply be this.


The Qwik approach looks the same as if the Layout component were an .astro file, so that’s another thing you don’t have to worry about when developing — or making future changes.

Final Thoughts

The Qwik Astro integration is currently in the early stages of development. You’ll see from my sample repository that I’m using version 0.1.16; so, as impressed as I am with it, I’m going to hold off implementing it in my site for just a little longer.

That said, the folks were super “qwik” in dealing with an issue I opened (thanks again Jack!) so I’m confident a stable v1 will be ready soon, and when it is, I’m 100% ready to implement it on my site.

If you have an Astro site and need interactivity, give Qwik a try. The two technologies compliment one another really rather well.

Group Created with Sketch.

 

 

 

 

Top