- My code broke the live site. Why didn't it do what I intended for it to do? How did it get all the way to production?
You're probably a frontend developer like me.
In this article I will try to convince you that you should learn to automate some actions for your repo.
I began building web pages in the 90's. My computer was old and I couldn't run both the editor and the web browser at the same time. I'd edit in DOS, then start Windows to proceed and open the page in Netscape. I'd have a quick look, then exit Windows and go back to editing.
This flow of edit, save, check it out in the browser, is sometimes referred to as The Inner Loop. I found out about this term from Kenneth who came across it when he worked at Microsoft.
As soon as I got better hardware my Inner Loop
was much faster. I would simply save, alt-tab, and refresh the browser.
"CSS reloader" plugins came several years later. For pages where you were styling a specific state, for instance filling out a form to trigger a validation message, this was very useful. You didn't need to click and type after every page refresh, simply because you didn't need to page refresh most of the time.
Nowadays we have the Webpack Dev Server which reloads automatically using Websocket, can reload components of a web application, keeping even the JavaScipt state intact when possible.
The Inner Loop
is shortened a lot.
But there are lots of more things we can do today to make our lives easier.
Typescript is one of these things. It enables me to keep writing longer, because I don't need to check for the trivial things. Like I forgot to add a return value, I didn't call the method properly... Believe me, I make these errors all the time.
So Typescript doesn't make the loops shorter. Instead it can almost be seen as to shift gears: You don't need to use as many loops to get there, because Typescript reduces the need for confirming that what you wrote became what you wanted.
This doesn't just make you faster. I find it makes me more skilled as a developer since I can spend more time thinking on the bigger problems while writing my code.
Unit Testing
is a way to ensure that our functions are still doing what we expect them to do. They're a great way to avoid getting errors into production.
And a way to get less context switching when writing the Unit Tests
is to use an editor plug-in for unit testing, like https://wallabyjs.com. You no longer need to alt-tab to your test runner to see the results. Instead it is visible from right where you write your source code. It's kind of the same cycle but it is way faster and more intuitive.
So it's important to have a fast Inner Loop
and to be able to use fewer loops to get there, i.e. Shift Gears
.
Outer Loops
can be very important to optimise too.
Some Outer Loops
involve:
- Code review (PR)
- Release pipelines
- Stakeholder approvals
The messy part of the Outer Loop
is that it one cycle can be pretty slow. From the time that my code was written until I found out that it rendered a blank screen to some users, was several days. And from the point that I fixed the problem until it completely went away was over an hour.
What if we could catch some of problems before they reach the Outer Loop
? That could save me a lot of time. But better than that, it would give the users of my site a much better experience.
And in a way, many of the things we do as developers are in fact to reduce the risk of letting bugs escape into production.
These loops all help answering something that's useful to us as developers and can provide a kind of checklist – is our code performing to the standard we want?
- Unit tests: Are our functions still doing what we expect?
- Living Style guide: Are the components still doing what we expect?
- Typescript: Are we calling our methods with a seemingly correct signature? (And much more... static analysis)
- Lint: Is the code written in a consistent style?
- End-to-end testing: Is the system still working in its entirety?
- Testing environment (for people): Does the application work, look and feel as we intended? (Also: On real devices, to get a feel for the layout, performance, and possible cross browser bugs)
All of these loops can be automated. All of them and more.
What are Github Actions?
GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.
Essentially you can run a workflow on any event. Events like pull_request
, commit
, even cron
for recurring intervals. To make it easier, "Actions" are pre-baked actions you can use to perform repeating things like setting up Node, checking out code and so on.
We've been using Github Actions for about two months and we came up with the following workflows:
- Check lint
- Check TypeScript
- Run unit tests
- Build the code and the style guide
- Check that the build fits within the performance budget
All of these tasks you could essentially perform on your own machine before creating the PR. But there's much more.
- Publish the PR build to an environment
This is my jam. As a result we can now:
- Run end-to-end tests against that environment
- Run Lighthouse against that environment
- ANYONE can visit this environment to verify that it works as intended
I mean product owners, UI designers, testers, developers and so on. Instead of discovering problems in production, we can catch them before they were even merged.