preface

The sun and the wind: I’m smiling and grabbing my cool IKBC keyboard and frantically typing bugs. Bolt from the blue: was pulled into a group, the product said my website is very slow, need to do performance optimization. Unbelievable: I developed it with the venerable Vue3+Ts (manual dog head). Very resistant: Yin Wei forced me to do a physical examination and surgery for the website.

A medical

There are many kinds of physical examination packages on the market, but in fact, they are all the same. What is it? We will explain below. I chose LightHouse, Google’s own son, for my performance checkup.

A medical standards

Why do I say that most medical check-ups are the same? Let’s start with the lighthouse scoring rules:

From the above we can see that lighthouse V6 / V7 is scored by several performance indicators and different weights. These indicators are defined according to the PerformanceTiming and PerformanceEntry API standards. Most physical examination packages on the market are also customized based on these indicators. Let’s see what these indicators mean.

FCP (First Contentful Paint)

Render the first element (text, image, Canvas…) The timing of the

SI (Speed Index)

First screen display time

LCP (Largest Contentful Paint)

The point in time at which the largest content element in the visual area is rendered

TTI (Time to Interactive)

The page resource loads successfully and responds to the user interaction point in time

TBT (Total Blocking Time)

Total time between FCP and TTI that the main thread was blocked by a long task(over 50ms)

CLS (Cumulative Layout Shift)

Accumulates the layout offset

FID (First Input Delay)

The first time a user interacts with a page (clicking a link, button, custom JS event), the browser actually starts processing the event

Core Web Vitals

In May 2020,Google launched a set of Core Web Vitals for the experience of using websites. Consists of three indicators:

Why not something else? Because this set of standards is mainly evaluated from the following three dimensions:

  • [Loading status] : LCP
  • Interactivity: FID
  • [Visual stability] : CLS

How do I view Core Web Vitals metrics?

Developers can monitor Core Web Vitals with the following tools:

Because FID requires a real user interaction, it cannot be tested with experimental data. In order to test FID under experimental data, TBT (Total Blocking Time) is usually used. While they measure different things, improving TBT usually improves FID as well.

A medical results

I don’t know, I was surprised. Six “vital organs” are half cold… It’s time to operate on it!

Index score

Improvement Suggestions

surgery

Operation scheme

Since it is performance surgery, the plan mainly takes performance indicators as the dimension, which is mainly divided into the following points:

  • Cumulative Layout Shift visual Stability
  • Largest Contentful Paint
  • TTI (Time to Interactive)
  • TBT (Total Blocking Time)
  • FCP (First Contentful Paint)

The procedure

Cumulative Layout Shift visual Stability

  • Optimizes unsized image elements

A high priority optimization mentioned in the improvement recommendations is to set explicit widths and heights for image elements to reduce layout offsets and improve CLS.

<img src="hello.png" width="640" height="320" alt="Hello World" />
Copy the code
  • The custom font file remains visible during loading

The suggestion is to use the CSS font-display property to ensure that the custom font file is visible during load.

This is because it takes a while for a website to download a custom font file, and different browsers behave differently at this point. Some browsers hide Text when loading custom fonts, called Flash Of Invisible Text (FOIT). Some browsers, on the other hand, display a downgraded font, called FOUT(Flash Of Unstyled Tex). These two behaviors can cause “font flicker problems” and affect visual stability (CLS).

Font display:swap; This property ensures that the font is visible at load time. FOUT still causes it, but it has less effect on visual stability than FOIT.

A better solution would be to preload font files. Make it more likely that fonts will be downloaded before FCP, thus avoiding FOIT/FOUT.

@font-face {
     font-family: 'Hello-World';
     src: url('.. /font/Hello-World.otf') format('OpenType');
     /* swap: If the specified font is not available, the browser will use the alternate font first, and replace the alternate font */ when the configured font is loaded
     font-display:swap;
 }
Copy the code
  • Avoid page layout deviation

We have a dynamic element inserted at the top of our product that causes the overall layout of the site to move down. This results in large layout shifts. After dealing with the product and UI PY, we made friendly adjustments to this element. Remove the element from the document flow and present it in a fixed location. To solve the problem.

  • Avoid non-composited animations

The improvement recommendations mention avoiding non-composited animations, which clutter up the page and add CLS. As for this optimization suggestion, I think it should be analyzed on a case-by-case basis, instead of “giving up eating for fear of choking “. After all, the only CSS properties that can be composited are Transform & Opacity. Of course, this is also a reminder that we should optimize our CSS animations (e.g. transform instead of top).

Largest Contentful Paint

  • Replaces the largest content drawing element

In my suggestions for improvement, I found that the largest content drawing element on the site was a block element in Google Maps. It is no wonder that the LCP data is not good, the reason: the link is too long – download Google Maps Js SDK => initialize Google Maps => Draw.

I decided to change the maximum content draw element to improve the LCP time. The Largest Contentful Paint API defines the element type, locking the “target” to a loading element (low drawing cost: default rendering, no conditions or judgments). After I changed the size of the element, the element succeeded.

TBT (Total Blocking Time) / TTI (Time to Interactive)

  • The Original Google Maps Js SDK was loaded synchronously by dynamically adding a script tag. The downside is obvious:

    • The Google Maps Js SDK loads late, affecting TTI performance and user experience.
    • The JS engine occupies the main thread for related JS execution.

    My solution is to load the Google Maps Js SDK asynchronously. One thing to note here is the difference between script async/defer, which I used to load asynchronously (the async executes immediately after loading, blocking the main thread and affecting DOM parsing).

    <script
          src="//maps.googleapis.com/maps/api/js"
          type="text/javascript"
          defer
    ></script>
    Copy the code
  • Optimize build bundle volume

Looking at the volume analysis reports generated based on Webpack-Bundle-Analyzer, I found two large products that could be optimized:

    • Lottie animation library

    The site has only one animation implementation using the library, and after a lot of work with the product and UI, we decided to sacrifice a bit of “visuals “. Remove Lottie Library and use CSS3 implementation instead.

    • Ant – Design-Vue builds in Momentjs dependencies

    Momentjs’ language pack (locale) is quite large and the site has no need for internationalization. So here I just use WebPack IgnorePlugin to ignore the language pack.

    After optimization, the bundle size (before GIzp) was reduced from 1.8MB to 1.3MB.

FCP (First Contentful Paint)

The site uses client rendering done by Vue. This also means that the FCP process can be a bit “lengthy” (initializing the Vue instance, etc.). Here I “smartly” added a “transparent text placeholder” to the HTML file to preempt FCP time. I personally think this is a bit clever, you can choose to ignore…

<div id="app">
   <! -- placeholder -->
   <p style="color:#fff;">Hello World</p>
</div>
Copy the code

other

In addition to optimizing the above several index dimensions, I also made several optimization, which are briefly mentioned here:

  • Optimize the DOM nesting level and number
  • Reduce unnecessary interface requests
  • Use translate instead of top to move/animate

Surgical results

With all that nonsense, how did the surgery turn out? Is it a transformation or a “reverse one Q day immortal”? Directly above:

As you can see from the chart above, all the indicators and ratings have taken a qualitative leap, even though I “ungraciously cut off the highest score” (LightHouse’s score fluctuates every time, and the actual effect of it rises from 50-70 to 70-90)!!

conclusion

The performance optimization points that we talk about are also the ones that are most easily overlooked. Performance optimization doesn’t happen overnight, and it needs to be discovered and optimized on a daily basis. There is a long way to go…

If you think my article is helpful to you, welcome to follow me and play together ~