Performance in web-apps: the solutions
At the very end of this saga we want to close it talking about actual solutions we can apply to improve the performance of your web-apps! Have you ever tried one of these?
In previous posts we have talked about:
- The importance of performance
- The goal we want to achieve
- Which tools can help us in the process
- A lot of tips in how we can be able to read the output of the tools
And now I want to mention a compilation of some helpful ideas that could improve your situation.
Identify your problems
“The first step is to recognize that you have a problem”
It's funny because it's true, if you don't understand your application you are acting erratic. So, if you are very lucky you might solve the problems. But if you aren't, then you are losing your time (and money) in the process.
There is an incredible amount of improvement-opportunities in the path and they are not free at all: if something only gives you benefits at 0 cost then that would be a standard and all the tools will provide you with it.
Here is a little set of useful tips I've learnt through the years:
- Infrastructure: the TTFB is a good indicator, but it is not enough. This is especially tricky because it is tightened with regions and connection types. I can suggest to choose flexible hostings with the ability to replicate your app in different regions if you need it.
- Server side improvements: I have focused the whole saga of posts in the front side of the problem but there is always a back side and a lot can be done there. Just don't forget that it remains as an option.
- Find your long tasks: If you analyse the waterfall in the page load some tasks are quite expensive than others. If those are needed for your critical path it is a good starting point for your improvement process.
- Avoid slow requests: once you find the requests which take lots of time, ask yourself how needed they are, if they can be asynchronous or even if you can break them into smaller pieces.
- You are as reliable as your third parties are: if some of them are slow then you are slow. This is very usual when talking about adds. Always remember that the perceived performance is from the whole product, it doesn't really matter if it wasn't your fault: you are as performant as the less performant of your dependencies. Remember to audit them in the process.
Decide based on your product
Everything that an automated tool "says" to you are suggestions. You are the right person to decide if the tool was correct or it is only noise. In order to be able to make that decision you must know the product. Special attention to the word PRODUCT. I am not saying only your application, I mean the whole context because I want to include the business in the equation.
Why? Simple, everything costs money and has pros and cons, so all of us want to spend only the needed amount of money to maximize the pros and minimize the cons, and you can not do that effectively without knowledge.
You should be able to talk with others about:
- The market where you are
- what are your competitors doing
- which is your differential
- The users you have
- who are they
- which are your top devices
- which are the common conditions were your product is being used
- You need to know which are your hero components
- If there is a lot to do, then please stay focused on the critical render path and always remember that sometimes it is more important to be perceived as performant rather than being performant. A lot more about Critical rendering path can be found here.
If you don't remember what I am talking about when I say that performance is also UX and what are hero components, please read the previous post: the objectives.
What can I do?
Always remember how is that technology works, and with that in mind (plus all the analysis we had already done), you will notice that the key point of the ideas here is to reduce the amount of data needed to perform the UI rendering or at least delay it.
Let's start with the easiest, because there is no alternative to keep a clean base of code. Avoid the zombie code: that code that was used a lot, then it lost popularity and now it's only used by that forgotten file in the app that no one has refactored yet (in my experience it is the css story of its life).
Remove the dead code, no one is using it, so please stop sending it to the client "just in case" that for some kind of dark sorcery one day a developer might want to use it again. You have your repository's history for that use case.
Try to avoid that tendency of adding a whole new library just because you want to use one (amazing) function. Why don't you re-write only that function in you own code base?
If you want to reduce your payload at least for the first view, some good ideas might be:
- Server side rendering: This is a normal solution to improve SEO but you can notice that it is very helpful when you want to speed the first load, because the whole point is to generate the final HTML in the server and respond directly with it (avoiding processing in the client as much as possible). I really love this short post because it gives context about the irony of rendering in the server and programming for a “heavy” client, the thing is that I’ve found it only in spanish https://lemoncode.net/lemoncode-blog/2018/5/13/server-side-rendering-i-conceptos
A lot more about rendering in the web and its flavors can be found in this great article https://developers.google.com/web/updates/2019/02/rendering-on-the-web
I will leave here the summary hopping that you find it interesting enough to read it:
Also if you send big payloads: use minifiers as soon as possible, every serious solution configures them by default nowadays, so first check your current status.
When you see problems with the loading of the fonts, you might be interested in fallback fonts or other ideas like using SVG fonts.
If you have hundreds of requests (try to reduce them!) be sure that you are doing everything you can in an asynchronous way. Also if the requests tend to be repeated you can enable a cache of responses.
If you have problems with images, lazy loading is a great option (https://medium.com/front-end-weekly/how-to-optimize-image-loading-on-your-website-855020fb41ae), but also some other used technics are:
- revise and use the right image formats
- serve only content that fits best for the device
You can find more information in this post: https://kinsta.com/blog/optimize-images-for-web/
I think that we can write at least one dedicated post for every idea I have mentioned before and those are just the visible part of the iceberg. As a matter of fact, I’ve left links to many others posts and lots of them are specific parts of this topic: https://developers.google.com/web/fundamentals/performance/why-performance-matters.
Always remember that a lot can be achieved with a change of hosting: keep that in the radar.
If you are about to overload for too much information and you want to remember only one thing after this very fast explanation I will highlight the idea of choosing the easiest action that speeds up the loading of your critical path.
I have no idea how to start
I will give you a recipe for that if you are interested: tomorrow when you start working, after preparing your favourite beverage for starting a great day, run webpagetest for your app. While it is running try to recognize your hero actions, while it is being executed, run Lighthouse and see the suggestions (compare them with the ones from webpagetest).
When you are confused read more about performance, concepts and good/bad results and discuss everything with your team.
Together with your team you can achieve the goal in an iterative and incremental way and end up with an automatic tool with history which measures automatically and alerts you all when something is not working as expected.
And if you have questions, thoughts or general feedback leave us a comment here!