This article will take a look at the actual process of optimizing a page using Performance. In general, Chrome Performance makes it easier to find problems in your code, and to locate, analyze, and optimize problems that might otherwise go unnoticed. Originally published on my blog

Rendering optimization

First of all, we analyze the whole detail page. The structure of the whole page is roughly as follows, mainly including three parts: basic information, visualization and timeline. The timeline contains detailed information about the timeline, including tables and several types of visualizations. As shown in the figure:

Let’s click Record to view the performance picture of the page:

Optimization point 1

As you can see, rendering the current page took nearly 1.2s, so let’s see what went wrong. Zooming in on the rendering, we see that most of the time spent rendering the timeline is spent displaying the details of each time node, but they are hidden by default. In other words, we did unnecessary render of N nodes, and we just had to kill them.

Looking at the code, we found that this was caused by the following location, and we performed an unwrapped box, something like this:

<Box data={data} border collapse loading={loading}>
  <AlertDetail />
</Box>Copy the code

In the unexpanded state, we still render the content, but hide it with styles, but React still renders and evaluates the virtual DOM. Here we modify it to render only when expanded and cache the rendered results as much as possible. Once the modifications are complete, Scripting has gone from 880+ms to 670ms, a reduction of about 200ms:

Optimization point 2

As we move on, the detail section of the page takes a lot of Evaluate Script time to initialize, mainly due to the categories to the right of the alarm details and the viewables and details under each category.

We might be thinking, why is it still taking so long to calculate when we didn’t render at initialization? Following up, I found out why:

In details the components, we including HTTP, TCP, all types of components for reference, and then according to the type of component matching, in various components may include the definition, classification and calculation of the corresponding to each type, and so on and so on, not only increase the loading time and more extended the initialization time, obviously we did is wrong.

Here, we can optimize it using lazy loading to show only graphs of its corresponding type, avoiding unnecessary waste of resources and computing time.

After the modification, we conducted the performance test again and found that when entering the page, the elapsed time of the detail component changed from 260ms to less than 2ms:

Scripting went from 670+ms to 415ms, a decrease of about 250ms:

At this point, the time to enter the page has changed from the initial 1.2s to 0.7s.

Update the optimization

When we click on the timeline to see details, we do several things. Close other enabled details, expand the current details, and display details of the corresponding type according to the current type, as mentioned above. This process involves the React update operation. Let’s optimize this process.

Optimization point 1

First we click the Record button, then click Expand and record it. We find the following results:

Click on the expand button and the Timeline component is rendered multiple times, which obviously shouldn’t be, so let’s take a look at what’s causing it. The timeline component uses connect to connect the timeline and alertList data, where alertList data is the alarm list corresponding to the specific category. Changes to both sets of data are mapped to component updates, such as timeline expansion and collapse, and alertList requests, successes and failures.

An alertList is supposed to correspond only to updates of the currently expanded content. Therefore, we have several modifications for this:

  1. References to alertList are deprecated in the timeline component to ensure that alertList is not implicated in overall updates to the timeline component
  2. Separate the timeline rendering from the detail rendering, pass the corresponding data to them, and control updates through the PureComponent
  3. Use shouldComponentUpdate for optimization

We use the first option here to avoid alertList’s impact on the entire component.

You can see that after clicking on details, there is only one major update to the entire timeLine, and details are only updated in the expanded component.

Optimization point 2

We see that when we expand at a point in time, the nodes of the entire list are updated, as shown in the figure below. Obviously, this performance cost is extremely large and unimportant. If the list is large, there is a good chance that the page will get jammed with updates.

Since all the other list nodes reference the alertList prop, all nodes are updated when it changes, so we need to manually optimize it with shouldComponentUpdate:

// When the switch state changes, the new render, ShouldComponentUpdate (nextProps, nextState) {const opened = _. Get (this.props, 'open') const willOpen = _.get(nextProps, 'open') if (opened === willOpen && ! WillOpen) {return false} else {// Similar to pureComponent shallow comparison return! _.isEqual(this.props, nextProps) || ! _.isEqual(this.state, nextState) } }Copy the code

After recording again, we found that as long as the current Item was updated, the update time of the whole Timeline was shortened to less than 40ms, greatly increasing the experience.

Other optimization procedures are similar and will not be described.

conclusion

Step by step optimization with the Performance tool, the rendering and update performance of the entire page has been greatly improved, and we also know the problems that need to be paid attention to in the process of writing code. Let’s summarize briefly:

  1. Avoid unnecessary rendering of non-presentation states
  2. If necessary, do lazy manual loading to avoid large modules marketing the page and loading unnecessary modules
  3. Ensure that the purity of the component props is displayed to avoid component updates due to changes in other props
  4. If necessary, use shouldComponent for manual optimization
  5. You can avoid unnecessary component updates by using PureComponent