preface
Performance optimization is a topic that every engineer cannot escape. Here are some optimization techniques summarized by me in combination with a course of Mr.Max. I hope they will be helpful to you and will continue to be updated in the future. If you want to watch the video, you can directly search on a course website. Demo source code and PPT conditional share (a like 👍), thank you brother 😎
First personal blog
The best time to plant a tree was ten years ago, and the second best time is now
Demonstrate the demo
Fe, optimize the source code
Presentation PPT (must see, super cool)
The online preview
Fe – PPT use HTML to do PPT source code
Front-end performance impact (long warning ❗️❗️❗ ❗)
An important indicator of front-end performance is page load time, which is not only relevant to user experience, but also a factor in search engine rankings.
- Data from Google show that when a page with 10 pieces of data loads in 0.4 seconds, instead of 30 pieces loading in 0.9 seconds, traffic and AD revenue drop
90%
. - Google Map home page file size from
100KB
Reduce to70-80KB
After that, traffic went up in the first week10%
The next three weeks it went up25%
. - Amazon’s data shows that loading times have increased
100 milliseconds
, salesA 1% drop in
.
Therefore: recast performance of the light, we are duty-bound 😎
I. Debugging tools
Sharpener do not mistakenly cut wood work, university work again!
1, the Network
Here you can see resource loading details, and an initial assessment of the factors that affect page performance. The right mouse button allows you to customize the TAB, and at the bottom of the page is an overview of the currently loaded resources. DOMContentLoaded Time when the DOM rendering is complete. Load: Time when all resources on the page are loaded
Consider: How to determine which resources are useless to the current page load, do the corresponding optimization?
Shift + CMD + P brings up the console extension and adds the rule
Extended tool for more use of postures
The waterfall flow waterfall
Queueing
The time the browser puts resources in the queueStalled
The time of stagnation due to the time placed in the queueDNS Lookup
DNS resolution timeInitial connection
The time to set up an HTTP connectionSSL
The time it takes the browser to establish a secure connection with the serverTTFB
The time to wait for the server to return dataContent Download
The time the browser downloads the resource
2, Lighthouse
First Contentful Paint
First screen render time, within 1s greenSpeed Index
Speed index, green within 4sTime to Interactive
Time to page exchangeable
Chrome automatically does a quality assessment of the site based on some of chrome’s strategies and makes recommendations for optimization.
3, Peformance
The most professional analysis of the website ~ will be repeated later
4, webPageTest
You can simulate different scenarios of access, such as different browsers, different countries, and so on, online test address: webPageTest
5. Resource packaging analysis
webpack-bundle-analyzer
NPM install --save-dev webpack-bundle-analyzer // webpack.config.js file const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports={ plugins: [new BundleAnalyzerPlugin({analyzerMode: 'server', analyzerHost: '127.0.0.1', analyzerPort: 8889, reportFilename: 'report.html', defaultSizes: 'parsed', openAnalyzer: true, generateStatsFile: false, statsFilename: 'stats.json', statsOptions: null, logLevel: 'info' }), ] } // package.json "analyz": "NODE_ENV=production npm_config_report=true npm run build"Copy the code
Open source – the map
webpack.config.js
module.exports = {
mode: 'production',
devtool: 'hidden-source-map',
}
Copy the code
package.json
"analyze": "source-map-explorer 'build/*.js'",
Copy the code
npm run analyze
Second, the WEB API
He that would do a good job must sharpen his tools. Some of the analytics apis provided by the browser are critical
1. Listen to the activation status of Windows
Do universities do MOOCs? The video will be paused as soon as you leave the window
Or some exam sites that remind you not to leave the current window
Or, this effect
// Let vEvent = 'visibilityChange '; if (document.webkitHidden ! = undefined) { vEvent = 'webkitvisibilitychange'; {if} function visibilityChanged () (document. Hidden | | document. WebkitHidden) {document. The title = 'the guest officer, ~' console.log("Web page is hidden.")} else {document.title = 'guest, You are back ~ '. The console log (" Web page is visible. ")}} the document. The addEventListener (vEvent visibilityChanged, false);Copy the code
There are a lot of hidden apis out there, so here are the ones you’re interested in:
2. Observe long tasks (Task in performance)
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry)
}
})
observer.observe({entryTypes: ['longtask']})
Copy the code
3. Monitor network changes
When the network changes, I will give feedback to users about the network problems. Sometimes when I watch a live broadcast, my network gets stuck, and the live broadcast platform will remind you or automatically switch the definition for you
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
var type = connection.effectiveType;
function updateConnectionStatus() {
console.log("Connection type changed from " + type + " to " + connection.effectiveType);
type = connection.effectiveType;
}
connection.addEventListener('change', updateConnectionStatus);
Copy the code
4, calculate the DOMContentLoaded time
window.addEventListener('DOMContentLoaded', (event) => {
let timing = performance.getEntriesByType('navigation')[0];
console.log(timing.domInteractive);
console.log(timing.fetchStart);
let diff = timing.domInteractive - timing.fetchStart;
console.log("TTI: " + diff);
})
Copy the code
5. More calculation rules
DNS resolution time: domainLookupEnd - domainLookupStart TCP connection time: connectend-connectstart SSL security connection time: ConnectEnd - secureConnectionStart Network request time (TTFB): responseStart - requestStart Data transfer time: DomInteractive - responseEnd resource load time: Duration: responsestart-DomainLookUpStart White screen duration: ResponseEnd - fetchStart domInteractive - fetchStart DOM DomContentLoadEventEnd - fetchStart Page full load time: LoadEventStart - fetchStart HTTP header size: transferSize - encodedBodySize redirection number: performance. Navigation. RedirectCount redirection time consuming: redirectEnd - redirectStartCopy the code
Three, the platitude, Yahoo catch-rule
Sharpened knife, should think to where to poke better ~ 🗡🗡🗡
About yahoo! Catch rules, how many do you know, what do you usually write to use? There are many optimizations that can be done for the following rules
1. Reduce cookie transmission
Cookie transmission will cause a waste of bandwidth. You can:
- Reduce what is stored in the cookie
- Static resources do not need cookies, can use other domain names, will not take the initiative to bring cookies.
2. Avoid excessive backflow and redrawing
The page backflow operation is triggered continuously
let cards = document.getElementsByClassName("MuiPaper-rounded");
const update = (timestamp) => {
for (let i = 0; i <cards.length; i++) {
let top = cards[i].offsetTop;
cards[i].style.width = ((Math.sin(cards[i].offsetTop + timestamp / 100 + 1) * 500) + 'px')
}
window.requestAnimationFrame(update)
}
update(1000);
Copy the code
Look at the effect. It’s obvious
performance
The results of the analysis,load
There is a lot of backflow after the event, andchrome
They’re all marked red
Optimize with fastDom to separate and merge the dom reads and writes
let cards = document.getElementsByClassName("MuiPaper-rounded");
const update = (timestamp) => {
for (let i = 0; i < cards.length; i++) {
fastdom.measure(() => {
let top = cards[i].offsetTop;
fastdom.mutate(() => {
cards[i].style.width =
Math.sin(top + timestamp / 100 + 1) * 500 + "px";
});
});
}
window.requestAnimationFrame(update)
}
update(1000);
Copy the code
Look at the effect again, very smooth ~performance
As a result, there are no more red flags after the load event
FastDom: Github fastDom online preview: fastDom Demo
As for the idea of task splitting and combination, React Fiber architecture is excellent. If you are interested, you can learn about the practice of scheduling algorithm in Fiber
Fourth, the compression
HMMM, make sure you are not walking in the wrong field, continue to continue!
1, Gzip
For details about how to enable gzip, see nginx
There is another way: when packaging, generate gz files and upload them to the server. This way, you do not need nginx to compress the files, which can reduce server pressure. Refer to: Gzip Compression file &webPack configuration Compression-webpack-plugin
2. Server compression
server.js
const express = require('express');
const app = express();
const fs = require('fs');
const compression = require('compression');
const path = require('path');
app.use(compression());
app.use(express.static('build'));
app.get('*', (req,res) =>{
res.sendFile(path.join(__dirname+'/build/index.html'));
});
const listener = app.listen(process.env.PORT || 3000, function () {
console.log(`Listening on port ${listener.address().port}`);
});
Copy the code
package.json
"start": "npm run build && node server.js",
Copy the code
3, JavaScript, Css, Html compression
Engineering projects directly use the corresponding plug-in, WebPack is mainly the following three:
- UglifyJS
- webpack-parallel-uglify-plugin
- terser-webpack-plugin
Specific advantages and disadvantages can be referenced: WebPack commonly used three JS compression plug-ins. The principle of compression is simply to remove some Spaces, newlines, comments, with the modular function of ES6, do some tree-shaking optimization. Some code obfuscation was done, both for smaller size and for source security.
The main CSS compression plugin is mini-css-extract-plugin, but the previous JS compression plugin will also do CSS compression for you. Use posture:
npm install --save-dev mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
plugins:[
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
Copy the code
HTML compression can be used with HtmlWebpackPlugin, a single page project index. HTML performance improvement is minimal ~
4, HTTP2 header compression
The characteristics of http2
- Binary framing
- The first compression
- Flow control
- multiplexing
- Request priority
- Server push
http2_push: 'xxx.jpg'
The specific upgrade method is also very simple, modify the nGINx configuration, please Google the method
Webpack optimization
Some webPack plug-ins were mentioned above, so let’s take a look at some others
1. DllPlugin improves build speed
With DllPlugin, some large and rarely upgraded packages are split to generate xx.dll.js file, which is referenced through manifest.json
webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
module.exports = {
mode: "production",
entry: {
react: ["react", "react-dom"],
},
output: {
filename: "[name].dll.js",
path: path.resolve(__dirname, "dll"),
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
name: "[name]",
path: path.resolve(__dirname, "dll/[name].manifest.json")
})
]
};
Copy the code
package.json
"scripts": {
"dll-build": "NODE_ENV=production webpack --config webpack.dll.config.js",
},
Copy the code
2. Unpack splitChunks
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
name: 'vendor',
test: /[\\/]node_modules[\\/]/,
minSize: 0,
minChunks: 1,
priority: 10,
chunks: 'initial'
},
common: {
name: 'common',
test: /[\\/]src[\\/]/,
chunks: 'all',
minSize: 0,
minChunks: 2
}
}
}
},
Copy the code
Six, skeleton screen
Use CSS to occupy a good position in advance, when the resource loading can be filled, reduce the page reflux and redraw, but also to give the user the most direct feedback. Using plug-ins in the figure:react-placeholder
There are many ways to implement skeleton screens, many of which are rendered using the Puppeteer server
Use CSS pseudo-classes: a skeleton screen solution that can be implemented with just CSS
, etc.
7. Windowing
How it works: Load only the DOM elements that can be displayed in the current window. When the view changes, remove the hidden ones and add the DOM to be displayed to ensure that the number of DOM elements on the page is never small and the page will not get stuck
Plugins used in the figure:react-window
Install: NPM I react-window
Import {FixedSizeList as List} from ‘react-window’;
Use:
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
const Example = () => (
<List
height={150}
itemCount={1000}
itemSize={35}
width={300}
>
{Row}
</List>
);
Copy the code
Eight, the cache
1. HTTP cache
keep-alive
Check whether Connection: keep-alive is enabled in Response Headers. When enabled, there is no Initial Connection time in the waterfall stream of the network
Nginx set keep-alive (default enabled)
#keepalive_timeout 0; # 65s no connection to close keepalive_timeout 65; # Disconnect keepalive_requests 100 when the number of connections reached 100;Copy the code
Cache-Control / Expires / Max-Age
Set whether the resource is cached and for how long
Etag / If-None-Match
Resource unique identifier for comparison, if changed, pull the resource from the server. If there is no change, the cache resource is fetched, status code 304, which is the negotiated cache
Last-Modified / If-Modified-Since
Compare the time differences to determine whether or not to retrieve resources from the server
For more HTTP Cache parameters, see using HTTP Cache: Etag, last-Modified, and cache-Control
2, the Service Worker
With the WebPack plug-ins WorkboxWebpackPlugin and ManifestPlugin, load serviceworker.js and register it with serviceWorker.register()
new WorkboxWebpackPlugin.GenerateSW({ clientsClaim: true, exclude: [/\.map$/, /asset-manifest\.json$/], importWorkboxFrom: 'cdn', navigateFallback: paths.publicUrlOrPath + 'index.html', navigateFallbackBlacklist: [ new RegExp('^/_'), new RegExp('/[^/?]+\\.[^/]+$'), ], }), new ManifestPlugin({ fileName: 'asset-manifest.json', publicPath: paths.publicUrlOrPath, generate: (seed, files, entrypoints) => { const manifestFiles = files.reduce((manifest, file) => { manifest[file.name] = file.path; return manifest; }, seed); const entrypointFiles = entrypoints.app.filter( fileName => ! fileName.endsWith('.map') ); return { files: manifestFiles, entrypoints: entrypointFiles, }; }}),Copy the code
Preloading && lazy loading
1, the preload
Take the example of the fonts in Demo. The normal loading order is like this:
Join our preload:
<link rel="preload" href="https://fonts.gstatic.com/s/longcang/v5/LYjAdGP8kkgoTec8zkRgqHAtXN-dRp6ohF_hzzTtOcBgYoCKmPpHHEBiM6LIGv3EnKLjtw.119 .woff2" as="font" crossorigin="anonymous"/> <link rel="preload" href="https://fonts.gstatic.com/s/longcang/v5/LYjAdGP8kkgoTec8zkRgqHAtXN-dRp6ohF_hzzTtOcBgYoCKmPpHHEBiM6LIGv3EnKLjtw.118 .woff2" as="font" crossorigin="anonymous"/> <link rel="preload" href="https://fonts.gstatic.com/s/longcang/v5/LYjAdGP8kkgoTec8zkRgqHAtXN-dRp6ohF_hzzTtOcBgYoCKmPpHHEBiM6LIGv3EnKLjtw.116 .woff2" as="font" crossorigin="anonymous"/>Copy the code
2, prefetch
Scenario: Home page does not need this font file, next page does: home page will load ahead of time with Lowest priority: Lowest
Join the prefetch:
<link rel="prefetch" href="https://fonts.gstatic.com/s/longcang/v5/LYjAdGP8kkgoTec8zkRgqHAtXN-dRp6ohF_hzzTtOcBgYoCKmPpHHEBiM6LIGv3EnKLjtw.113 .woff2" as="font"/> <link rel="prefetch" href="https://fonts.gstatic.com/s/longcang/v5/LYjAdGP8kkgoTec8zkRgqHAtXN-dRp6ohF_hzzTtOcBgYoCKmPpHHEBiM6LIGv3EnKLjtw.118 .woff2" as="font"/> <link rel="prefetch" href="https://fonts.gstatic.com/s/longcang/v5/LYjAdGP8kkgoTec8zkRgqHAtXN-dRp6ohF_hzzTtOcBgYoCKmPpHHEBiM6LIGv3EnKLjtw.117 .woff2" as="font"/>Copy the code
Pages needed fromprefetch cache
To take
Webpack also supports these two properties :webpackPrefetch and webpackPreload
3. Lazy loading
The picture
Machine images
Progressive image (similar to Gaussian blur)
This format needs to be specified when the UI sister publishes
Responsive picture
Native mode:<img src="./img/index.jpg" sizes="100vw" srcset="./img/dog.jpg 800w, ./img/index.jpg 1200w"/>
The route was loaded lazily. Procedure
This is done by the function + import
const Page404 = () => import(/* webpackChunkName: "error" */'@views/errorPage/404');
10. SSR && React-Snap
- Server renders SSR, vue uses Nuxt.js, react uses nex.js
- The React-Snap implementation uses Puppeteer to render a single page, then preserve the DOM and send it to the client
11. Experience optimization
White during loading
loading.htmlYou need to get it yourself. There’s another way to use itwebpack
The plug-inHtmlWebpackPlugin
Insert loading resource into the page
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, Word-wrap: break-word! Important; "> < span style> Body {margin: 0; } #loadding { position: fixed; top: 0; bottom: 0; display: flex; width: 100%; align-items: center; justify-content: center; } #loadding > span { display: inline-block; width: 8px; height: 100%; margin-right: 5px; border-radius: 4px; -webkit-animation: load 1.04s ease infinite; Animation: load 1.04s ease infinite; } @keyframes load { 0%, 100% { height: 40px; background: #98beff; } 50% { height: 60px; margin-top: -20px; background: #3e7fee; } } </style> </head> <body> <div id="loadding"> <span></span> <span style="animation-delay: ">< span style=" max-width: 100%; clear: both; min-height: 1em; 0.39 s "> < / span > < span style =" animation - delay: Word-wrap: break-word! Important; ">< span style = "box-sizing: border-box; color: RGB (74, 74, 74); () => { const $loadding = document.getElementById("loadding"); if (! $loadding) { return; } $loadding.style.display = "none"; $loadding.parentNode.removeChild($loadding); }); </script> </html>Copy the code
Job ads
Micro medical group
Hospital support group- Coordinates: Hangzhou, Zhejiang
- 3 years + or 21 years internship
- Resume email: [email protected]
Stay tuned for more performance optimizations
Study + sort out these spent a long time, passing eldest brother, young lady sister also please give a praise 👍, have a problem also can leave a message exchange ha 😝
Reference article:
- 【 Link is illegal, please search by yourself 】
- Front-end performance optimization of yahoo 35 catch-rules
- Webpack Practice – Use of Webpack-bundle-Analyzer
- Nginx open gzip
- Gzip Compression file &webPack Configure Compression-webpack-plugin
- Webpack commonly used three JS compression plug-ins
- A skeleton screen solution that can be implemented as long as CSS
- Use HTTP caches: Etag, last-Modified, and cache-control
- WebpackPrefetch and webpackPreload