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.
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
, 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.
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.
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>
.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
By prefetching DNS, it is parallel and does not block page rendering, which can shorten the time for resource loading.
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.
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.