DEV Community

Cover image for Personal website case study
Alvin Bryan
Alvin Bryan

Posted on • Originally published at alvin.codes on

Personal website case study

I recently launched my personal website. It took a while and was a slog at times, but I learnt a lot along the way. It feels very "me" now.

The launch day went beyond my expectations. I got lucky that Josh Comeau liked it enough to tweet about it. The numbers were nice, but the most important aspect was the response: People were impressed and genuinely liked it.

Hopefully folks here will be interested in what's going on under the hood.

Disclaimer: For brevity’s sake I’m assuming a fair bit of prior knowledge. If you would like to learn more about something mentioned here, let me know on Twitter or here directly.

Requirements

  • Minimal tech lock-in
  • High lighthouse score (95, at least)
  • Try to reduce bundle size as much as possible
  • The reading experience works without JavaScript

Minimal tech lock-in

I don’t want my site to rely on a specific technology too much. I don’t use CSS-in-JS, I hardly use React hooks or component methods, and favour implicit declarations over “Gatsby magic.” Everything should be easy to reproduce with another generator.

I feel like I made the right choice with Gatsby, and it boils down to two time-saving elements: plugins and built-ins.

Do you want a dark mode? Here’s gatsby-plugin-dark-mode. Crazy WebGL graphics with glslify? You’ve got gatsby-plugin-glslify. An RSS feed? Yep. Gatsby even optimises my images, and adds aria-current to active links.

On the Markdown side of the house, I dearly missed Jekyll’s fantastic defaults, but again: Plugins! Remark (the markdown processor) has itself a thriving ecosystem. I got footnotes, custom expanding blocks and table of contents by adding the corresponding plugins.
You can see examples on the original post.

I’m also pleased that I didn’t have to fiddle with Gatsby internals too much.

High Lighthouse score

Screen shot showing a hight lighthouse score

This is for the homepage that has a WebGL sketch using post-processing.

Reduce Bundle size

Throughout the development process of this site I was ruthless when it comes to dependency sizes:

  • I run every dependency through package-size to make sure there isn’t a smaller alternative, and including it is weighed against its cost.
  • The fonts are compressed as Woff2 files and self-hosted.
  • Preact is used to make the Gatsby runtime 30% smaller.

WebGL sites tend to have needlessly large bundle sizes, here’s my answer to that.

WebGL

This site was another excuse to experiment with 3D graphics, shaders and WebGL. Three.js was ruled out from the start because of the ridiculously large JavaScript size. I tried to strip most features out of Babylon.Js but the bundle was still too big. I ended up using Regl 👑 which is way more lightweight but more low-level, (you have to write GLSL). It’s battle-tested, has been stable for years, and isn’t changing any time soon. Fun fact: Mikola, the creator of Regl, even moved off-the-grid to a lava field at one point and no problem happened with the library.

I’m keeping an eye on OGL which is an even smaller WebGL library and even gives us a scene graph out-of-the-box, but the API isn’t final yet.

Here’s how they compare (minified size):

  • 632.33 KB – Three.js v0.120.1
  • 110.85 KB – Regl v1.6.1
  • 98.39 KB – OGL v0.0.60

Picking Regl over Three.js saves us 500kb, more than a five-fold decrease in bundle size. Performance was also paramount. My goal was a smooth 60fps experience on my old budget Android.

Thanks to Gatsby’s code-splitting, the WebGL library is only included in the homepage.

Homepage sketch

First, I wanted to create a fractal. They have always fascinated me, whether in code or in nature. There are a lot of fractals to choose from in 2D, but in 3D they’re kind of hard. The only one that I could wrap my head around quickly was the Menger sponge.

Menger Sponge Fractal
The 1st homepage sketch: 160 000 cubes forming a Menger sponge fractal

After adding a bit of instancing magic, there it was. 60fps and all, except boring to look at. I tucked that code away and turned my attention to another piece of Math & Magic that I had wanted to play with: attractors.

The Nosé-Hoover Attractor
The 2nd homepage sketch: Cubes along a Nosé-Hoover attractor

Despite running at 60fps it “felt” sluggish and became boring to look at.

The final attempt at shoehorning adding 3D graphics to this is what you can see on the homepage now.

Gatsby wish list

As with most things in development, there were a few surprises along the way, so here’s my wish list for the Gatsby team:

Become evergreen by default

I wish Gatsby’s relationship with older browsers was an “opt-in” one as opposed to “opt-out.” I prefer a lean website out of the box, with features like Webp enabled and polyfills removed by default. I would rather add backwards compatibility if necessary.

Disparity in plugin quality

Gatsby makes it easy to find plugins, and to know which ones are maintained by the core team. Despite this, there is a huge variance in the quality of the non-official plugins. I wish more things were parsed out of the plugin repository (like the number of open issues without a response) as some are still referenced despite deal-breaker issues.

Telemetry

That should absolutely be disabled by default from the stable release.

I understand the idea, but knowing that a seemingly innocuous CLI might transmit data when I’m not explicitly asking it to is scary, and sets a dangerous precedent. The logs may be “anonymised” but doing this is extremely hard and a waste of time.

If it’s not disabled by default, then “How to opt-out of telemetry” should at the very least be part of the kick-start tutorial (like VSCode does) and not buried in the documentation. I would even argue that the CLI should ask for again permission every once in a while.

Final words

On top of everything mentioned above, I wrote scripts, GraphQL queries, and learned about CSS grids, Exif data, and more. I feel like I’ve come out of it as a better coder.

Discussion (0)