当前位置:网站首页>Web resource preloading - production environment practice
Web resource preloading - production environment practice
2022-06-26 18:53:00 【Flying bear blablabla】
This article records the practice of resource preloading in our project , The technical difficulty is not high , Focus on introducing the birth and implementation of a set of technical solutions , What are the thoughts in it , Based on what to make decisions , How to evaluate the effect , wait . It provides some enlightenment for readers when making technical plans .
background
The resource preloading mechanism is well understood , That is, before the user visits the page , Load the corresponding resources in advance . So when users visit the page , Saves time to load resources , achieve “ Second on ” The effect of .
There are many resource preloading schemes , What this article describes is pure web Resource preloading under , It is different from using containers to preset resources . So the technology used is pure web programme .
There is also a background : The project is SPA framework ,webpack+vue Family bucket , What we do is after loading the home page , That is, the preload when jumping to other pages . coordination SPA Advantages of application , It can achieve zero delay jump comparable to native applications .
Let's introduce the technical details .
Which resources are preloaded
There are many resources that can be preloaded , Page asynchrony chunk、vue Components 、js modular , Even interface data can be pre requested . So it depends on what your purpose is .
Here we aim to jump to the page with zero delay , So the page to be preloaded is asynchronous chunk. The so-called page asynchrony chunk, Refers to the use of vue-router The asynchronously loaded file corresponding to the defined page route , In fact, it's also a vue Components , In order to communicate with others vue Component differentiation , We call it page asynchrony chunk Well . This is what the code usually says :

const routes = [
name: 'home',
path: '/home',
children: [
{
path: 'A',
component: () => import('pageA.vue'),
},
{
path: 'B',
component: () => import('pageB.vue'),
}
]
]
pageA.vue and pageB.vue Packaged asynchronously chunk It will only be loaded under the corresponding route , Bring a sense of delay to page Jump , This is the part of resources we need to preload .
Resource loading time
Specify the resources to be loaded , The next thing to consider is , When to load these resources ? If we preload pageB And the user doesn't jump B What shall I do? ?
Resource loading time , It's a technical job , Two key points need to be grasped :
1. Preloading resources should try not to affect the normal operation of users
2. Preloaded resources should be used by users as much as possible
The first 1 spot , It's easy to think , We can preload the page when it is idle . And as soon as possible , If you load late , Users will not use your preloaded resources . To sum up , The time to load resources is “ As early as possible when the page is idle ”.
The first 2 spot , It's not easy , Whether the user jumps or not B Pages are user behavior , How can we guarantee that it will use the preloaded resources . So this can only be a strategy , Maintain an acceptable proportion , stay “ Waste traffic ” And “ User experience ” Find a trade-off point between .
Let's talk about these two points .
Page idle detection
How to detect whether a page is idle ? Unfortunately, there is no such api You can use , There is one requestIdleFrameCallback, It supports the execution of a callback function during the idle period of each frame , But there is no guarantee that .
So we can only judge by ourselves , In fact, the idea is relatively simple , The browser's rendering process has js The engine and UI Engine these two threads , As long as these two threads are idle , We think the page is idle , This should work .
that , How to detect the idleness of these two threads ? It's very simple , Just look at the code :

// testing js Thread idle
const d1 = new Date();
setTimeout(()=>{
const offset = new Date() - d1;
if (offset < 25 ) {
// JS Thread idle
}
}), 20);
Start a delay function , Check the delay of actual execution , If the delay is very large , That means the current situation js The engine is busy . If it is less than a certain threshold , That means js Engine idle .
How should this threshold be determined ? Statistics on real users are certainly the most accurate , So we use an idle page to calculate the average delay of users , It was finally determined to be 5ms.
Same idea ,UI Idleness of the engine can also be detected :

// testing UI Thread idle
const d1 = new Date();
requestAnimationFrame(()=>{
const offset = new Date() - d1;
if ( offset < 30 ) {
// UI Thread idle
}
})
The determination of threshold value is also the statistical mean value of real users , It was finally determined to be 30ms.
With these two tests , We got the page “ Spare time ”. How about “ As soon as possible ” Take it ? The method is relatively simple , We use... After the page is loaded setInterval Start polling , every other 1 Check once per second , Once idle is detected , Resource preloading .
Resource inventory policy
Next, let's look at No 2 spot , How to be in “ Waste traffic ” And “ User experience ” Find a trade-off between .
Consider a question , If only 5% Of users will jump to the page from the home page B, that B Is it necessary to preload the resources of ? The answer is obviously No . In other words, the resources that need to be preloaded should be determined manually , What do we use to determine the resource list ?
There are two ways :
1. Page access funnel . According to the funnel chart, we can get the loss rate of each page Jump , For pages with high churn rate , We can avoid preloading . What is the value of ” more “, This also needs to be weighed , For example, we think 60% Even if the loss is large . A typical funnel diagram is as follows :

2. Dynamic adjustment according to statistical indicators . How effective is our resource preloading scheme , What is the cost-benefit ratio , It needs clear indicators to measure . Pages that have a negative effect on indicators , Don't preload it .
that , How to design statistical indicators ? Let's continue .
Index design
Indicators are used to evaluate and guide our work in a data-based way 、 Decision making . Since it is a production environment practice , There must be a rigorous set of indicators to measure the merits of this scheme .
As mentioned above, we have counted the user execution setTimeout and requestAnimationFrame Average delay of , It is used to guide us to set the idle detection threshold , This is an example of an application .
For the whole scheme , We also designed the following indicators :
Page Jump time
That is, the average time it takes a user to jump to a page . This is the core index we should pay attention to , The goal of the whole scheme is to reduce the page Jump time . Because it is SPA application , This time is easy to count .
Trigger rate
That is, the proportion that triggers resource preloading , Calculation formula : Trigger rate = Number of resource preloads / Page load times . To measure our loading strategy ( Idle detection ) Is it reasonable , Ideally, this value should be close to 100%, In other words, the vast majority of users have preloaded resources . If the trigger rate is found to be lower than expected , Then we should adjust the loading strategy .
shooting
That is, the proportion of preloaded resources used by users , Calculation formula : Number of times preloaded resources were used / Number of resource preloads . This is used to measure the effectiveness of preloaded resources , For example, the hit rate of a resource is 80%, explain 80% Of users use preloaded resources , The effect is very good . But the actual hit rate is often not so high , So our evaluation criteria are : The closer to the scale of the funnel diagram , The better the effect .
Page dwell time
That is, the average time a user stays on a page . This indicator is also collected to guide the loading strategy , For example, the average stay time of the home page is 3 second , Then we can set the polling interval to check whether the page is idle 600ms once , A total of 5 Time .
besides , We also collected the network speed of users , To analyze the impact of this scheme on users in different network speed segments .
With the above indicators , We will be able to formulate strategies scientifically , For example, the hit rate of a resource is lower than 10%, That means it's a low frequency page , Simply remove from the list , No preloading .
How to load resources
The whole idea has become clear , The next step is to load resources . There are many ways to preload resources , Which one shall we choose ?
You might as well look at them one by one .
1. Handwriting script label
The project uses webpack packaged , adopt manifest Documents can be obtained from the resource list , Create one manually when preloading is required script label , Users can use the resources in the cache when they actually jump .
The advantage of this method is that it is less invasive , Just one extra resource load , Minor changes to the original code .
But the disadvantages are obvious : Bad statistical indicators . To count the completion of loading, you can do it in each script Labeled onload In the incident , It's acceptable . But there is no way to count the hit rate , It is impossible to determine whether the user is using the resources in the cache or newly loaded .
2. browser prefetch
That is to use <link rel="prefetch" href="xx.js">, This is the method of preloading resources provided by the browser , It will automatically load resources when the browser is idle .
This method is a little weak , Because no js API For calling , Yes, we have a black box , There is no way to make statistics on relevant indicators .
3.webpack Provided import()
webpack Provides a method for dynamically loading resources , Although it is written in essence script label , but webpack It is well encapsulated , We go through .then() You can know that the resource is loaded . And the resources are stored in memory , On the one hand, it is convenient to count various indicators , On the other hand, you don't even have to leave the cache , Faster .
Sum up , We finally chose the method 3, Can meet our needs .
Effect evaluation
The above is the technical content of the whole scheme , But it's not over yet . Track and evaluate the effectiveness of the scheme , And continue to optimize , This is the correct posture for production environment practice .
The core indicators we care about , Page Jump time , With 50% The above reduction . This is expected , Before the page Jump, such as time-consuming 200ms, After hitting the preloaded resource , Maybe it will be in a moment 10ms Within . The impact on the market is very significant .
Trigger rate , It should be at least 90% The above is qualified . No preload is triggered , How can we talk about hit in the future . Of course, this index can be optimized by adjusting the loading strategy , The back can speak .
As for hit rate , It's hard to say . The first is the one mentioned above , It is related to user behavior , It's an unstable factor . secondly , If the resource preload is triggered too late , The user has already gone to jump , It will also affect this indicator . So the whole is from 15%~35% Don't wait . What is the level of this value ? Qualified or unqualified ? We read the information about preloading schemes in the industry , See that their hit rate is about 20%, So we can think that our effect is good .
Continue to optimize
You can see that , Our index has optimization space , Direction is : Increase trigger rate 、 shooting , Reduce page Jump time .
It is also mentioned above , In order to work out the most accurate loading strategy , Many auxiliary indicators have been collected . An interesting optimization is , We used to go to the page 1 Seconds later, it starts to detect idle , Later, it was changed to detect immediately . Unexpectedly, this change has significantly improved the trigger rate , The reason is that some users are 1 Jump to another page within seconds , There is no time to trigger the preload .
Similar optimizations include , We adjust the idle detection interval , It is found that the trigger rate is also affected .
in addition , We also calculate the hit rate according to the statistics , Removed some low frequency pages , Avoid these resources pulling down the hit rate .
To make a long story short , The reference value of each index is a trade-off process , It needs to be negotiated according to their own business conditions .
Think more
As a performance optimization scheme , We're just building on a specific project 、 Some explorations have been made under specific scenarios . In fact, this subject can do more than that .
For example, the resource loading policy , Can it only be loaded when the page is idle ? stay PC Time , Some schemes guess the next action of the user according to the trajectory of the mouse , Then decide which resources to preload . In mobile terminal , Can we make predictions based on the sliding motion , Or, , Whether the user behavior can be counted ( Business ) As a reference , These are all directions that can be explored .
A friend might ask ,SPA The application loads resources that are not needed on the home page , As a result, you add it back with preload , Isn't that an unnecessary move ? Just package it into a file ? Sounds like a lot of sense , But think carefully , Package into a file and SPA+ Preloading , Compare the advantages and disadvantages of these two methods by drawing out a list , I knew there was a difference . This requires the ability to think .
So the purpose of this article is , Describe the design and implementation process of a technical scheme , To provide you with technical or methodological reference .
边栏推荐
- (几何) 凸包问题
- JVM entry Door (1)
- SSO微服务工程中用户行为日志的记录
- Clion breakpoint single step debugging
- Chain game development finished product source code chain game system development details
- JSONUtils工具类(基于alibaba fastjson)
- PC端录制扫515地机器人/scan数据
- 知识点总结
- IK分词器
- Enter n integers and output the number of occurrences greater than or equal to half the length of the array
猜你喜欢

Solidity - contract inheritance sub contract contains constructor errors and one contract calls the view function of another contract to charge gas fees

Clion编译catkin_ws(ROS工作空间包的简称)加载CMakeLists.txt出现的问题

9. Intelligent transportation project (2)

IK word breaker

Pinda general permission system (day 3~day 4)

Pinda general permission system (day 1~day 2)

(multi threading knowledge points that must be mastered) understand threads, create threads, common methods and properties of using threads, and the meaning of thread state and state transition

Refresh the strong pointer assignment problem in the HP-UX system of Sanguan

CLion断点单步调试

LeetCode 128最长连续序列
随机推荐
Feign remote call
微服务版单点登陆系统(SSO)
Idea collection code, quickly open favorites collection window
Example of using QPushButton style (and method of adding drop-down menu to button SetMenu)
Vscode 基础必备 常用插件
PC end records 515 ground sweeping robot /scan data
微信小程序 uniapp 左滑 删除 带删除icon
爬取豆瓣读书Top250,导入sqlist数据库(或excel表格)中
9. Intelligent transportation project (2)
Determine whether a sequence is a stack pop-up sequence
VCD video disc
几种常见的UML关系图汇总
Clion编译catkin_ws(ROS工作空间包的简称)加载CMakeLists.txt出现的问题
DVD digital universal disc
JVM entry Door (1)
stm32和电机开发(直流有刷电机和步进电机)
50行代码爬取Top500图书导入TXT文档
Request method 'POST' not supported
JVM入个门(1)
8VC Venture Cup 2017 - Final Round C. Nikita and stack