How can we define web application performance?
By: Alexandr Kazachenko
Tags: Performance, Http2, JavaScript, Lighthouse, Google Chrome

Some applications are loaded quickly, some are slow, but why? Is page load speed the only indicator of application performance?

Answering these and many other questions in one article would be very difficult. So, I have collected a directory of links and categorized them. But for a start — a bit of theory about what performance is and when to think about it.

When performance problems begin

You can develop web applications for years and hardly face any application performance problems.

But most likely, problems occur in the following situations:

Big data appears (you need to render large lists or hundreds of thousands of points on the map). The application becomes big (hundreds of custom scripts, dozens of screens, forms, etc.). A large number of clients from different regions (for example, 300,000+ clients per day from all over the world). High competition in the market (for sure, a user will prefer your competitor’s application if it works faster). You need a mobile version (browsers on mobile devices still suffer from performance problems).

What does the performance consist of

Globally, performance problems with web applications can be divided into two categories: data transfer and runtime.

By data transfer we mean downloading any resources required for the application to run.

Under runtime — application operation, rendering and processing of user input.

Each of these categories contains a lot of nuances, which we often do not think about, but which distinguish high-quality applications from low-quality ones.

These are the most popular performance metrics for web applications (all should be minimal):

Page Loading

TTFB — Time To First Byte.

FCP — First Contentful Paint.

FMP — Time To First Meaningful Paint.

TTI — Time To Interactive (time until the page can react to user input).

Runtime

Response time to user input.

Time of interface redrawing.

Although TTFB and TTI are both page load performance metrics, they can be affected by runtime related issues.

How to search and analyze performance issues

The main set of tools in the developer’s arsenal is Chrome DevTools or similar tools such as Firebug/Firefox developer tools.

Network — allows you to analyze in detail what resources are loaded on the page, from what resources, at what speed and so on. This tool is often used for manual analysis of the page load speed.

Performance — in this tab you can enable recording of code execution calls, I/O operations and others. In addition, the record can be made with network and CPU throttling emulation. For example, you can check the application’s performance on weak devices.

Lighthouse — a tool built into Chrome DevTools that launches page loading, records metrics, analyzes them and even gives recommendations on performance improvement.

How to measure and monitor performance

Web application performance monitoring tools can be divided into two categories: those that perform synthetic measurements and those that record performance data from real users.

Synthetic monitoring tools include Lighthouse and Webpagetest.

For real user monitoring (RUM — real user monitoring) mPulse and Sematext will be suitable.

Besides there are tools like Webpack-bundle-analyzer which cannot be attributed to these two categories. But with their help it is possible to measure some parameters which influence productivity, for example the size of a bandle.

Data transfering

TCP connection, DNS lookup — you can speed up page loading even by properly configuring server connections. In particular, if you use DNS pre-fetching or even IP addresses instead of domain names.

TTFB (Time to First Byte). Time to First Byte is an important metric. To accelerate it, you should try to implement as little logic as possible on the server before issuing index.html.

HTTP1 vs HTTP2 — HTTP2 can greatly speed up page loading by multiplexing or compressing headers. Besides, the new (relatively) protocol opens up a lot of possibilities, for example, server push.

Domain sharding. If you need to pass a lot of HTTP headers for API requests, but not for static requests, it is better to divide them by different domains.

CDN (Content Delivery Network) will help speed up loading for geographically distributed clients.

Resource prioritization (preload, prefetch, preconnect) is a page loading speed-up due to the correct resource loading strategy. Browsers allow you to set priorities for different types of resources and to load earlier what is important for the first rendering.

Static compression: GZIP and Brotli. Brotli is a compression algorithm that will reduce the weight of static and thus increase loading speed. And here’s a great solution from my colleague.

Webp vs Png & Jpg. Webp is a great alternative to Png. In addition to the lower weight of images, Webp is not inferior in quality. Now this format supports about 78% of browsers. But even if you need 100% support, you can implement flyback on Png using the tag picture.

Runtime

Tasks, Microtasks. With proper prioritization of code deploying, you can get rid of “friezes” and speed up response to user input.

requestIdleCallback is a useful feature that allows code to be deployed in your spare time at the end of a frame (frame/tick) or when the user is inactive. It will help to get rid of all the same lags and “friezes”.

requestAnimationFrame allows you to schedule your animation correctly and maximize your chances of rendering 60 frames per second.

ES2015 vs ES5. The ES2015 provides many features that are more powerful than ES5.

DOM manipulation. DOM manipulations are expensive and need to be done carefully and sensibly. For example, do not call querySelector() in a loop if you can do it with one call.

Render blocking resource. Loading some resources may block rendering. To avoid this, you should use attributes defer, async, preload.

60 FPS by pointer-events: none is a great hack that can be used to achieve 60 FPS when scrolling a page. It works very simply: all mouse event handlers are disabled while scrolling.

Passive event listener is a way to make smooth page scrolling on touch screens. In short, the browser has an imperfect flow of event handlers for touch events. If you set the passive parameter when creating the event handler, the browser will clearly understand that the handler will not cancel scrolling and render without waiting for its completion.

Virtual scroll is a smart way not to render large lists, but to generate them while scrolling. It consumes less memory and makes scrolling lists easier.

Avoid large Complex Layouts and Layout Thrashing. Layout/reflow are expensive operations that perform many recalculations of rendering parameters. To avoid calling them frequently, you need to build the layout and manipulate DOM correctly.

What forces layout/reflow is a cheat sheet where you can find a list of functions and parameters that layout/reflow calls on.

Building

Tree shaking — remove unused code from the bandit and speed up page loading.

Code splitting — by splitting the code into chunks, you can optimize the first download and open the possibility to download parts of the code “lazy”.

Obfuscation can reduce the size of the bandit and even a little help to hide your code from other people’s eyes.

Architecture

Server side rendering is probably the best known way to make sure that the SPA is rendered immediately on first boot. This is an important requirement for some search engines (and not only).

Lazy loading images and video (+native) — a native solution designed to improve the metrics of the first rendering by “lazy” loading images and video.

Lazy loading modules/routes — a tool that is available in all popular frameworks and libraries. It allows “lazy” loading of pieces of application functionality.

Caching files with Service workers allows you to cache the files in your browser and not to download them every time from the server. Perhaps the only way to make offline mode in a browser application.

HTTP Caching — with the help of some HTTP headers you can greatly improve the speed of page loading and reduce the load on the server.