Performance is a term that we know we should be constantly thinking about (and working on), but for different reasons, we tend to forget about it. The truth is that it can be such an overwhelming topic that when face these issues, it's hard to know where to even begin.
And even though, nowadays we have a lot of tools that will help us test our apps to see how they're doing, at the same time understanding how they work can be a bit tricky (and sometimes really hard), so with the limited time we have, we often put it to the side because results seem to be less noticeable than other things like shipping a new feature or fixing a nasty bug.
In this article, I'll cover some initial notions on why should we care, how to get started and how to make it part of our daily workflows.
But first, it's a good idea to go over a few things to both understand the importance of performance and to set the right expectations about it:
While less noticeable at first glance, the performance of our app or Website can have an even bigger (and often negative) impact on our users, sometimes even driving them away and choosing to go to a different site. If your app belongs to a business, this could turn into an even worse result, driving customers away and losing a potential sale to a competitor that has a "faster" site than yours.
We can find plenty of stats shared by big companies about how delays of even 1 second or less while loading their content can impact their sales or drive traffic away, so it makes you wonder if that kind of impact can happen to well-known brands, what can it do to ours?
Like most good things in life, having a performant app doesn't come easy, and it's important to understand that right off the bat. Working on performance related issues involve a lot of... well, work. Sadly, there's no miraculous package or library that we can use and will solve all of our problems (yet, who knows, maybe one day, you know, with like 🤖🤖🤖 and stuff), but that doesn't mean it's impossible to achieve, in fact, quite the opposite. The process of solving performance issues and improving our apps is relatively straightforward:
- Collect some data.
- Collect some new data and compare.
- Draw conclusions (a.k.a keep what worked, undo what didn't).
While some of these parts might have different implications (and some of them might be a bit tricky), the process is always the same, which makes these two things even more important to keep in mind:
- What works on some other app might not be the right thing for yours: This doesn't mean that good practices and general advice should be dismissed, it's often useful advice that will help us get there, just that it might not be right (or the biggest priority) for your use case.
- Performance is, a lot of times, all about trade-offs.
As developers, a lot of times our first reaction when we get involved in a project that has issues is to think about rewriting that code. Truth is, most of the times, we won't be able to do so due to time constraints, budgets or other priorities. That's why it's a good idea to think about improving the current codebase we're working on instead of throwing it out and writing a new one. With this, we'll be able to compare results with actual data that has been live for a long time and get a better idea of the impact every change makes.
And, if we ever actually get to do a rewrite, there's a lot of things that we'll probably keep in mind to make it better.
So, with all of this in mind, how do we start?: With a plan.
Going head first into working not knowing what we're supposed to achieve will probably cause more problems than it solves. Understanding what should be the focus of the work and making a plan on how to execute it will allow us to get actual wins that are relevant to the main purpose of our app.
Wait, purpose, what do you mean?
When building an app, or a Website, probably one of the first questions we should ask ourselves is What is this app trying to achieve?. In most cases, the goal is pretty clear: sell something, show content, provide a service and so on. Now, while identifying the main goal can be straightforward, a lot of times it's hard to get a clear idea of how the app should focus to accomplish that goal.
That focus tends to be different between apps, especially if they fall under different categories, and it relates closely to where our performance efforts should be concentrating on.
For instance, let's say we build a Website to sell cookies. The main goal of the site would be pretty clear: selling those delightful 🍪🍪🍪. Now, when planning the features of the homepage of the site, we know we'll probably have these sections:
- A header with a nice logo and a menu with cool animations.
- A list with all the cookies available.
- A sidebar with contact info, social media links, newsletter signup for promotions and some ads.
- A cool footer with all the legal info.
If we go back to what our main goal is (selling cookies), and we think about the importance of each section and how it relates to the goal, we can probably assume that our users don't really care about some of the stuff on that list and that they're visiting the site to get some cookies (and that's what we want too). So with that in mind, we should probably put our efforts in showing them the list with the cookies first and as fast as possible instead of spending time and resources displaying the menu and the animations (as cool as they might be) or the sidebar with the social media links, so that's where our plan should focus on.
One very important thing to understand when talking about performance is that it's an ongoing effort and that it's very likely that we won't be able to fix every issue right away. A big part of this is measuring and experimentation, so there's a lot of back and forth between trying new things, analyzing trade-offs and making decisions based on that. As well, there's a pretty good chance that the changes we make will not have huge differences in terms of percentages, but that doesn't mean that are not wins, on the contrary, every improvement we make will have an impact on every user that visits our site and will make their experience better.
So, with that in mind, a good rule of thumb will be to plan for gradual improvements between 5-10% on each cycle of work. If we can get more, excellent, but everything between those numbers should be great and realistic since initially, the wins will be bigger and more noticeable, but as we progress, it'll be harder to find places for improvement. After every cycle of improvements, we can get some new samples and plan for the next one.
The last step before getting to work is to get real data from the current performance of our app to identify the pain points and prioritize the work. We do that by measuring.
Whenever thinking about why should we measure, I like to think about these principles:
- Sometimes things look fast, but they're not.
- Sometimes things look ok but could be better.
- Sometimes things look slow, but it's not their fault.
Browsers are faster than ever, so nowadays are able to do a lot of things faster than we can notice, but that doesn't necessarily mean that they are, indeed, fast. A lot of stuff happens underneath that we won't get a clear idea until we peek under the hood and see how everything is being loaded, how much time each part takes and if any of it it's causing issues.
By using tools to measure each part of our app, we'll get a clear picture of how everything's truly looking, and it'll be easier to identify the problems and plan the work.
There is a lot of tooling these days that allow us to get a clear idea of how our app is performing, and even get some advice on how to improve any issues that are found. Out of those alternatives, the ones I like to use are:
Google Lighthouse is probably the best tool nowadays to run performance audits against our app. It takes care of checking different load scenarios, how we're handling resources and even give advice on how to improve any issues found, even when it comes to accessibility and SEO. The best thing about it, is that there are multiple ways to run it (through Google's Web Dev site, Chrome extension or even Chrome Dev Tools), and can even be incorporated to our daily workflow as a build check with their GitHub integration.
A while back, if you measured a URL in PageSpeed Insights and Lighthouse, you would often get some different information, scores, and advice, so it is useful to run both and consolidate that information. Currently, it's a lot closer, but it doesn't hurt to actually keep checking on both to make sure we're tackling all the issues found.
Running audits with an external tool like Pingdom is also useful to have extra data that we can compare. One of the cool things about this one, in particular, is that it allows us to test how our site is loading from different locations, so if we're reaching a global audience, we'll have a better idea of how they see our content.
And last, but certainly not least, it's the Performance Tab of Chrome Dev Tools, which will be one of our best friends while doing local development. With it, we can record everything that happens with our site while it loads, including how much code is being parsed, in what order, if we're making our CPU work too much and how long everything takes, which will give us a clear picture on potential bottlenecks that we should work on.
Remember a couple of sections ago where we discussed Identifying the main goal of your app? Now that we have real data and know where the pain points are, it's easier to get an idea of which of those are affecting that goal. With that in mind, defining priorities and putting together a list of things that will have the bigger impact it's important since those wins will not only benefit users but also whatever we're trying to achieve with our app.
As it happens commonly with tests during software development, we need to change the way we think about performance and think of it as part of the process instead of an extra. The best way to do this and make it part of the culture of our teams is to try to find a way to include it as part of our planning. A good idea is, at the beginning of every sprint, to leave 10-20% of our time to work on performance issues. If we make this an ongoing effort and part of our weekly work, not only it'll become something everyone will care about, but eventually, there will be fewer problems to attack and efforts will not be as significant.
The good thing about performance improvements is that they're usually tied to wins for the business, so making a case to dedicate time to this is not as hard as other technical tasks like refactoring some code, improving tooling, and others.
Premature optimization is one of the big gotchas when thinking about performance. It's easy to get caught up in thinking too far ahead and trying to come up with the best way to handle cases we may never reach, so it's a good idea to not worry about it too much at the beginning, but at the same time, keep an eye on things and try to identify possible issues that could arise at some point.
One of the big mistakes we usually make as developers is to test apps under the best conditions (locally, in our computer, with a fast internet connection). But we have to wonder, it's that the reality of our users? Probably not. That's why when testing it's a good idea to emulate different scenarios (slower CPUs or network connections) and see how our app behaves. It's important to remember that things always look great under the best conditions, but it's only under some constraints that we start seeing the cracks 😔.
Lucky for us, it's simple to simulate those conditions and test now, thanks to the Chrome Dev Tools:
Play around with those settings and reload your app, and that will allow you to see it under those simulated conditions.
Note: Those conditions are kept as long as Chrome Dev Tools is open. As soon as we close it, we'll go back to normal settings.
Get data about your users (devices, browsers) and see what they're using and what you should be thinking of
With tools like Google Analytics, it's easier than ever to get a clear idea of not only where your users are, but also what are they are using when visiting your site: browsers, devices, operating systems, and even screen resolutions. Having that data will be your superpower to figure out what your focus should be and to avoid wasted efforts.
For instance, if you collect data and realize that 100% of your users come to your site with the latest version of Chrome on Desktop, and no one is using other browsers or mobile devices, you could safely prioritize issues that are affecting them and not focus (so much) on your mobile version or supporting old versions of other browsers. On the contrary, not having that data could mean spending countless hours fixing bugs that will probably have zero impact on your users.
And now that we have the data, the ideas and know what we need to focus on, it's time to get to work!. But, how do we do that? Well, that's for the next article ✌️.
Originally published on my blog at xabadu.dev