23
头图

Introduction to Lighthouse

Lighthouse is a open source tool that can be used to improve the quality of web applications.

Lighthouse is now integrated into the new version of Chrome DevTools and can also be run as a Chrome extension or from the command line.

Lighthouse will run some automated tests against the web page, generate a report on the performance of the page, and then can optimize the page on the test report.

The Lighthouse test report contains five parts: performance, accessibility, best practices, SEO, PWA , today we are mainly to propose an optimization plan for the performance report and reproduce the code .

image.png

Chrome DevTools can adjust the language, for example, from English to Chinese.

Lighthouse Performance Metrics

  1. First Contentful Paint
    FCP refers to the first content rendering time of , which identifies the time the first text, image (images on the page, non-white <canvas> elements, and SVG are considered DOM content) are first rendered on the web page. FCP quantile map .
  2. Time to Interactive
    TTI refers to the interactive time , and identifies how long it takes for the web page to provide full interactive functionality . We know that the main thread of JS is single-threaded, and if there are long JS tasks, it will block page interaction
  3. Speed Index
    The speed index indicates how fast the content of the web page is visible to fill
  4. Total Blocking Time
    TBT refers to the accumulated blocking time of , which identifies the time between the first content rendering (FCP) of the web page and the interactive time
    Timeout tasks tasks that take longer than 50ms , if Lighthouse detects a 70ms long task, the blocking part will be 20ms.
  5. Largest Contentful Paint
    LCP refers to maximum content drawing , which identifies the time when the webpage renders the maximum text or picture. Similar to First Meaningful Paint (time when the main content is visible to the user) metric, but the LCP is a general fixed calculation rule .
  6. Cumulative Layout Shift
    CLS refers to cumulative layout offset , which identifies the movement of visible elements of web page within the viewport . calculation rule

    • Say you read an article online and something on the resulting page suddenly changes? The text shifts without warning, so you can't find where you read earlier.
    • Like you're about to click a link or a button, but the moment your finger drops, eh? The link is shifted, and it clicks to something else! Most of the time, these experiences are just annoying, but in some cases, they can be really disruptive (a point of deny turns into an allow).
    • Or think about perverted cats? It looks unremarkable, but when it is operated, disasters will fly.

image.png

LCP, FCP example

Image source: https://web.dev/lcp/#-2

image.png
image.png
image.png
image.png

Lighthouse Optimization Recommendations

Recommendation 1: Reduce unused JavaScript, CSS code

image.png

Means 1: Asynchronous. reload when needed

There are many nouns: lazy loading, lazy loading, idle loading, on-demand loading, etc.

  1. "Lazy loading" import asynchronous components

    1. For example, we have a message center module with client and management pages inside. Both pages should use async component . Because the destination is either sending or receiving , and the management side needs permission to see it.
    2. For example, our message module, supports markdown, rich text, docs, xlsx and other types , but a message can only display one type, so we can encapsulate DocsView and dynamically load component rendering.
  2. "Lazy loading" import asynchronous function

    1. For example, our table has export function, based on xlsx implementation. Such a function is not a high-frequency function , so we can also load and use it asynchronously through import.
  3. "Delayed loading" functions by manually adjusting the priority or delayer.
    needs to pay attention to the CLS indicator . Here, you need to be careful not to cause the CLS indicator to be abnormal.

    1. It is still an example of our message module. We do not load the latest news before LCP, and then load it after LCP. Here, the request for the first screen is reduced, and the impact on the user will be relatively small (only one red dot is displayed, and the user clicks on with or without a red dot to view the message list ).
    2. You need to be careful about switching modules such as following, likes, and favorites. Because the effect is the opposite, it was originally a concern, and the result may become a cancellation.

Means 2: Tree Shaking Optimization Tree-Shaking

Unused code logic can be removed at compile time.
Because Webpack 4 is enabled by default , so we only talk about some restrictions.

  • Only works for ES Module, invalid for commonjs, and also invalid for umd.
  • The package itself needs to support it.
  • Pay attention to configuring sideEffects to prevent Css from being optimized
  • It will be optimized when build is required. process.env.NODE_ENV === 'production' status

Method 3: babel reduces the adaptation version

Set a reasonable .browserslistrc to escape babel and babel-polyfill.
For example, if only the background system of Chrome is supported, there is no need to escape the IE series, which can greatly reduce the size.

Summary & Notes

  1. CSS optimization can also rely on asynchronous components.
  2. Third-party libraries can consider using components for secondary encapsulation.
  3. Correctly distinguish v-if and v-show, and study the implementation mechanism of el-tabs in depth. sure components are not actually instantiated
  4. You can check which code is not being executed through coverage in chrome-devtools.
    We can analyze which code is not executed, and the expected result is that every line of code loaded is useful.
    It can be seen that there is a resource that most of the code is not used, which is a waste. If bandwidth is pay-as-you-go, people will cry.
    image.png
  5. last 2 verions means the last two digits of all versions are supported. also includes IE which is never updated

Recommendation 2: Optimize size and eliminate duplicate code

Method 1: Compression

  1. The resource server starts Gzip compression and sets the resource 30D cache. Then update it by hashing the filename
  2. Generally speaking, CDN will support to compress and cache , and the bandwidth is relatively reliable, and the node is relatively close to the user.
  3. jsmin, tree shaking optimization and other programs.
  4. Pay attention to the picture type. Solid color image png, complex image jpg, webp smaller.
  5. Pay attention to the image size. Try not to be too large, pay attention to the cropping.

Means 2: Eliminate duplicate packets. dependency sharing

  1. lerna + yarn
    Common duplicate packages (axios, ui library), because many of our components are based on business encapsulation (what is business-based encapsulation? There is logic inside, there is automatic update of data calls, and the UI can be used directly in the business).
    We use lerna to do the same version sharing, we generally require the same version for .
  2. peerDependencies
    For some reason, some packages are not available in all projects, or have strong dependencies on versions. We also need to configure peerDependencies to so that the consumer can install the correct version of the dependency .
  3. externals
    The version number of some third-party libraries is 0.xx.x , because lerna is based on whether the first bit is not 0 to compare whether they are the same version. Causes axios@0.23 and axios@0.24 not to be considered the same version.
    At this time, we will use externals to force no packaging and let the user provide it.
  4. Unified build tools and versions
    Because sometimes we have some basic packages ( babel , babel-polyfill ), but the versions and methods used by each cli version are different, and the escape processing is also inconsistent. In order to use the smallest package size, we require the same version of cli webpack .

Method 3: Replace the package, choose a smaller version

  1. Replace large packages with small packages, and replace full packages with on-demand packages

    1. momentjs uses dayjs , momentjs package only uses format around 100k , and dayjs is only less than 10k .
      This is because the momentjs language pack is entered in i18n .
      So there is another solution, which is to change the language to be introduced on demand.
    2. Avoid import _ from 'lodash , use lodash-es instead.

Recommendation 3: Reduce reflow, reduce layout changes, and reduce the number of DOMs

It can be understood as the CLS indicator.

Method 1: Use a fixed width and height

image.png

Generally there is a fixed height ( 24*24 ), which we restrict to a range. To prevent all subsequent data changes after the image is loaded asynchronously and the dom is opened.

  1. For example, in an article page, if you remember the last browsing position. How to ensure that the user can still locate the last location? If you don't use a fixed width and height, there's a chance that what the user sees will always change.
  2. For example, on the WeChat chat page, how to always position it at the bottom of the page? When the image is loaded, the height changes.

Method 2: Virtualization, virtual list, tombstone mechanism, paging loading, lazy loading

The virtual list is similar to implementing a worst-case scenario, I only display 20, which is when my performance is the worst. No matter 100, 1000, I only show 20.

  1. For long lists such as select, table, tree, etc., pay attention to the use of virtual lists.

    1. For example, in WeChat chat, will you delete the conversation list on the left? It is estimated that there will be hundreds or thousands, including single chats, group chats, notifications, public accounts, and so on.
      How many nodes will there be? Avatar, name, message digest, time, blocked, unread, etc., even if there are 10 tags. 10 * 1000 has 10,000 tags, and if a virtual list is used, 10 * 50 has 500 tags.
    2. For example, if there are some tree nodes, there may be hundreds of thousands of nodes in the level coverage. If you operate logic such as selection
  2. Abnormal tooltip node.

    1. For example, components will be rendered ahead of time.
    2. For example, frequent changes will be made.

Recommendation 4: Reduce memory usage and CPU usage

Method 1: Image lazy loading

The picture will occupy the actual memory, causing the freeze.

  1. Pay attention to the image size. Try not to be too large, pay attention to the cropping.
  2. Load only the viewport image. Other pictures are loaded on demand, and the reference article page returns to the logical function of the last reading. If it is not required, the pictures will not be viewed.

Method 2: Reduce JS code, reduce CSS code

Just follow the logic above.

The code of is reduced, of course, it will be reduced when downloading, parsing, and executing .

It is recommended that you reduce the time spent parsing, compiling and executing JS. You may find that serving a small JS payload helps achieve this.

image.png

Recommendation 5: Reduce network load and speed up user downloads

What are the general restrictions on the download speed of resources?

  1. Bandwidth (throughput) 1M small water pipe
  2. Distance (near and far) in North China, global visit
  3. Media (Stable) Wired, Wireless, WiFi, 5G, 4G

Means 1: Increase the bandwidth

The problems that need to be paid to solve are not solved 🐶

If the server bandwidth is not enough, then the solution is to charge money.
If the user bandwidth is not enough, it can only be optimized.

Method 2: Go to CDN

The key technologies of CDN mainly include content storage and distribution technology which enables users network congestion, and improves user access response speed and hit rate.

Simply put, is close to the user, the bandwidth is large, and the network is smooth and not congested.

Method 3: Reduce the size

(same as suggestion 1 and suggestion 2)

Method 4: Increase the cache

image.png

Front-end projects generally do not cache html, and then resources are updated by hash name.

World class conundrum: how makes the cache expire and how does the cache not expire .

Recommendation 6: Shorten the execution time, shorten the execution link, and avoid blocking the main thread

Method 1: Reduce the main thread work and optimize the code execution speed

  1. Use loops correctly. should execute filter first, and then execute map .
    Because after the filter, the number will be reduced (random numbers, become half), the two examples are equal to 1.5 times and 2 times the contrast.
    So is there any way to double the result? (reduce?)
    image.png
  2. Use loops correctly. If the result is not used, a forEach traversal should be used.
    image.png
  3. Optimize nested loops. The above example is N*2 at best, and the nested loop becomes N². generally appears in a tree structure, such as permission .
    Example using deduplication to illustrate the gap
    image.png
  4. Use methods in lodash to simplify data processing logic.
    It can achieve less code, high efficiency and clear semantics.

    Object.entries(treeData).filter(([, v]) => v.level === 0).forEach(([key]) => { What is this line of code trying to do? Are there any performance issues?
    image.png
    The performance deviation of Object.entries(treeData) , what is the magnitude of the tree node? Consider using the method provided by lodash, the performance will be better (the number of loops will be reduced, 3 times will be reduced to 1), the code will become less (reduce useless semantics), and the semantics will be more explicit (convert objects into keyvalues) Array, filter out those with level, traverse execution logic => traverse objects).

Means 2: reduce serial code, shorten the request chain

  1. Misuse of await and async
    image.png

Recommendation 7: Avoid Obsolete Code

The code of frameworks such as Vue and react is good, and there is a unified management method. The common ones are some old projects, js, and jQuery projects.

  1. Ban document.write
  2. Put the style on the top and the JS on the bottom. Don't block DOM parsing.

Summarize

The road of optimization complements each other.

  1. Optimize loading speed. Expand bandwidth, cache, content distribution, reduce size.
  2. Optimize volume. Reduce loss and reduce parsing time.
  3. Optimize logic. Lazy loading, asynchronous loading, reducing invalid loss and improving execution efficiency.

Project combat

I have provided some minimal examples in the repository: Demo repository address , you just need to look at the example to see the problem directly (and then you can optimize it).


linong
29.2k 声望9.5k 粉丝

Read-Search-Ask