Front-end performance optimization - summary of optimization methods and auxiliary tools

    Why do performance optimization? How important is performance optimization? The performance optimization of the website has a great impact on the retention rate and conversion rate of users, so the performance optimization ability is also an important inspection point for front-end development

    What is performance optimization

    In general, under the current B/S architecture, the front-end requests the back-end, the back-end organizes the data and returns it to the client, and then the client performs data processing and rendering to display the interface. Such a general process, and Front-end performance optimization is based on this process. There are only two major directions that we can optimize:

    One is faster network communication (that is, load-time optimization), which means that there is less time delay between the client and the server when requesting or responding

    The second is faster data processing (that is, runtime optimization), which means that after the server receives the request, it sorts out the data needed by the client faster; after the client receives the response data, it sorts out the data faster Faster processing when displaying and interacting with users


    Performance optimization while loading

    We know that if the browser enters a URL, it first needs to be handed over to DNS domain name resolution -> find the corresponding IP address -> then make a TCP connection -> browser sends HTTP request -> server receives request -> server processes the request and returns HTTP message -> and the browser receives and parses the rendered page. From this process, you can actually dig out optimization points and shorten the request time, thereby speeding up the website access speed and improving performance

    1. DNS pre-resolution

    Now most new browsers have been optimized for DNS resolution. A typical DNS resolution takes 20-120 milliseconds. Reducing the time and frequency of DNS resolution is a good optimization method.The browser's first domain name DNS resolution lookup process for the website is as follows:

    Browser cache -> system cache -> router cache -> ISP DNS cache -> recursive search

    Implementation of DNS pre-resolution:

    Use meta information to inform the browser that the current page needs to be DNS pre-analyzed:

    <meta http-equiv="x-dns-prefetch-control" content="on" />
    

    Use the link tag in the page header to force DNS pre-resolution:

    <link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
    

    Note:dns-prefetch should be used with caution. Repeated DNS pre-analysis on multiple pages will increase the number of repeated DNS queries.


    2. Use HTTP2

    HTTP2 brings a very large loading optimization, so when doing optimization, I first thought of replacing HTTP1 with HTTP2.HTTP2 has these advantages over HTTP1:

    Parsing speed is fast:
    When the server parses HTTP1.1 requests, it must continuously read in bytes until it encounters the delimiter CRLF. Parsing HTTP2 requests is not so troublesome, because HTTP2 is a frame-based protocol, and each frame has a field indicating the frame length. Multiplexing:
    On HTTP2, multiple requests can share a single TCP connection, this is called multiplexing.
    header compression:
    HTTP2 provides header compression
    server push:
    The server can actively push other resources when sending the page HTML, instead of waiting until the browser resolves to the corresponding location, initiates a request and then responds.


    3. Compress and merge files

    Compress files -> reduce HTTP request size, which can reduce request time
    File Merging -> Reduce the number of HTTP requests.
    We can compress html, css, js and image resources, and now we can easily use webpack to compress files:

    js compression: UglifyPlugin
    CSS compression: MiniCssExtractPlugin
    HTML compression: HtmlWebpackPlugin
    Image compression: image-webpack-loader
    

    extract common code

    Although merging files can reduce the number of HTTP requests, it does not mean that the more files are merged, the better. You can also consider the on-demand loading method (described in point 6 later). What kind of files can be merged? The common code used multiple times in the project can be extracted and packaged into a common module.

    You can use webpack4's splitChunk plugin cacheGroups option.

    optimization: {
           runtimeChunk: {
             name: 'manifest' // Split webpack's runtime code into a separate chunk.
         },
         splitChunks: {
             cacheGroups: {
                 vendor: {
                     name: 'chunk-vendors',
                     test: /[\\/]node_modules[\\/]/,
                     priority: -10,
                     chunks: 'initial'
                 },
                 common: {
                     name: 'chunk-common',
                     minChunks: 2,
                     priority: -20,
                     chunks: 'initial',
                     reuseExistingChunk: true
                 }
             },
         }
    },
    


    4. Use svg pictures or font icons

    Because the font icon or SVG is a vector diagram, written by code, it will not be distorted when zoomed in, and the rendering speed is fast. Font icons are used just like fonts, and properties can be set, such as font-size, color, etc. Another advantage is that the generated files are extremely small.


    5. Static resources use CDN

    The physical distance of the user from the server also has an impact on response time. Deploying content on multiple geographically dispersed servers can allow users to load pages faster. CDN is designed to solve this problem by deploying servers in multiple locations so that users are closer to the server, thereby shortening the request time.


    6. Load code on demand to reduce redundant code

    load on demand

    When developing a SPA project, there are often a dozen or more routing pages in the project. If these pages are packaged into one JS file, although the number of HTTP requests is reduced, the file will be relatively large and a large number of home pages will be loaded at the same time. Unnecessary code is not worth the loss. At this time, you can use on-demand loading to package each routing page separately into a file. Of course, not only routing can be loaded on demand.

    Generate a file name based on the file content, and dynamically introduce components in combination with import to achieve on-demand loading:

    This requirement can be achieved by configuring the filename property of output. There is a [contenthash] in the value option of the filename attribute, which will create a unique hash based on the file content. When the content of the file changes, [contenthash] also changes.

    output: {
        filename: '[name].[contenthash].js',
        chunkFilename: '[name].[contenthash].js',
        path: path.resolve(__dirname, '../dist'),
    },
    


    Reduce redundant code
    On the one hand, avoid unnecessary escaping: babel-loader uses include or excludeto help us avoid unnecessary translation, does not translate js files in node_moudules, and secondly caches currently translated js files, setting loader: 'babel-loader? cacheDirectory=true'

    Secondly, reduce the redundant code from ES6 to ES5: Babel converted code needs to use some helper functions if it wants to achieve the same function as the original code, such as:

    class Person {}
    

    would be converted to:

    "use strict";
    
    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
      }
    }
    
    var Person = function Person() {
      _classCallCheck(this, Person);
    };
    

    Install:

    npm i -D @babel/plugin-transform-runtime @babel/runtime use in .babelrc file

    "plugins": [
            "@babel/plugin-transform-runtime"
    ]
    


    7. server-side rendering

    Client-side rendering: get the HTML file, download the JavaScript file as needed, run the file, generate the DOM, and then render.

    Server-side rendering: the server returns an HTML file, and the client only needs to parse the HTML.

    Advantages: fast rendering of the first screen, good SEO. Disadvantages: The configuration is troublesome and increases the computing pressure on the server.


    8. image optimization

    Sprite Figure

    The core principle of the sprite map is to set different background offsets, which roughly includes two points:

    • Different icon elements will set the background-url to the uri of the merged sprite image;
    • Different icons display the corresponding icon part in the larger image by setting the corresponding background-position. You can make sprites yourself with tools like Photoshop. Of course, it is recommended to integrate the generation of sprite images into front-end automated construction tools, such as using webpack-spritesmith in webpack, or gulp.spritesmith in gulp. Both of them are based on the spritesmith library.

    Image lazy loading

    The implementation method is not to set the path for the picture first, and only set the real picture path when the picture appears in the visible area of the browser.
    When the page is not visible, the picture will not be loaded; by monitoring the page scrolling, set the picture src when the page is visible

    <img original-src="" />
    const img = document.querySelector('img')
    img.src = img.getAttribute("original-src")
    

    If you want to use lazy loading, you can also use some existing tool libraries, such as aFarkas/lazysizes, verlok/lazyload, tuupola/lazyload, etc.


    Runtime performance optimization

    1.Minimizing repaints and reflows

    repaints:
    Repaint refers to the browser behavior triggered by a change in the appearance of an element. The browser will redraw according to the new properties of the element, so that the element presents a new appearance. Since there is no change in the geometric properties of the DOM, the position information of the element does not need to be updated. , thus saving the layout process.


    reflow: When rendering a part (or all) of the tree due to the size of the element, the layout,Hiding and other changes requires rebuilding, which is called reflow. Each page requires at least one reflow, which iswhen the page first loads.
    The fundamental principle after rearrangement is that the geometric properties of elements change:

    • Add|remove visible DOM elements
    • The position of the element changes
    • The size of the element's own province changes
    • content changes
    • page renderer initialization
    • Browser window size changes


    How to reduce reflow and repaint?

    • Minimize repaints and reflows, such as style-focused changes, add new styles using classname.class or cssText
    • Batch DOM operations, such as reading the offsetwidth attribute of an element and storing it in a temporary variable, and then using it instead of frequently using this computed attribute; use document.createDocumentFragment() to add nodes, and then insert them into the actual DOM after processing middle
    • Use absolute or fixed to take elements out of document flow when making complex animations
    • Turn on GPU acceleration, use the css attributes transform, will-change, etc., to change the position of the element, we use translate to change its left, top, etc. more efficiently than using absolute positioning, because it will not trigger rearrangement or redrawing
    • Try to use requestAnimationFrame for js animation instead of timer


    2. Long List Optimization

    Sometimes there is a need to display a list containing hundreds of elements on the page (for example, a feed stream). Each list element also has a complex internal structure, which obviously increases the cost of page rendering. The problem of long lists is further magnified when you use React. So how to optimize long lists?

    1.1 Implementing a virtual list
    Virtual lists are a technique used to optimize long lists. It can ensure good scrolling and browsing performance when the list elements are continuously increasing, or there are many list elements. Its core idea is: only render list elements near the visible area. The left side of the figure below is the effect of the virtual list. You can see that only the elements in the viewport and the upper and lower areas adjacent to the viewport will be rendered.

    The specific implementation steps are as follows:

    • First determine the size of the parent element where the long list is located, the size of the parent element determines the width and height of the visible area
    • Determine the width and height of each list element in the long list, and calculate the position of each element in the long list relative to the parent element under the initial conditions, and use an array to save the position information of all list elements
    • When rendering for the first time, only display the child list elements relative to the visible area of the parent element. When scrolling, recalculate the child list elements that should be in the visible area according to the offset of the scrolling of the parent element.
    • Supplementary explanation, in this case, the parent element generally uses position: relative The positioning of the child element generally uses: position: absolute or sticky


    1.2 In addition to self-implementation, commonly used frameworks also have good open source implementations, such as:

    • React-virtualized based on React
    • vue-virtual-scroll-list based on Vue
    • Angular based ngx-virtual-scroller


    3. Scroll event performance optimization

    One of the scenarios where performance problems are most likely to be encountered by the front end is to listen to scrolling events and perform corresponding operations. Since scrolling events occur very frequently, frequent execution of monitoring callbacks can easily cause mutual blocking between JavaScript execution and page rendering.

    Corresponding to the scene of scrolling, anti-shake and throttling can be used to deal with it:
    The most complete and understandable principle, implementation and optimization of debounce and throttling


    4. Vue optimization

    1. Routing lazy loading components
    2. The keep-alive cache component keeps the original display state
    3. Add a key to the list item to ensure uniqueness
    4. List item binding event, using event delegation
    5. Object.freeze freezes the interface data object of the pure display class
    6. Using vue's server-side rendering (SSR)


    5. Packaging optimization (mainly webpack optimization)

    1. Unpack the externals dllPlugin
    2. Extract the common package commonChunkPlugin or splitChunks
    3. Narrow down the scope of various loader configuration include and exclude, noParse skip files
    4. Open the cache. Various loaders open the cache
    5. Multithreading to speed up happypack or thead-loader
    6. Tree-shaking ES module analysis, remove dead code
    7. Scope Hoisting ES6 module analysis, combining multiple modules into one function, reducing memory usage, reducing volume, and prompting running speed


    Auxiliary analysis tools for performance optimization

    The previous article introduced many performance optimization methods, but each project may have different optimization points, so the optimization mainly depends on your own project; what to optimize depends on the developer tools of the browser (Chrome as an example) Lighthouse and Performance

    Lighthouse is to generate performance analysis reports. You can see the data and ratings of each item and suggest points for optimization, such as where the picture is too large

    Performance is runtime data, you can see more detailed data. Such as blocking, rearrangement and redrawing, etc.

    Then, according to the situation reflected in these reports and performance indicators, we will continue to optimize our projects in a targeted manner


    Lighthouse

    Open directly in the Chrome developer tools or Node 12.x or above can be installed locally

    npm install -g lighthouse
    

    After installation, for example, to generate a blogger performance analysis report, one code is enough, and then an html file will be generated

    lighthouse https://blogger.com/
    

    As shown in the figure, the five items are:

    Performance: This is divided into three performance indicators, optimizeable items, and manual diagnosis

    Accessibility: Analysis of accessibility features. For example, there is not enough contrast between the foreground color and the background color, whether the picture has an alt attribute, whether the a link has a recognizable name, etc.

    Best Practices: Best practice strategies. For example, the aspect ratio of the picture is incorrect, whether there is an error message in the console, etc.

    SEO: Is there some stuff about search engine optimization without SEO

    PWA:The official word is to measure whether the site is fast, reliable and installable.

    According to the diagnostic information, we can do targeted optimization


    Performance

    It records performance data during the operation of the website. If we replay the entire page execution process, we can locate and diagnose the operation of the page in each time period

    Open Performance, check Memory, click Record on the left to start recording, then perform operations or refresh the page, and then click (Stop) to end recording and generate data

    Overview panel

    It contains page frame rate (FPS), white screen time, CPU resource consumption, network loading, V8 memory usage (heap), etc., displayed in chronological order.

    • If a red block appears on the FPS chart, it means that it takes too long to render a frame near the red block, which may cause a freeze

    • If the CPU graphic occupies too much area, it means that the CPU usage is high, it may be because a certain JS occupies too much time of the main thread and blocks other tasks from executing

    • If V8's memory usage keeps increasing, there may be a memory leak for some reason

    Click on the problematic place on the timeline, and then this piece of detailed content will be displayed in the performance panel


    Performance panel

    The performance panel will list many performance indicators, such as

    • Main indicator: is the task execution record of the rendering main thread
    • Timings indicators: record the data information of some key time points such as FP, FCP, LCP, etc.
    • Interactions metric: Records user interactions
    • Network indicator: is the time spent on each request of the page
    • Compositor indicator: is the task execution record of the synthetic thread
    • GPU indicator: is the task execution record of the main thread of the GPU process
    • Chrome_ChildIOThread indicator: It is the task execution record of the IO thread, which contains user input events, network events, device-related events, etc.
    • Frames indicator: record the time of each frame, layer structure and other information

    Popular posts from this blog

    大学资料分享——广工计院各个科目实验报告、课设及期末复习资料!!

    Win10 远程计算机或设备将不接受连接

    JAVA Traffic Signal Light Course Design (Source Code + Report + Video Demonstration)

    Implementation of Ajax Interceptor