Front-end Performance Optimization Solutions

Front-end resources are quite extensive, including HTML, CSS, JavaScript, Image, Flash, Media, Font, Doc, and so on. Front-end optimization is relatively complex, with different ways to optimize various resources. It can be roughly divided into two categories based on granularity. The first category is page-level optimization, such as reducing the number of HTTP requests, non-blocking loading of scripts, and optimizing the position of inline scripts. The second category is code-level optimization, such as optimizing DOM operations in JavaScript, image optimization, and HTML structure optimization. From the user's perspective, front-end optimization can make the page load faster and respond more timely to user actions, providing a more user-friendly experience. From the service provider's perspective, front-end optimization can reduce the number of page requests, reduce the bandwidth occupied by requests, and save server resources.

Reducing HTTP Requests

Most of the time spent on loading front-end resources is in downloading various resources. The browser also has a limited number of HTTP request connection pools for the same server. Excessive requests need to be queued, minimizing HTTP requests and reducing the number of requests can prevent the HTTP connection pool from being filled up, and also avoid the time consumption caused by excessive TCP handshakes when there are too many HTTP connections.

CSS Sprite

CSS Sprite, also known as a sprite image, combines multiple images into one image, which can reduce the number of images. In addition, since the merged image reduces the storage information overhead such as color tables and format information compared to separate images, the size of the merged image tends to be smaller than the sum of the sizes of the separate images. Of course, if there is a large amount of whitespace used to separate the original individual images when merging, the size may tend to be larger. To use a sprite image, you need to use the background-image and background-position properties of CSS to display the desired image segment.

Image maps

If a website has many images with links, such as a map application, image maps are a good choice. Image maps allow multiple images with links to be placed on a single image. By using <map> and <area>, a complete image can be divided into multiple areas to create different links. Similarly, this can also reduce the number of HTTP request links for images.

Inline images

By using the data:URL scheme to directly embed image data into a page or CSS, although this increases the size of the document or CSS file, it is indeed a solution to reduce the number of HTTP requests. The format of data:URL is data:[<mediatype>][;base64],<data>.

Font icon

Using font icons instead of images, combining multiple icons into font icons can not only reduce the number of HTTP requests for images and the size of icons, but also, as vector graphics, they will not lose quality when zooming in or out. In addition, font icons have the advantage of being easy to change colors, create shadows, transparency effects, etc. They are well supported by CSS, making it possible to create various styles, rotations, and animation effects.

Combined files

Combining multiple CSS files or JavaScript files into one CSS file or JavaScript file can effectively reduce the number of HTTP requests and reduce the file size through compression algorithms. When scripts and stylesheets change between pages, combined files may become difficult to read and modify, but including them as part of the publishing process can shorten response time.

Utilizing Caching Mechanism

Cache Control

By setting the Expires and Cache-Control response headers on the server side, the expiration time and expiration strategy of resource components can be set. For static resources, setting Expires to a long-term time can achieve a never-expiring strategy. For dynamic components, Cache-Control can be used to specify caching mechanisms to assist browsers in handling conditional requests.

External References

By setting JavaScript and CSS as external files to be imported instead of directly embedding them in HTML, the browser's caching mechanism allows the external files to be imported through the browser's cache without the need to repeatedly request the same resource file. This makes the browser much faster when opening the page for the second time. However, using external file references increases the number of HTTP requests, so the key issue with external references is how to balance the number of cached external JavaScript and CSS files relative to the number of HTML documents. Although it is difficult to quantify, various metrics can be used to measure this factor. If users on the website have multiple page views per session and many pages reuse the same scripts and stylesheets, caching external files can bring greater potential benefits.

Optimizing Resource Loading

Stylesheet Placement

According to the order of browser rendering, importing or embedding CSS in the <head> section of the HTML can speed up page rendering compared to placing the CSS in the <body> or at the bottom of the page. This is particularly important for websites with rich content or slow network connections. Placing the stylesheet at the bottom would cause the browser to start rendering the page before the stylesheet is loaded, resulting in an immediate transition from a style-less state to a styled state, which leads to a poor user experience. Additionally, some browsers may delay rendering the page until the CSS is downloaded, so placing the stylesheet at the bottom would delay page rendering.

Script Placement

Browsers can make concurrent requests, which allows them to load resources faster. However, when external JavaScript scripts are being loaded, they block other resources. For example, until the script is loaded, any images, styles, or other scripts that come after it are blocked. One reason for this is that JavaScript can modify the page or change the dependencies between scripts. For example, if A.js changes the page using document.write, and B.js depends on A.js, the order of loading must be strictly maintained and parallel downloading is not possible. Placing the script too high in the page would affect the overall loading speed and user experience. Additionally, when the browser encounters a JavaScript script, it immediately starts parsing the script and stops parsing the document, as the script may modify the DOM and CSS, continuing to parse would waste resources. There are many ways to solve these problems, such as asynchronous loading of scripts. However, the simplest and most reliable method is to move the script as far down as possible to minimize the impact on concurrent downloading and page rendering.

Code Optimization Solutions

Avoid CSS Expressions

CSS expressions use the expression method to accept JavaScript expressions, which is a powerful way to dynamically set CSS properties. However, it is also a very dangerous method. The problem with CSS expressions is that they are frequently calculated. The frequency of CSS calculations far exceeds our imagination. Calculations are not only performed when the page is displayed or scaled, but also when the page is scrolled or the mouse is moved, which affects the performance of the page. Instead of using CSS expressions, you can use JavaScript to calculate the properties once and assign them to the style properties, which is a one-time expression. If it is necessary to dynamically set style properties throughout the entire lifecycle of the page, event handlers can be used instead of CSS expressions. If CSS expressions must be used, it is important to note that they may be calculated thousands of times and are likely to affect the performance of the page.

Avoid Redirects

Try to avoid using redirects as much as possible. When a page is redirected, it delays the transmission of the entire HTML document. Nothing will be rendered in the page until the HTML document arrives, and no components will be downloaded, which reduces the user experience. If redirects must be used, such as redirecting from http to https, use a 301 permanent redirect instead of a 302 temporary redirect. If a 302 redirect is used, every time http is accessed, it will be redirected to the https page, whereas with a permanent redirect, once the redirect from http to https occurs, the browser will remember it, and each time http is accessed, the https page will be returned directly.

Minimize DOM Manipulation

Manipulating the DOM with JavaScript inevitably triggers browser repaints or reflows. Repaints and reflows can be expensive, so it is best to minimize their occurrence. To reduce the number of repaints and reflows, multiple modifications to the DOM and styles can be combined and processed together, or the styles can be designed in advance and the class can be dynamically changed. Another approach is to use an offline DOM modification solution, using the documentFragment object to manipulate the DOM in memory. Modifying the DOM in memory allows the elements to be removed from the document flow, which does not trigger repaints. All modifications to the DOM can be completed in batches, and then the nodes can be placed back into the document flow, triggering only one reflow.

Compressing Resource Files

Gzip

Starting from HTTP/1.1, clients can indicate support for compression by using Accept-Encoding: gzip, deflate in the HTTP request. If the server sees this header in the request, it can compress the response using one of the methods listed by the client, and notify the client to use gzip compression through Content-Encoding: gzip in the response. Gzip has a high compression ratio and is currently the most popular and efficient compression method. It was developed by the GNU project and standardized by RFC 1952.

Compressing External Files

Compress JavaScript and CSS files by removing unnecessary characters from the code to reduce their size, thereby shortening the loading time. When the code is minimized, all comments and unnecessary white spaces will be removed. By reducing the size of the downloaded files, response time performance can be improved.

Optimizing Network Requests

CDN

CDN stands for Content Delivery Network. It is an intelligent virtual network built on top of the existing network infrastructure. By relying on edge servers deployed in various locations and functional modules such as load balancing, content distribution, and scheduling on the central platform, CDN enables users to obtain the required content nearby, reducing network congestion and improving user access response speed and hit rate. When users are in multiple locations across regions, the perception of server response speed varies. Most of the time, users access websites in the state of downloading static resources. By distributing these static resources to CDN servers first, response time can be greatly reduced. CDN can select the server with the fewest network hops or the fastest response time based on user network status information to deliver resources to users nearby.

DNS Prefetching

When a browser accesses a domain name, it needs to resolve the DNS once to obtain the corresponding IP address. In the resolution process, it reads the cache step by step according to the order of browser cache, system cache, router cache, ISP DNS cache, root domain name server, top-level domain name server, and primary domain name server, until it obtains the IP address. DNS prefetching is to pre-resolve domain names that may be used in the future according to the rules defined by the browser, and cache the resolution results in the system cache to shorten the DNS resolution time and improve website access speed.

<link rel="dns-prefetch" href="https://www.google.com">
<link rel="dns-prefetch" href="https://www.google-analytics.com">

By prefetching DNS, it is parallel and does not block page rendering, which can shorten the time for resource loading.

Configure ETag

Entity tag (ETag) is a mechanism used by web servers and browsers to determine whether the resource in the browser cache matches the resource on the original server. Adding ETag provides a more flexible mechanism for validating entities than the last modification date. ETag is a string that uniquely identifies a specific version of a component, and the only format restriction is that it must be enclosed in quotation marks. The original server uses the ETag response header to specify the ETag of the component.

Early Release of Buffers

When a user requests a page, the backend server may take 200 to 500 milliseconds to concatenate the HTML page. During this time, the browser is idle while waiting for the data to arrive. This time can be used to send the partially processed data from the server to the frontend, so that the browser can start loading external resources first while the backend is busy processing the rest of the HTML page. For example, when using PHP, the function flush() can be used to send the partially ready HTML response to the browser, so that the browser can start fetching resources while the backend is busy processing the remaining parts of the HTML page. This is particularly beneficial for busy backends or lightweight frontends.

Daily Question

https://github.com/WindrunnerMax/EveryDay

References

https://www.jianshu.com/p/fbd1d510be67 https://www.cnblogs.com/coober/p/8078847.html https://www.cnblogs.com/psxiao/p/11552823.html https://www.cnblogs.com/xiaohuochai/p/9178390.html https://developer.yahoo.com/performance/rules.html