For the last two weeks, I’ve been working on a really large refactor project at Gusto and I realize that this is the first time that a project like this has gone smoothly for me. There haven’t been any kinks in the process, it took about as much time as I thought it would, and no-one appears to be mad at me. In fact, things have gone almost suspiciously well. How did this happen and what was the issue?
Well, we had a problem with how our CSS was organized. Some pages in our app loaded Bootstrap and some didn’t. Others were loading only our app styles and some weren’t loading the styles we served from our component library, a separate repo that includes all our forms, buttons, and variables, etc. This led to all sorts of design inconsistencies but most important of all it wasn’t clear how to write CSS in our app. Do the component library styles override Bootstrap? Does Bootstrap override the app styles? It was scary stuff.
The goal was a rather complex one then. First, I needed to figure out how our styles were loaded in the app. Second, I wanted to remove Bootstrap from our
node_modules and make a new Sass file with all those styles. Third, I then had to remove all our Bootstrap styles and place them into the component library where we would be able to refactor every line of Bootstrap into each individual component (so all the styles for the
Tabs.jsx component was styled only by the
Tabs.scss file). All of this work should reduce the amount of CSS we write by thousands of lines and generally make our codebase more readable and much more developer-friendly for the future.
However, before I started I knew that everything would have to be extraordinarily organized because this would involve a big shakeup in terms of our codebase. There will be spreadsheets! There will be a single, neat and tidy pull request! Lo, and behold! There will be beautiful, glorious documentation for everyone to read.
So here are some tips on making sure that big refactor projects go smoothly, based on my experience working on this large and complex codebase. Let’s begin!
For this project, I needed to know a bunch of stuff beforehand, namely in the form of data. This data would then serve as metrics for success because if I could show that we could safely remove 90% of the CSS in the app then that’s a huge win that the rest of the team can celebrate.
My favorite tool for refactoring CSS these days is Chrome’s Coverage tab in DevTools and that’s because it can show you just how much CSS is applied to any given page. Take a look here:
And it showed me everything I needed: the number of CSS files we generated, the overall size of those files and how much CSS we can safely delete from that page.
The very first refactor project I worked on at Gusto was a complete nightmare because I jumped straight into the codebase and started blowing stuff up. I’d remove a class here, an element there, and soon enough I found myself having changed thousands of lines of CSS and breaking hundreds of automated tests. Of course, all of this was entirely my fault and it caused a bunch of folks to get mad at me, and rightly so!
This was because I hadn’t written down a list of everything that I wanted to do and the order I needed to do it in. Once you do this you can begin to understand just how big the scope of the project really is.
The second reason I made such a huge mistake on my first refactor project was that I wasn’t focused on a very specific task. I’d just change things depending on how I felt, which isn’t any way to manage a project.
But once you’ve made that list of tasks you can then break it down even further into each individual pull request that you’ll have to make. So you might already be doing this but I would thoroughly recommend trying to keep each commit as focused and as small as you can. You’ll need to be patient, a quality I certainly lack, and determined. Slow, small steps during a refactoring project is always better than a single large, unfocused pull request with dozens of unrelated commits in them.
If you happen to notice a new issue with the CSS or with the design as you’re refactoring then don’t rush to fix it, trust me. It’ll be a distraction. Instead, focus on the task at hand. You can always return to that other thing later.
This might just be something that I struggle with personally but I never realized until recently just how much of front-end development is a community effort. The real difficulty of the work doesn’t depend on whether you know the fanciest CSS technique, but rather how willing you are to communicate with the rest of your team.
Tell everyone you’re working on this project to make sure that there isn’t anything you overlooked. Refactoring large codebases can lead to edge cases that can then lead to overwhelmingly painful customer-facing problems. In our case, if I messed up the CSS then potentially thousands of people wouldn’t be paid that week by our app. Every little bit of information can only help you make this refactor process as efficient and as smooth as possible.
I really wish I could find the precise quote, but somewhere deep in Ellen Ullman’s excellent book Life in Code she writes about how programming is sort of like a bad translation of a book. Outside the codebase we have ideas, thoughts, knowledge. And when we convert those ideas into code something inexplicable is lost forever, regardless of how good you are at programming.
One small tip that helps that translation process is writing really detailed messages in the pull request itself. Why are you doing this? How are you going about it? How do you plan to test that your refactor didn’t break everything? That’s precisely the sort of information that will help someone in the future learn more about your original intent and what your goals were.
I learnt all this stuff the really hard, long stupid way. But if you happen to follow these tips then large front-end projects are bound to go a whole lot smoother, both for you and your team. I guarantee it.