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.
- Minimal tech lock-in
- High lighthouse score (95, at least)
- Try to reduce bundle size as much as possible
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.
This is for the homepage that has a WebGL sketch using post-processing.
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.
This site was another excuse to experiment with 3D graphics, shaders and WebGL. Three.js was ruled out from the start because of the
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.
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.
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.
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.
As with most things in development, there were a few surprises along the way, so here’s my wish list for the Gatsby team:
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.
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.
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.
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.