Don’t worry, I haven’t gone anywhere! I’m currently hard at work refactoring the blog toolkit I authored in order to create this blog, which I named sbstr8.
Refactoring, as other engineers probably know, is the art of generalizing or otherwise mangling code into a new shape. I’m doing a major refactor, but I’ve committed to not break the build at every step!
First of all, I made myself a fresh
git checkout -b refactor
And the whole time, to ensure I haven’t broken the build, I have the site up and running in development mode at
npm run dev. Crucially, I never break the build; each commit is a functional snapshot of this website! Yes, this is a flex :3
In this new
git branch, I’m moving source files individually from e.g.
Were I using VS Code, there’d probably be some fancy tool to move and refactor files, but I’m neovim all the way, baby, which means I need to improvise with some regular expressions.
sed is of course the usual tool that one would use under a unix-like OS, but venerable
sed lacks previews, and besides, it’s boring.
So instead, I’m using
sad, an amazing, efficient CLI tool that lets you opt in and out of each change.
The full incantation (from the repo root) looks like:
pushd src; fd | sad '@/components/foo' '@/sbstr8/components/foo’; popd
I exploit the fact that I’m using
@-prefixed import paths to build regular expressions that neatly target just the imports.
When I’m satisfied, I stage the result with
git add -p, walking through the changes (thanks to
delta again for the highlighting.)
Sometimes I’m also renaming components as I go; for this, I do another find/replace (messier and more ad-hoc, a pattern enabled by
sad) search for e.g.
Foo and approve or disapprove of each offered conversion (to
git mv the files so they are actually in the right place:
git mv src/components/foo.tsx src/sbstr8/components/bar.tsx
I then commit the change. Crucially, each change is atomic. So I can roll back the refactoring of any given file.
The next step is to add Jest snapshot tests and Storybook stories under
./src/sbstr8, so I can see what is changing and how.
Then, I’ll copy the
./sbstr8 directory back into the sbstr8 repo. At this point, I’ll also strip out style information (I don’t want every sbstr8 site looking like lizmars.net; I want the blog engine to be nearly ‘headless’ (visually unopinionated).
When everything is kosher over at
sbstr8, I’ll merge into
lizmars.net from sbstr8.
And this is the fancy part! At this stage, I’ll revert most of the commits I made above.
As I revert each commit, I’ll wind up with:
- a stylized, lizmars.net component under
- an unstyled base component under
I’ll then copy the snapshot jest tests and stories (which I will need for the next step) from the
./src/sbstr8/components directory into
I’ll then use those tests as a so-called ‘harness’ while I modify each of the lizmars.net components to add styling to the now-unstyled sbstr8 base component.
There will be some other steps as well, with a similar philosophy, for e.g. handling
sitemap.ts. This absolutely will take another day or two.
But! The payoff for this elaborate dance is pretty epic: I’ll have an unbroken build the entire time.
And that’s how you do a major refactor with both efficiency and caution.
Don’t believe me? You’re reading these very words in the refactored branch, halfway through refactoring!
Photo Wikimedia Commons. CC0 1.0. Universal Public Domain Dedication