preface
Recently, I spent some time on the performance optimization of the project, and did a lot of work behind the scenes. However, I still failed to achieve the result I wanted. I was a little disappointed, but I still recorded my perseverance.
Summary of performance optimization: reduce the number of requests, reduce the size of resources, improve the response and loading speed, optimize the loading time of resources, optimize the loading mode.
Performance classification
I think the optimization of front-end engineering performance can be divided into two categories:
-
Subjective and perceived performance from the user’s perspective.
-
Objectively measurable performance from a developer’s perspective.
Perceived performance
To the user, the user perception performance is the most important, simply put, is to make the user feel that your site is fast, and there is no measurement of perception performance.
However, there are always exceptions, and if a page takes a long time to load, there are ways to make it feel slower.
In short, your page can be fast, but you can make your users feel fast.
Objective performance
For developers, performance metrics can be measured objectively, and there are ways to optimize Web performance to meet the standards set by developers.
Objective performance is a measure of time from the time the user enters the URL to the time all resources are downloaded, parsed, and executed, and eventually drawn.
Performance metrics are a very complex standard, and I will write a separate article on performance metrics later.
Build optimization
Because our company is using
So a lot of webPack configuration scaffolding has already been done for you, I won’t go into it, just base on it
Do some optimization configuration
Gzip compression
Gzip compression is very efficient, usually up to 70% compression, which means that if your web page is 30K, it’s compressed to about 9K.
//npm i -D compression-webpack-pluginconfigureWebpack: config => { const CompressionPlugin = require('compression-webpack-plugin') config.plugins.push(new CompressionPlugin())}Copy the code
Remove the console log
Online projects are naturally not supposed to see console print logs, so we need to remove console.log.
//npm i -D terser-webpack-plugin configureWebpack: config => { const TerserPlugin = require('terser-webpack-plugin') config.optimization.minimizer.push( new TerserPlugin({ extractComments: false, terserOptions: { compress: { drop_console: true}},}))}Copy the code
Remove SourceMap
Because packaged files are compressed, merged, and obfuscated, Babel compiled code is not conducive to locating analysis bugs.
module.exports = { productionSourceMap: false,}Copy the code
CDN reduces packaging volume
Use CDN files to reduce the project to package volume and can also be loaded on demand.
Import the required JS and CSS files in /public/index.html
Remove dependencies on vue, element-UI and other related resources from package.json
SRC /main.js, remove vue, element-ui and other related resources import and vue.use statements
Configuration externals. Because the default configuration of Vue Cli 3 is used, the new project does not have the build directory. First, you need to create a new Vue. Config. js file in the root directory of the project and add the following code:
module.exports = { configureWebpack:{ externals:{ 'Vue': 'Vue'.'element-ui': 'element-ui'.'clipboard':'VueClipboard'}}}Copy the code
pre-rendered
There are three rendering methods: client rendering, server rendering and pre-rendering.
Our default development mode is through client rendering, but the client rendering page content, the key link is long, the first screen rendering will have a certain delay, and for
Very unfriendly and not feasible for c-end products.
Therefore, many companies will solve these two problems through SSR or pre-rendering. Due to the reasons of the company’s technology stack, we use pre-rendering to optimize.
What is pre-rendering?
To put it simply, the browser’s part of the job of parsing javascript dynamically rendered pages is done in the packaging phase. In other words, during the build process, WebPack generates statically structured HTML using the prerender-spa-plugin.
// npm i -D prerender-spa-plugin configureWebpack: config => { const path = require('path') const PrerenderSPAPlugin = require('prerender-spa-plugin') config.plugins.push( new PrerenderSPAPlugin({ staticDir: path.join(__dirname, 'dist'), routes: ['/'], minify: { collapseBooleanAttributes: true, collapseWhitespace: true, keepClosingSlash: true, decodeEntities: true, sortAttributes: true, }, renderer: new PrerenderSPAPlugin.PuppeteerRenderer({ renderAfterDocumentEvent: 'render-event', renderAfterTime: 5000, // headless: false,}),}))}Copy the code
Note: The routing mode must behistory
If no value is sethistory
Modes can also run and generate files for eachindex.html
The contents of the file will be the same.
Network Resource optimization
Service Worker
ServiceWorker is a SECTION of JS running in the browser background process. It can do many things, such as intercepting client requests, sending messages to clients, and making requests to servers. One of the most important functions is offline resource caching.
The ServiceWorker has rich and flexible control over the caching process. When a page request is made to the ServiceWorker, the ServiceWorker requests the cache and the network at the same time, gives the cached content directly to the user, and then overwrites the cache. Our company has used ServiceWorker to replace the HTTP cache policy.
Note: You need HTTPS to use ServiceWorker
HTTP cache
HTTP caches generally fall into two categories: strong caches (also known as local caches) and negotiated caches (also known as 304 caches).
A normal refresh enables negotiated caching and ignores strong caching. Strong caching is enabled only when you enter a url in the address bar or favorites, reference a resource through a link, and so on.
Strong cache (200)
Local caching is the fastest way of caching. As long as the resource is still in the cache, the browser will read it directly locally without asking the server.
Negotiation cache (304)
Negotiation cache, as the name implies, is negotiated between the browser and the server, after deciding whether to read the local cache. If the server notifies the browser that it can read the local cache, the 304 status code will be returned, and the negotiation process is very simple, only the header message will be sent, not the response body.
The cache location
The Cache location is usually divided into Memory Cache and Disk Cache.
Memory cache: fast read, short duration, small capacity
Hard disk cache: Reads data slowly, lasts for a long time, and has a large capacity
Cache priority
Service Worker -> Memory Cache -> Disk Cache -> Push Cache
HTTP2
Four new features of HTTP2:
-
Multiplexing eliminates the need for multiple TCP connections because it allows multiple requests to be made on a single HTTP2 connection and therefore does not rely on establishing multiple TCP connections.
-
Binary framing, which encodes all messages to be transmitted in binary and divides the information into smaller message blocks.
-
Header compression: Uses the HPACK technology to compress the header and reduce the packet size
-
Server push. The server can send data before the client initiates a request. In other words, the server can send multiple responses to a request from the client, and the resources can be properly cached.
server { listen 443 ssl http2; }Copy the code
Note: To use HTTP2, you must use HTTPS.
Resource preloading
Simply put, resources are loaded ahead of time and rendered directly from the local cache when the user needs to view them.
Summary: Use preload to preload resources required by the current page and prefetch to preload resources required by other pages.
preload
Preload is loaded during page loading before the browser begins body rendering.
<! -- Preload sty1e.cs5 and index.js with pre1oAD --><link rel="preload" href="style.css" as="style"><link rel="preload" href="index.js" as="script">Copy the code
prefetch
After the prefetch page is loaded, it is loaded in advance in idle time.
<! Prefetch --><link rel="prefetch" href="next.css"><link rel="prefetch" href="next.js">Copy the code
Note: Vue-CLI enables Prefetch by default. You can disable prefetch globally in vue.config.js and enable prefetch for a specific module.
chainWebpack: config => { config.plugins.delete('prefetch')}Copy the code
dns-prefetch
After the page is loaded, use the idle time to load in advance.
<link rel="dns-prefetch" href="//example.com">Copy the code
Load JS asynchronously without blocking
Load js files asynchronously without blocking page rendering.
Let’s start with a common script tag parsing process.
<script src="a.js" ></script>Copy the code
-
Stop parsing the document.
-
Request a. s.
-
Execute the script in A. js
-
Continue parsing the document
defer
<script src="d.js" defer></script><script src="e.js" defer></script>Copy the code
-
Do not prevent document parsing, parallel downloading of D. js, e.js
-
E.js continues parsing document even after downloading D.js
-
Execute d.js and e.js in the order that they appear on the page, after the execution of the other synchronization scripts, and before the DOMContentLoaded event.
async
<script src="b.js" async></script><script src="c.js" async></script>Copy the code
-
Do not prevent document parsing, parallel downloading of B. js, C. js
-
Execute the script immediately after it is downloaded. (The execution sequence and execution stage are uncertain, which may be before or after the DOMContentLoaded event)
webp
Webp is a new image format, which is only 2/3 of the size of JPEG. Switching image resources to WebP can speed up requests.
Most of our picture resources are on Ali’s OSS, and Ali provides an interface to convert PNG/JPEG to WebP format online.
Note: WebP has some browser compatibility issues, so you need to determine whether your browser supports webP.
function check_webp_feature(feature, callback) { var kTestImages = { lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA", lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==", alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==", animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gc A" }; var img = new Image(); img.onload = function () { var result = (img.width > 0) && (img.height > 0); callback(feature, result); }; img.onerror = function () { callback(feature, false); }; img.src = "data:image/webp; base64,"+ kTestImages[feature]; }Copy the code
Perceptual performance optimization
Loading load
Rivers and lakes known as chrysanthemum map….
However, there is now a better way to load a design experience than chrysanthemum loading.
Skeleton screen
The skeleton screen provides a better user experience and a strong sense of loading.
Unfortunately, ElementUI doesn’t provide skeleton screen components. Antd, on the other hand, is delicious.
Compare the experience
The first one is skeleton screen, the second one is chrysanthemum chart, and the third one is no optimization. Compared with the traditional chrysanthemum chart, it can be seen that the content appears smoothly but not obscenely, and the experience is better.