Every experienced developer knows how important it is to maintain application performance and what a pain it is. When it comes to uploading, the difference between a successful business and a disaster is only a few seconds. As such, the developer is responsible for ensuring that the app provides a better user experience, higher conversion rates, and ultimately more satisfied customers.
>16 milliseconds
JavaScript executes tasks using an event loop. The idea is simple: there is an infinite loop that waits for a job to complete, executes it, and returns to the waiting state until a new job arrives.
The work that the event loop does consists of discrete tasks (such as running a loaded script or moving the mouse), microtasks, and rendering changes, which we'll briefly discuss below. Rendering doesn't happen while some other task is running. Therefore, for a full user experience, it is vital that everything in the event loop goes on in a timely manner.
Rendering time is primarily affected by device features, such as the screen refresh rate, power saving mode, or browser settings. While browsers go out of their way to show something to the user as quickly as possible, most modern monitors support a refresh rate of 60 frames per second. This leaves us only 16 milliseconds to complete the task that needs to be rendered, so as not to disappoint the user with frame losses.
Most JavaScript tasks are simple enough to be completed in such a short time. But modern web applications are becoming more complex every day, turning the client side into an extravaganza with an abundance of functions and calculations that far exceed our threshold of 16 milliseconds.
Processing large amounts of data
Calculating a large amount of data can quickly exceed all possible limits and block the event loop. Especially if we try to do everything in one thread. In this case, the browser will not be able to display anything until our hard work with the data is completed. As you can see, this does not ensure optimal user interaction.
Solution
Break the calculation into smaller parts using setTimeout.
The second option is to use web workers. They run scripts in the background so that they do not block tasks in the main thread, giving the browser the opportunity to show the image as soon as possible.
Excessive use of third-party libraries
Optimization is far from universal among third-party libraries, even the most popular ones. Take, for example, bcrypt, which hashes a string with 13 rounds of hashing. Each round takes about two seconds, blocking the main thread for quite a long time and stopping other connections from running.
While this isn't a problem with 16 milliseconds, since it's an internal process that doesn't directly affect rendering, encryption is a great example of how unoptimized libraries can wreak havoc on your application.
Solution
The best solution here is to choose optimized libraries. Try to find libraries specifically designed for Node.js, because they use C++ bindings that allow you to parallelize threads and perform calculations up to three times faster.
Layout
This is a typical performance issue, especially for SPA applications that create and destroy content on the fly. Layout is a step in the rendering queue, when your browser determines where each page element should be displayed, evaluates its size and its relation to other objects.
Not surprisingly, the more DOM objects there are on the page, the longer the process takes. However, the most difficult part is that even the least significant style change invalidates the previous calculations and triggers an entirely new Layout step.
Solution
You should be very careful about organizing the measurement (read) and update (write) tasks element styles. I recommend grouping these processes so that you don't force layout to restart multiple times. In a large project, this may take some time, but you will be surprised how useful it will be.
Large builds
Big scripts are big problems. Executing JavaScript files consumes the maximum page load time. This can take even longer than rendering an image, because the latter represents a basic set of pixels on the screen, while the former triggers a whole chain of events, including parsing and executing the script, creating scopes, and so on.
Therefore, optimizing JavaScript files is an important part of improving your app's performance. Use the Webpack Bundle Analyzer to see the size of the output files and what they consist of.
Solution
Solution 1. For React, the best solution is to use deferred loading. React. lazy allows you to use dynamic import, which knows how to split code into parts, instead of including the entire code in a single file.
Solution 2. If you can't reduce the size of the files, try caching them so that they don't get reloaded every time the app needs them. There are 4 headers for caching files:
- ETag-an identifier that allows the web server to avoid sending a full response again if the content has not changed;
- Cache-Control-contains instructions that you can use to manage your cache;
- Expires-shows the cache lifetime;
- Last-Modified-contains the date and time when the file was last modified.
Solution 3. Compress the file. Although most browsers support the Gzip and Brotli compression formats, I recommend using the latter, as it is more efficient.
When it comes to making the interface work effectively, improving JavaScript performance is key. In this article, I have addressed only a few important issues that you may encounter. What are some valuable tips for improving JavaScript performance?
Top comments (0)