The Performance Tuning section documents the methods used in the project
The network layer
Increase the DNS – prefetch
The domain name DNS lookup process of the browser is as follows:The impact is small when the bandwidth is large, but the DNS request bandwidth is very small on mobile devices. To solve this problem, the project adopts the pre-read DNS scheme, which can significantly reduce the delay, especially on the mobile terminal.
Step 1: Use meta information to inform the browser that the current page needs to be pre-resolved by DNS:
Developer.mozilla.org/en-US/docs/…
<meta http-equiv="x-dns-prefetch-control" content="on" />
Copy the code
Step 2: Use the link label in the header to force DNS pre-resolution
<link rel="dns-prefetch" href="https://company.info.com/">
Copy the code
Note: DNs-prefetch is only valid for DNS lookups on cross-domain domains
CDN distribution optimization
The full name of CDN is Content Delivery Network.
Users can obtain the content at the nearest location, reducing network congestion and improving user access response speed and hit ratio.
CDN acquisition process:
Cache policy used
Combined with the external attribute in vue-CLI project, the main improvements are as follows:
- Reduce server stress
- Geographically closer to users, greatly improving the response speed of page resources
- Do not cache HTML entry files (especially wechat browser O (╥﹏╥) O), only cache JS and CSS policy, avoid resources do not update at the same time, speed up the acquisition of some resources
HTTP2
Hypertext Transfer Protocol Version 2, originally named HTTP 2.0), abbreviated as H2 (Encrypted Connections based on TLS/1.2 or above) or H2C (unencrypted Connections) [1], is the second major version of the HTTP protocol used on the World Wide Web.
HTTP2.0 is enabled as follows:
server {
listen 443**ssl** **http2**; server_name yourdomain; ... ssl on**; ... }Copy the code
Enable HTTP2 listening
listen 443 ssl http2;
Copy the code
Multiplexing replaces the original sequence and blocking mechanism, so that multiple resources can be downloaded in parallel in a connection, and is not restricted by the browser’s request for resources in the same domain name, which improves the loading speed of resources in the whole site.
Avoid option requests across domains
The browser classifies requests according to the request method and specific fields in the request header. Specifically, requests that meet the following criteria are simple requests:
- The request method is
GET
,POST
orHEAD
- The value range of the request header:
Accept
,Accept-Language
,Content-Language
,Content-Type
(Limited to three valuesapplication/x-www-form-urlencoded
,multipart/form-data
,text/plain
)
The browser draws a circle where simple requests are inside and non-simple requests are outside, and treats the two different requests differently.
Non-simple requests always have a precheck request
At the very least, custom headers take time to send precheck requests, lengthening the page drawing time. Final solution: Remove the custom header and change it to a simple request to avoid prechecking the request.
Set the upper limit for failed requests
Scenario: When a service associated with a page suddenly hangs, the request keeps being reissued
In the project, axiOS was used to configure the retransmission times to solve the problem
axios.interceptors.response.use(undefined.function axiosRetryInterceptor(err) {
var config = err.config;
// If config does not exist or the retry option is not set, reject
if(! config || ! config.retry)return Promise.reject(err);
// Set the variable for keeping track of the retry count
config.__retryCount = config.__retryCount || 0;
// Check if we've maxed out the total number of retries
if(config.__retryCount >= config.retry) {
// Reject with the error
return Promise.reject(err);
}
// Increase the retry count
config.__retryCount += 1;
// Create new promise to handle exponential backoff
var backoff = new Promise(function(resolve) {
setTimeout(function() {
resolve();
}, config.retryDelay || 1);
});
// Return the promise in which recalls axios to retry the request
return backoff.then(function() {
return axios(config);
});
});
Copy the code
axios.get('/some/endpoint', { retry: 5.retryDelay: 1000 })
.then(function(res) {
console.log('success', res.data);
})
.catch(function(err) {
console.log('failed', err);
});
Copy the code
Reference: github.com/axios/axios…
Static resource optimization
Code files
- The public library used by the third party can be introduced by CDN to reduce the volume of packaged project JS. The project is externals combined with Vue
Do configuration;
code spliting
Unpacking optimization
.optimization.splitChunks({
chunks: 'all'.cacheGroups: {
libs: {
name: 'chunk-libs'.test: /[\\/]node_modules[\\/]/,
priority: 10.chunks: 'initial' // only package third parties that are initially dependent
},
commons: {
name: 'chunk-commons'.test: resolve('src/components'), // can customize your rules
minChunks: 3.// minimum common number
priority: 5.reuseExistingChunk: true}}})Copy the code
Image resource optimization
The advantages of WebP are reflected in its better image data compression algorithm, which can bring smaller image volume and has undifferentiated image quality recognized by naked eyes. With lossless and lossy compression modes, Alpha transparency and animation features, JPEG and PNG conversion results are excellent, stable and uniform.
According to the current vUe-based technology stack of the company, VUE-LazyLoad is selected, and the following two points are mainly added:
- To implement a
v-webp
Command for webP-enabled pictures - Image URL can be dynamically changed to WebP
Webp compatibility judgment: Canvas scheme is adopted
const supportWebP = (function () {
var canvas = typeof document= = ='object' ? document.createElement('canvas') : {}
canvas.width = canvas.height = 1
return canvas.toDataURL ? canvas.toDataURL('image/webp').indexOf('image/webp') = = =5 : false}) ()Copy the code
Since the project is a VUE technology stack, you can write a directive v-webp to get the image URL using the directive
bind: function (el, binding) {
if (el.tagName.toLowerCase() === 'img' && el.src && el.src.indexOf('data:image') = = = -1 && supportWebP) {
// Use the SRC attribute to get the image address associated with the img element
var _src = el.src
/ /... Follow-up to IMG}}Copy the code
GZIP
Gzip is an abbreviation for several file compression programs, usually the implementation of the GNU Project. Here Gzip stands for GNU Zip. It is also often used to refer to the file format gzip.
Gzip configuration items in nginx are as follows:
1, gzip on | off: * * off by default
Enable or disable the Gzip module
2. Gzip_comp_level 4: ** The default value is 1. 4 is recommended
Gzip Compression ratio/compression level. The value ranges from 1 to 9. The higher the compression level, the higher the compression rate, the longer the compression time, and the higher the CPU consumption.
3, gzip_min_length 1k: ** default 0, no matter how large the page compression
Set the minimum number of bytes allowed to compress a page. The number of bytes is obtained from the Content-Length in the header.
You are advised to set the number of bytes to a value larger than 1K. If the value is smaller than 1K, the pressure may increase. Namely: gzip_min_length 1024
4, gzip_static on | off: * * off by default
Gzip_static is a nginx static file processing module that can read pre-compressed GZ files. It is used with build-time compression. See build-time compression in the next section
5, gzip_types
6, more configuration information: **Nginx gzip
At present, the main gZIP compression optimization, is through the gzip compression program, to compress resources, so as to reduce the file size of the resource request.
Render layer optimization
Avoid reflow
The principle is not pulled, the operation in practice is mainly:
- Avoid frequent use
style
Instead, take modificationsclass
The way. - use
createDocumentFragment
In bulkDOM
Operation. - for
Resize, scroll
Etc for anti-shake/throttling treatment. - add
will-change: tranform
Let the rendering engine implement a single layer for it, and when these transformations occur, just use the composition thread to process them, without involving the main thread, greatly improving the rendering efficiency. Of course, this change is not limited totranform
, any CSS property that can be synthesizedwill-change
To declare.
Vue optimization
- Use v-show and V-if properly. If updates are not frequent, v-if can be used. If updates are frequent, v-show can be used.
- With computed properly, computed attributes are cached based on their responsive dependencies, and they are reevaluated only when the associated responsive dependencies change;
- V-for has a higher priority than V-if. V-if has to be recalculated every time v-for is used. This is wasteful.
- Tasks such as custom events, DOM events, and timers are destroyed in time (in beforeDestory) to avoid inner layer leakage.
- Use asynchronous components wisely, loading modules from the server only when needed, and caching the results when Vue asynchronous components are rendered for future re-rendering;
- Use keep-alive wisely. Cache components that do not need to be re-rendered, such as multiple static Tab pages, can be wrapped with keep-alive.
- For a long list and a large amount of data, it is recommended to paginate the source data and not put it in data (the data in data is reactive).
- Not only vue-Routers can be imported on demand, but components can also be imported
export default {
components: {
NoticeDialog: () = > import('dialog.vue')}}Copy the code
Reduce white screen time
Compared with Native pages, H5 page experience problems are mainly as follows: opening an H5 page requires a series of processing, and there will be a period of blank screen time, and the experience is bad.
The white screen time is the time between the time the browser responds to the user’s web address and the time the browser starts displaying content.
Optimization of item:
- Skeleton screen, HTML direct rendering transition effect;
- Change the third party JS introduction order; (LOADING CSS blocks DOM tree rendering)
- Split common code using SplitChunksPlugin;
- Dynamic import is used to slice the page code and reduce the JS volume of the front screen.
- Long list optimization
- ssr
H5 offline package
Principle:
We could start with the page needs to be packaged and preloaded static resources to the client installation package, when users to install, then extract resources to local storage, when the WebView to load a H5 page, intercept all HTTP request, check to see if the requested resource in the local existence, if there is a direct return resources.
Offline package update
Manage background configuration to record all related offline package information sets and update version fields
If the version of main is larger than that of the local offline package, the system downloads the latest version from the offline package platform
On what basis does the client intercept a static resource request
{
"version": 1."items": [{"packageId": "u"."version": 1."remoteUrl": "073d65.js"."path": "js/app.67073d65.js"."mimeType": "application/javascript"}}Copy the code
Where remoteUrl is the address of the resource on the static resource server, path is the local relative path of the client (by intercepting the server request corresponding to the resource, hitting the relevant resource locally based on the relative path and then returning)
Commonly used indicators
- Page loading time
- First screen loading duration
- The Dom Ready time
- The Dom Complete time
- Home page rendering duration
- Home page content rendering time
- Home page effective rendering time
Calculation: Using the Performance API
White screen time:
White screen time = responseStart – navigationStart
First rendering duration = All Event Registration Duration = loadEventEnd – navigationStart
Page drawing time = Capture data until end of load = loadEventEnd – fetchEnd(Self record)
Buried point reporting method
The Beacon interface is used to send asynchronous and non-blocking requests to the server. Beacon requests use the POST method of the HTTP protocol and usually do not require a response. This request is guaranteed to be sent before the Unload state of the page goes from start to finish. You don’t need a blocking request, such as XMLHttpRequest.
sendBeacon