January is generally a terrible month to start any new projects. I’m of the mind that new year’s resolutions should be saved for the spring equinox, at the earliest. The best thing to do in January is to get cosy, surround yourself with familiar things, and keep your head down until February.
I had this in mind when I opened up this very website in my dev environment the other day. Couple of CSS tweaks and a new journal entry to keep me busy - perfect way to spend a spare evening.
Of course it wasn’t going to be that easy. The project didn’t want to run, even after updating all the dependencies. Gatsby threw error after error.
Now, I’d been thinking about migrating this project away from Gatsby for a while. My implementation of it had become awfully outdated over the past… [checks watch]… eight years. It was starting to feel like it was held together with duct tape.
My search for a new framework quickly led me to Astro. Component-based, but not tied to any particular front-end framework. SSG, but only per component. Same for hydration. No GraphQL in the data layer, just imports.
So I thought I’d dip my toe in. And here I am a week later, happily reporting that the water’s just fine. I’m not going to sing Astro’s praises or give you all kinds of statistics in comparison to other frameworks - Astro can do that for itself. What I can tell you is just how easy the migration process was.
The tutorial has it all
After following the “Build a blog” tutorial from start to finish, I had everything I needed to move my project over, more or less wholesale. The final chapter of the tutorial covers adding Preact to the project, so from the beginning of the migration I was using a combination of React and Astro components. I’ve managed to reduce the number of components I was using to begin with, and converted a few of the remainder into Astro components. The plan is to eventually convert everything into an Astro component; I might not even need Preact anymore when I’m done.
One thing that’s really impressed me is how little config Astro needs in order to generate pages. With Gatsby, I had eighty-two lines of code in gatsby-node.js, alongside a Gatsby library, describing how I wanted my Markdown files to be converted into HTML. In my astro.config.mjs, I have four lines telling it which Shiki theme to use on code blocks in my journal entries. That’s all the config it needs to generate my journal.
And dependencies! The Gatsby project had fifty-seven dependencies. The Astro project has eleven, four of which are Fontsource libraries. Seven dependencies to run this website. That’s remarkable.
The tutorial also contains a section for building a theme toggle icon, which blew me away with its simplicity. The JavaScript to power it lives inside the Astro component file itself, and relies on no-third party libraries. Thanks to Astro’s island architecture, the rest of the website isn’t aware of this JavaScript at all. At this point, I had to take a moment to look with disgust at all the code I’d written in Gatsby, across several different files, to achieve the same effect. So long, gatsby-plugin-use-dark-mode.
Beyond what I learned in the tutorial, I created a content collection for my journal entries, so that I can import all of them with just one line of JavaScript at the top of an Astro file, instead of writing a huge GraphQL query in Gatsby.
Getting dynamic images working for each entry was a dream. Astro uses import.meta.glob to grab everything in your image directory, then it’s a simple matter of using the journal entry’s image property from the frontmatter as a key on the images object. For a project whose priority isn’t necessarily top-quality images (come on, I know you were thinking it), not having to faff about with Sharp was a real blessing.
Redirecting to a new mindset
Most exciting of all was the change I was able to make to my journal content thanks to Astro’s configured redirects. Instead of having MDX files with content copied from the articles I’ve written on Medium, I’ve got MDX files that are empty except for the frontmatter needed to generate the entry and its corresponding route in Astro. In astro.config.mjs, the redirect config is as simple as saying “go from that route to this URL”:
redirects: {
"/journal/joeys-journal-entry": "https://medium.com/..."
}
Funny how something so intuitive could cause me to completely rethink the way I present my content. Aside from the work of migrating the code, I’ve rebuilt a lot of my previous content as journal entries, instead of treating them purely as external links. The whole site feels more coherent now.
Oh, and I did that CSS tweak I mentioned at the beginning. Can’t forget that. (I’m actually insanely proud of how the journal looks now. I’ve never been completely satisfied with it before. I’ve truly outdone myself.)
I’m not going to wrap this up with talk of reduced build times and whatnot; this project is tiny enough that those numbers would be meaningless to anyone else. But I’m here to tell you that Astro makes for a very enjoyable dev experience, and I’m glad that I migrated to it.