JavaScript performance optimization
It is very important to consider how you are using JavaScript on your websites and think about how to mitigate any performance issues that it might be causing. While images and video account for over 70% of the bytes downloaded for the average website, byte per byte, JavaScript has a greater potential for negative performance impact — it can significantly impact download times, rendering performance, and CPU and battery usage. This article introduces tips and techniques for optimizing JavaScript to enhance the performance of your website.
Prerequisites: | Basic software installed, and basic knowledge ofclient-side web technologies. |
---|---|
Objectives: | To learn about the effects of JavaScript on web performance and how to mitigate or fix related issues. |
To optimize or not to optimize
The first question you should answer before starting to optimize your code is "what do I need to optimize?". Some of the tips and techniques discussed below are good practices that will benefit just about any web project, whereas some are only needed in certain situations. Trying to apply all these techniques everywhere is probably unnecessary, and may be a waste of your time. You should figure out what performance optimizations are actually needed in each project.
To do this, you need tomeasure the performance of your site. As the previous link shows, there are several different ways to measure performance, some involving sophisticatedperformance APIs. The best way to get started however, is to learn how to use tools such as built-in browsernetwork andperformance tools, to see what parts of the page load are taking a long time and need optimizing.
Optimizing JavaScript downloads
The most performant, least blocking JavaScript you can use is JavaScript that you don't use at all. You should use as little JavaScript as possible. Some tips to bear in mind:
- You don't always need a framework: You might be familiar with using aJavaScript framework. If you are experienced and confident with using this framework, and like all of the tooling it provides, then it might be your go-to tool for building most projects. However, frameworks are JavaScript-heavy. If you are creating a fairly static experience with few JavaScript requirements, you probably don't need that framework. You might be able to implement what you need using a few lines of standard JavaScript.
- Consider a simpler solution: You might have a flashy, interesting solution to implement, but consider whether your users will appreciate it. Would they prefer something simpler?
- Remove unused code: This may sound obvious, but it is surprising how many developers forget to clean up unused functionality that was added during the development process. You need to be careful and deliberate about what is added and removed. All script gets parsed, whether it is used or not; therefore, a quick win to speed up downloads would be to get rid of any functionality not being used. Consider also that often you will only use a small amount of the functionality available in a framework. Is it possible to create a custom build of the framework that only contains the part that you need?
- Consider built-in browser features: It might be that you can use a feature the browser already has, rather than creating your own via JavaScript. For example:
- Usebuilt-in client-side form validation.
- Use the browser's own
<video>
player. - UseCSS animations instead of a JavaScript animation library (see alsoHandling animations).
You should also split your JavaScript into multiple files representing critical and non-critical parts.JavaScript modules allow you to do this more efficiently than just using separate external JavaScript files.
Then you can optimize these smaller files.Minification reduces the number of characters in your file, thereby reducing the number of bytes or weight of your JavaScript.Gzipping compresses the file further and should be used even if you don't minify your code.Brotli is similar to Gzip, but generally outperforms Gzip compression.
You can split and optimize your code manually, but often a module bundler likewebpack will do a better job of this.
Handling parsing and execution
Before looking at the tips contained in this section, it is important to talk aboutwhere in the process of browser page rendering JavaScript is handled. When a web page is loaded:
- The HTML is generally parsed first, in the order in which it appears on the page.
- Whenever CSS is encountered, it is parsed to understand the styles that need to be applied to the page. During this time, linked assets such as images and web fonts start to be fetched.
- Whenever JavaScript is encountered, the browser parses, evaluates, and runs it against the page.
- Slightly later on, the browser works out how each HTML element should be styled, given the CSS applied to it.
- The styled result is then painted to the screen.
Note:This is a very simplified account of what happens, but it does give you an idea.
The key step here is Step 3. By default, JavaScript parsing and execution are render-blocking. This means that the browser blocks the parsing of any HTML that appears after the JavaScript is encountered, until the script has been handled. As a result, styling and painting are blocked too. This means that you need to think carefully not only about what you are downloading, but also about when and how that code is being executed.
The next few sections provide useful techniques for optimizing the parsing and execution of your JavaScript.
Loading critical assets as soon as possible
If a script is really important and you are concerned that it is affecting performance by not being loaded quickly enough, you can load it inside the<head>
of the document:
<head> ... <script src="main.js"></script> ...</head>
This works OK, but is render-blocking. A better strategy is to userel="preload"
to create a preloader for critical #"preload" href="important-js.js" as="script" /> <!-- Preload a JavaScript module --> <link rel="modulepreload" href="important-module.js" /> ...</head>
The preload<link>
fetches the JavaScript as soon as possible, without blocking rendering. You can then use it wherever you want in your page:
<!-- Include this wherever makes sense --><script src="important-js.js"></script>
or inside your script, in the case of a JavaScript module:
import { someFunction } from "important-module.js";
Note:Preloading does not guarantee that the script will be loaded by the time you include it, but it does mean that it will start being downloaded sooner. Render-blocking time will still be shortened, even if it is not completely removed.