The background is a page in a project. After real data is connected to the page, the loading time takes about 10 seconds, which seriously affects user experience.

Trying to reason

In Chrome’s DevTools, a clean cache is hard loaded to simulate a user’s first visit to a page. According to several indicators in Network, the performance bottleneck is preliminarily judged as follows:

  • requestsIn:HTTP / 1.0orHTTP / 1.1Connection,ChromeA maximum of six concurrent hosts are allowedTCPConnection, so too many requests can causeTTFBThe waiting time is too long.
  • xhr:ajaxThe interface takes too long, and the bottleneck is the back-end interface. Procedure
  • Finish:FinishTime is far greater thanDOMContentLoadedandLoadTime indicates that the request resources on the page are large

To optimize the direction

  1. The bottleneck of too many requests is simply to reduce the number of requests. From top to bottom, the client (browser) page should reduce the number of requests, put the resources not visible on the first screen after the first screen, and preload or lazily load some requests blocking page rendering; usingHTTP 2Multiplexing feature, merge request; Server rendering.
  2. ajaxNodejs (BFF layer) is based on the capability of microservices. Therefore, it is necessary to speed up service invocation, reduce the number of service invocation, and optimize the service (caching, batch interface, asynchronous request for non-essential data…). Of course, the efficiency of their own code layer should also be considered.
  3. To solve the problem of too many requests for resources, img images can be optimized for lazy loading (as will be mentioned below). When big data is stuffed into the array object to traverse the rendering, lazy loading of invisible components can save performance and page rendering time. Compressed image formats, such as WebP;

Comparison of PNG original image, PNG lossless compression, PNG to WebP (lossless), PNG to WebP (lossy) compression renderings

  1. From a user experience perspective,loadingAnimation, images, progressive rendering (browser load order for an image is basically show as many downloaded, and let the user feel very rigid curt, progressive rendering is the process of image content from fuzzy to clear), preload (prescient load some invisible regional resources, improve the user experience in fast scrolling when the browser).

Lazy loading practice application

In the above optimization direction, the author optimized the API interface time of Nodejs layer, cached part of the business logic, and stripped part of the underlying interface to make it asynchronous acquisition. At the same time, the lazy loading optimization direction is selected to optimize the loading of front-end components and picture resources. The optimization result is visible to the naked eye.

Lazy loading is not a new term. As the name suggests, it means lazy, not loading now, loading later, in other words, loading on demand. In many scenarios, resources that are temporarily invisible and not needed do not need to be loaded at the same time, which wastes time and consumes unnecessary CPU, IO and other resources. For example, lazy loading of images has been very popular in the era of jQuery. After the emergence of front-end MV* frameworks such as React and Vue, lazy loading of components, lazy loading of routes in SPA single-page applications, lazy loading of code blocks that do not need to be initialized in Webpack is implemented to optimize performance. The following author focuses on the lazy loading of pictures and VUE components.

Lazy loading of images

For some video image Web applications, image lazy loading is almost a must, which can greatly improve the user experience.

The principle of analytic

  1. Will require lazy loadingimgOf the labelsrcSet thumbnail or no thumbnailsrc, the placeholder map can be the default map, loading map;
  2. Check whether the IMG tag is in the viewable area of the browser. If so, set the real image URL to the SRC attribute of the IMG tag.
  3. The user scrolls the browser to traverse the labels that need to be loaded lazily. Check and perform step 2.

Determines whether the element is in the browser viewable area

The author thinks this is the most important part of lazy loading

getBoundingClientRect

Defined in the MDN: Element getBoundingClientRect () method returns the Element size and its position relative to the viewport.

// Get the element's getBoundingClientRect property
const rect = Element.getBoundingClientRect();

if(rect.top < document.documentElement.clientHeight) {
    // Compare the top value with the clientHeight of the page, or less than the visible area. }Copy the code

PS: This solution needs to listen for scroll events and pay attention to throttling.

Intersection Observer

The IntersectionObserver interface (subsumed from the IntersectionObserver API) provides a way to asynchronously observe the intersecting status of a target element with its ancestor element or top-level document viewport. The Intersection Observer API allows you to configure a callback function that is executed whenever a target element intersects a device view or other specified element. The device window or any other element is called the root element or root.


var options = {
    root: document.querySelector('#scrollArea'), 
    rootMargin: '0px'.threshold: 1.0 // The intersection ratio between the target element and the root element is 0.0 and 1.0
}

var observer = new IntersectionObserver(() = > {
    // A callback function that is triggered when the target element crosses the root element. }, options);var target = document.querySelector('#listItem');
// Add the target element for cross-state comparison with the root element
observer.observe(target);
Copy the code

PS: The advantage of this scheme over the former is that there is no need to listen, in fact, compatibility in Chrome is good.

Vue components load lazily

Here the lazy loading judgment basis is similar to the picture, the same is to determine the visibility or visibility of the time, to control the loading of components. When the load condition is false, do not render, when true, render, this can be done with the V-if directive.

At the same time of the condition switch, it is best to add a page similar to the skeleton screen to transition the user experience.

The project practice

Vue – LazyLoad, star 5.7K, recent updates is 2 months ago

The introduction of

NPM I vue-lazyload -s Import VueLazyload from 'vue-lazyLoad' vue. use(VueLazyload, {lazyComponent: true}); import VueLazyload from 'vue-lazyLoad' vue. use(VueLazyload, {lazyComponent: true});Copy the code

This.$slots.default (L11-L16); this.$slots.default (L11-L16);

render (h) {
   if (this.show === false) {
        return h(this.tag)
   }
   return h(this.tag, null, this.$slots.default)
}
Copy the code

Application components

/ / the original code
<div class="camera-card-img" :style="{'backgroundImage': 'url(' + data._thumbnails + ')'}">

// Add image lazy loading logic
<div class="camera-card-img" v-lazy:background-image="data._thumbnails">

<lazy-component>// Components that need lazy loading...</lazy-component>
Copy the code

The optimization results

Call real data, control variables, before optimization:

52 requests, 19 img

Add image lazy loading:

38 requests, 12 img

When the browser continues to scroll, the images are loaded one by one. It can be seen that the request in the network increases to 52, indicating that the remaining images are loaded.

Lazy loading of components is also the same effect, the data volume is small, the page finish time perception is not obvious, can increase the simulation amount to thousands:

Finish 10 seconds,

The Finish time is 4s and the speed is significantly improved.

PS: The reason why the number of requests remains unchanged is that the author repeated real data several times in the simulation of data, resulting in the same resource address. The browser will cache requests, so the number of requests remains unchanged.

The follow-up plan

In fact, it can be seen that when there is a large amount of data, the loading speed is still very slow. It still needs to be optimized in the following directions:

  • Thumbnail format (compressed resource size)
  • Optimize WebPack packaging to load components on demand from the code block level
  • Lazy loading is still “not lazy enough”
  • Resolve requests seen in flame diagrams that take a long time and block page rendering

conclusion

Optimization is endless, and often takes a lot of effort to achieve little. Time and resource costs should be considered and optimization directions with high input-output ratio should be prioritized. The above is the author in the actual project encountered optimization problems, only for your reference.