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 drop90%.
  • Google Map home page file size from100KBReduce to70-80KBAfter that, traffic went up in the first week10%The next three weeks it went up25%.
  • Amazon’s data shows that loading times have increased100 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

  • QueueingThe time the browser puts resources in the queue
  • StalledThe time of stagnation due to the time placed in the queue
  • DNS LookupDNS resolution time
  • Initial connectionThe time to set up an HTTP connection
  • SSLThe time it takes the browser to establish a secure connection with the server
  • TTFBThe time to wait for the server to return data
  • Content DownloadThe time the browser downloads the resource

2, Lighthouse

  • First Contentful PaintFirst screen render time, within 1s green
  • Speed IndexSpeed index, green within 4s
  • Time to InteractiveTime 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

performanceThe results of the analysis,loadThere is a lot of backflow after the event, andchromeThey’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 ~performanceAs 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 pushhttp2_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 cacheTo 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 itwebpackThe plug-inHtmlWebpackPluginInsert 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 groupHospital 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