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 .
Chrome DevTools can adjust the language, for example, from English to Chinese.
Lighthouse Performance Metrics
- 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, andSVG
are considered DOM content) are first rendered on the web page. FCP quantile map . - 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 - Speed Index
The speed index indicates how fast the content of the web page is visible to fill - 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. - 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 . 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.
LCP, FCP example
Image source: https://web.dev/lcp/#-2
Lighthouse Optimization Recommendations
Recommendation 1: Reduce unused JavaScript, CSS code
Means 1: Asynchronous. reload when needed
There are many nouns: lazy loading, lazy loading, idle loading, on-demand loading, etc.
"Lazy loading" import asynchronous components
- 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.
- 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.
"Lazy loading" import asynchronous function
- 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.
"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.- 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 ).
- 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
- CSS optimization can also rely on asynchronous components.
- Third-party libraries can consider using components for secondary encapsulation.
- Correctly distinguish v-if and v-show, and study the implementation mechanism of el-tabs in depth. sure components are not actually instantiated
- 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.
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
- The resource server starts Gzip compression and sets the resource 30D cache. Then update it by hashing the filename
- Generally speaking, CDN will support to compress and cache , and the bandwidth is relatively reliable, and the node is relatively close to the user.
- jsmin, tree shaking optimization and other programs.
- Pay attention to the picture type. Solid color image png, complex image jpg, webp smaller.
- Pay attention to the image size. Try not to be too large, pay attention to the cropping.
Means 2: Eliminate duplicate packets. dependency sharing
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 .peerDependencies
For some reason, some packages are not available in all projects, or have strong dependencies on versions. We also need to configurepeerDependencies
to so that the consumer can install the correct version of the dependency .externals
The version number of some third-party libraries is0.xx.x
, becauselerna
is based on whether the first bit is not 0 to compare whether they are the same version. Causesaxios@0.23
andaxios@0.24
not to be considered the same version.
At this time, we will useexternals
to force no packaging and let the user provide it.- Unified build tools and versions
Because sometimes we have some basic packages (babel
,babel-polyfill
), but the versions and methods used by eachcli
version are different, and the escape processing is also inconsistent. In order to use the smallest package size, we require the same version ofcli
webpack
.
Method 3: Replace the package, choose a smaller version
Replace large packages with small packages, and replace full packages with on-demand packages
momentjs
usesdayjs
,momentjs
package only usesformat
around100k
, anddayjs
is only less than10k
.
This is because themomentjs
language pack is entered ini18n
.
So there is another solution, which is to change the language to be introduced on demand.- 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
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.
- 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.
- 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.
For long lists such as select, table, tree, etc., pay attention to the use of virtual lists.
- 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. - 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
- 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.
Abnormal tooltip node.
- For example, components will be rendered ahead of time.
- 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.
- Pay attention to the image size. Try not to be too large, pay attention to the cropping.
- 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.
Recommendation 5: Reduce network load and speed up user downloads
What are the general restrictions on the download speed of resources?
- Bandwidth (throughput) 1M small water pipe
- Distance (near and far) in North China, global visit
- 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
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
- Use loops correctly. should execute
filter
first, and then executemap
.
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?)
- Use loops correctly. If the result is not used, a forEach traversal should be used.
- 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
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?
The performance deviation ofObject.entries(treeData)
, what is the magnitude of thetree
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
- Misuse of await and async
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.
- Ban
document.write
- 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.
- Optimize loading speed. Expand bandwidth, cache, content distribution, reduce size.
- Optimize volume. Reduce loss and reduce parsing time.
- 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).
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。