9 strategies and 6 indicators for performance optimization

9 strategies and 6 indicators for performance optimization

Preface

Usually everyone thinks

Performance optimization
It is a disordered application scenario, but in the author s opinion it is an orderly application scenario with many
Performance optimization
They are all paving the way for each other and even the Belt and Road Initiative. From the perspective of process trends,
Performance optimization
It can be divided into network level and rendering level ; from the result trend,
Performance optimization
It can be divided into time level and volume level . Simply put
To make it appear in front of users quickly and accurately when visiting the website
.

all

Performance optimization
All around
Two big levels and two small levels
Realization, the core level is
Network level
with
Rendering level
, The auxiliary level is
Time level
with
Volume level
, And the auxiliary level is full of the core level. So the author sorted out the front-end
Performance optimization
The nine strategies and six indicators . Of course these
Strategy
with
index
They are all defined by the author, so that it is convenient to make some specifications for performance optimization in some way.

Therefore, combining these characteristics at work or interview can perfectly interpret

Performance optimization
The extended knowledge. High energy ahead, you have to collect it without looking, and walk up! ! !

In order to highlight the theme, all code examples only show the core configuration code, other configurations have not been supplemented, please make your own brain Copy code Copy code

9.strategies

Network level

Performance optimization at the network level is undoubtedly how to make resources

Smaller size and faster loading
Therefore, the author makes suggestions from the following four aspects.

  • Build strategy : based on build tools (
    Webpack/Rollup/Parcel/Esbuild/Vite/Gulp
    )
  • Image strategy : based on image type (
    JPG/PNG/SVG/WebP/Base64
    )
  • Distribution strategy : Based on the content distribution network (
    CDN
    )
  • Cache strategy : based on browser cache (
    Strong caching/negotiation caching
    )

The above-mentioned four aspects are completed step by step, which is full of the entire project process. The construction strategy and the image strategy are in the development stage, and the distribution strategy and the caching strategy are in the production stage. Therefore, at each stage, it is possible to check whether the above strategies are connected in order. In this way, you can maximize

Performance optimization
Application scenarios.

Build strategy

The strategy mainly revolves around

webpack
Do related processing, but also the most common access
Performance optimization strategy
. The handling of other build tools is similar, and may just be inconsistent in configuration. Speaking of
webpack
of
Performance optimization
, Undoubtedly from
Time level
with
Volume level
Get started.

The author found that the overall compatibility of webpack v5 is not particularly good. Some functions may have problems with third-party tools. Therefore, we have not upgraded to v5 yet and continue to use v4 as a production tool. Therefore, the following configurations are based on v4, but the overall configuration is the same as that of v5. The configuration is not very different Copy code Copy code

The author makes 6 points for each of the two levels

Performance optimization recommendations
12 in total
Performance optimization recommendations
, In order to facilitate memory, all four-character words are used to summarize, so that everyone can digest. means
Reduce packaging time
, means
Reduce packaging volume
.

  • Reduce packaging time :
    Reduce scope
    ,
    Cached copy
    ,
    Directed search
    ,
    Build ahead
    ,
    Parallel build
    ,
    Visual structure
  • Reduce packaging volume :
    Split code
    ,
    Tree shaking optimization
    ,
    Dynamic gasket
    ,
    Load on demand
    ,
    Role enhancement
    ,
    Compress resources

Reduce scope

Configure include/exclude to narrow Loader's search range of files . The advantage is

Avoid unnecessary translation
.
node_modules directory
With such a large size, how much time does it cost to retrieve all the files?

include/exclude
Usually in major
Loader
Configuration,
src directory
Usually as a source code directory, it can be handled as follows. of course
include/exclude
It can be modified according to the actual situation.

export default { //... module: { rules: [{ exclude:/node_modules/, include:/src/, test:/\.js$/, use: "babel-loader" }] } }; Copy code Copy code

Cached copy

Configure the cache to cache Loader's compiled copy of the file , the advantage is

Only compile the modified files when compiling again
. Why should the unmodified file be recompiled along with the modified file?

most

Loader/Plugin
Will provide an option to use the compilation cache, usually including
cache
Wording. To
babel-loader
with
eslint-webpack-plugin
Take for example.

import EslintPlugin from "eslint-webpack-plugin"; export default { //... module: { rules: [{ //... test:/\.js$/, use: [{ loader: "babel-loader", options: {cacheDirectory: true} }] }] }, plugins: [ new EslintPlugin({ cache: true }) ] }; Copy code Copy code

Directed search

Configure resolve to improve the search speed of files , the advantage is

Directional designation must file path
. If some third-party libraries are introduced in a conventional form, errors may be reported or you want the program to automatically index specific types of files.

alias
Mapping module path,
extensions
Indicates the file suffix,
noParse
Filter non-dependent files. Normal configuration
alias
with
extensions
Is enough.

export default { //... resolve: { alias: { "#": AbsPath(""),//Root directory shortcut "@": AbsPath("src"),//src directory shortcut swiper: "swiper/js/swiper.min.js" },//Module import shortcut extensions: [".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]//The file extension can be omitted when importing the path } }; Copy code Copy code

Build in advance

Configure DllPlugin to package third-party dependencies in advance , the advantage is

Completely separate the DLL from the business code and only build the business code each time
. This is an ancient configuration, in
webpack v2
Time has existed, but now
webpack v4+
This configuration is no longer recommended, because the performance improvement brought by its version iteration is enough to ignore
DllPlugin
The benefits brought by.

DLL means

Dynamic link library
, Refers to a code library that can be used by multiple programs at the same time. In the front-end field, it can be considered as the existence of alternative caches. It packs the common code into DLL files and stores them in the hard disk, and dynamically links when repacking
DLL file
There is no need to package those common codes again, thereby improving the construction speed and reducing the packaging time.

Configuration

DLL
Generally speaking, it is more complicated than other configurations, and the configuration process can be roughly divided into three steps.

First tell the build script which dependencies are made

DLL
And generate
DLL file
with
DLL mapping table file
.

import {DefinePlugin, DllPlugin} from "webpack"; export default { //... entry: { vendor: ["react", "react-dom", "react-router-dom"] }, mode: "production", optimization: { splitChunks: { cacheGroups: { vendor: { chunks: "all", name: "vendor", test:/node_modules/ } } } }, output: { filename: "[name].dll.js",//output path and file name library: "[name]",//Global variable name: other modules will get the internal module from this variable path: AbsPath("dist/static")//output directory path }, plugins: [ new DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development")//Overwrite production environment into development environment in DLL mode (start third-party dependent debugging mode) }), new DllPlugin({ name: "[name]",//Global variable name: reduce the search scope and use it in conjunction with output.library path: AbsPath("dist/static/[name]-manifest.json")//output directory path }) ] }; Copy code Copy code

Then in

package.json
Configure the execution script in the configuration and first execute the script before each build and package it out
DLL file
.

{ "scripts": { "dll": "webpack --config webpack.dll.js" } } Copy code Copy code

Last link

DLL file
And inform
webpack
Hitable
DLL file
Let it read by itself. Use html-webpack-tags-plugin to automatically insert when packaging
DLL file
.

import {DllReferencePlugin} from "webpack"; import HtmlTagsPlugin from "html-webpack-tags-plugin"; export default { //... plugins: [ //... new DllReferencePlugin({ manifest: AbsPath("dist/static/vendor-manifest.json")//manifest file path }), new HtmlTagsPlugin({ append: false,//insert after the resource is generated publicPath: "/",//Use public path tags: ["static/vendor.dll.js"]//Resource path }) ] }; Copy code Copy code

For the time cost of those few seconds, I suggest a better configuration. Of course, you can also use autodll-webpack-plugin instead of manual configuration.

Parallel construction

Configure Thread to convert Loader single process to multi-process , the advantage is

Unleash the advantages of CPU multi-core concurrency
. currently using
webpack
When building a project, there will be a large number of files that need to be parsed and processed. The construction process is a computationally intensive operation. As the number of files increases, the construction process becomes slower.

operating

Node
inner
webpack
It is a single-threaded model, which is simply
webpack
The tasks to be processed need to be processed one by one, and multiple tasks cannot be processed at the same time.

File read and write
versus
Calculation operation
Unavoidable, can you let
webpack
Handle multiple tasks at the same time, play multi-core
CPU
How about the power of computers to increase the speed of construction? thread-loader will help you, according to
CPU
The number of threads to start.

There is a problem to pay attention to here. If the project files are not too many, do not use this

Performance optimization recommendations
After all, there will be performance overhead in opening multiple threads.

import Os from "os"; export default { //... module: { rules: [{ //... test:/\.js$/, use: [{ loader: "thread-loader", options: {workers: Os.cpus().length} }, { loader: "babel-loader", options: {cacheDirectory: true} }] }] } }; Copy code Copy code

Visual structure

Configure BundleAnalyzer to analyze the structure of the packaged file , the advantage is

Find out the cause of the excessive volume
. In order to reduce the construction time by analyzing the reasons, an optimized solution can be obtained.
BundleAnalyzer
Yes
webpack
Official plug-in for intuitive analysis
Package file
Visual data such as module components, module volume ratio, module inclusion relationship, module dependency relationship, file duplication, compression volume comparison and so on.

You can use the webpack-bundle-analyzer configuration, with it, we can quickly find related problems.

import {BundleAnalyzerPlugin} from "webpack-bundle-analyzer"; export default { //... plugins: [ //... BundleAnalyzerPlugin() ] }; Copy code Copy code

Split code

Split each module code, extract the same part of the code , the advantage is

Reduce the frequency of repeated codes
.
webpack v4
use
splitChunks
Substitute
CommonsChunksPlugin
Implement code splitting.

splitChunks
There are many configurations. For details, please refer to the official website , where the author pastes common configurations.

export default { //... optimization: { runtimeChunk: {name: "manifest" },//Extract the WebpackRuntime function splitChunks: { cacheGroups: { common: { minChunks: 2, name: "common", priority: 5, reuseExistingChunk: true,//reuse existing code blocks test: AbsPath("src") }, vendor: { chunks: "initial",//code split type name: "vendor",//code block name priority: 10,//priority test:/node_modules///check file regular expression } },//Cache group chunks: "all"//Code split type: all modules, async asynchronous modules, initial entry modules }//Code block division } }; Copy code Copy code

Tree shake optimization

Delete the unreferenced code in the project , the advantage is

Remove duplicate code and unused code
.
Tree shaking optimization
First appeared in
rollup
,Yes
rollup
Core concept, later in
webpack v2
Use it for reference.

Tree shaking optimization
Only right
ESM specification
Take effect, and invalidate other module specifications.
Tree shaking optimization
For static structural analysis, only
import/export
Can provide static
Import and Export
Features. Therefore, you must use when writing business code
ESM specification
To make
Tree shaking optimization
Remove duplicate code and unused code.

in

webpack
Just set the packaging environment to
Production Environment
Can make
Tree shaking optimization
Take effect, and use the business code at the same time
ESM specification
Write, use
import
Import the module, use
export
Export the module.

export default { //... mode: "production" }; Copy code Copy code

Dynamic gasket

Use the shim service to return the current browser code shim according to the UA . The advantage is

No need to pack heavy code shims
. Configure every build
@babel/preset-env
with
core-js
According to certain needs
Polyfill
Packed in, which undoubtedly adds to the code size.

@babel/preset-env
which provided
useBuiltIns
Can be imported on demand
Polyfill
.

  • false : ignore
    target.browsers
    Will all
    Polyfill
    Load in
  • entry : According to
    target.browsers
    Will part of
    Polyfill
    Load it in (only introduce those that are not supported by the browser)
    Polyfill
    , Need to be in the entry file
    import "core-js/stable"
    )
  • usage : According to
    target.browsers
    And the use of ES6 in the detection code will be part
    Polyfill
    Load it in (no need to enter the file
    import "core-js/stable"
    )

Recommend everyone to use

Dynamic gasket
.
Dynamic gasket
According to the browser
UserAgent
Return to the current browser
Polyfill
, The idea is based on the browser s
UserAgent
From
browserlist
Find out which features of the current browser lack support to return these features
Polyfill
. Students interested in this aspect can refer to the source code of polyfill-library and polyfill-service .

Here are two

Dynamic gasket
Service, you can click the following link in different browsers to see the different output
Polyfill
. Believe
IExplore
Still the most
Polyfill
Yes, it proudly says:
I am me, a different firework
.

Use html-webpack-tags-plugin to automatically insert when packaging

Dynamic gasket
.

import HtmlTagsPlugin from "html-webpack-tags-plugin"; export default { plugins: [ new HtmlTagsPlugin({ append: false,//insert after the resource is generated publicPath: false,//Use public path tags: ["https://polyfill.alicdn.com/polyfill.min.js"]//resource path }) ] }; Copy code Copy code

Load on demand

Package the routing page/trigger function into a single file and load it when used . The advantage is

Reduce the burden of first-screen rendering
. Because the more features of the project, the larger the package size, which leads to the slower the first screen rendering speed.

Only need to correspond when the first screen is rendered

JS code
Without other
JS code
, So you can use
Load on demand
.
webpack v4
Provide module on-demand cutting and loading function, cooperate with
import()
It can achieve the effect of reducing the package of the first screen rendering, thereby speeding up the first screen rendering speed. Only when certain functions are triggered will the current function be loaded
JS code
.

webpack v4
Provide magic annotation naming
Cutting module
, If there is no annotation, the cut out module cannot distinguish which business module belongs to, so generally one business module shares one
Cutting module
The name of the annotation.

const Login = () => import(/* webpackChunkName: "login" */"../../views/login"); const Logon = () => import(/* webpackChunkName: "logon" */"../../views/logon"); Copy code Copy code

The console may report an error when it is running.

package.json
of
babel
Just insert @babel/plugin-syntax-dynamic-import in the relevant configuration .

{ //... "babel": { //... "plugins": [ //... "@babel/plugin-syntax-dynamic-import" ] } } Copy code Copy code

Improved function

Analyze the dependencies between modules and merge the packaged modules into one function . The advantage is

Reduce function declaration and memory cost
.
Role enhancement
First appeared in
rollup
,Yes
rollup
Core concept, later in
webpack v3
Use it for reference.

Not turned on

Role enhancement
There will be a large number of function closures in the code after construction. Due to module dependency, pass
webpack
After packaging, it will be converted into
IIFE
, A large number of function closures wrapping code will cause the package size to increase (
The more modules the more obvious
). The scope of the function created when running the code becomes more, which leads to greater memory overhead.

On

Role enhancement
Later, the constructed code will be put into a function scope in the order of introduction, and some variables will be appropriately renamed to prevent variable name conflicts, thereby reducing function declarations and memory costs.

in

webpack
Just set the packaging environment to
Production Environment
Can make
Role enhancement
Take effect, or explicitly set
concatenateModules
.

export default { //... mode: "production" }; //Explicitly set export default { //... optimization: { //... concatenateModules: true } }; Copy code Copy code

Compress resources

Compress HTML/CSS/JS code, compress font/image/audio/video , the advantage is

Reduce packaging volume more effectively
. Optimizing the code to the extreme may not be as effective as optimizing the size of a resource file.

against

HTML
Code, use html-webpack-plugin to enable compression.

import HtmlPlugin from "html-webpack-plugin"; export default { //... plugins: [ //... HtmlPlugin({ //... minify: { collapseWhitespace: true, removeComments: true }//Compress HTML }) ] }; Copy code Copy code

against

CSS/JS
Code, use the following plugins to enable the compression function. among them
OptimizeCss
based on
cssnano
Package,
Uglifyjs
with
Terser
All
webpack
Official plug-in, but also need to pay attention to compression
JS code
Need to distinguish
ES5
with
ES6
.

  • optimize-css-assets-webpack-plugin : compression

    CSS code

  • uglifyjs-webpack-plugin : compression

    ES5
    Version of
    JS code

  • terser-webpack-plugin : compression

    ES6
    Version of
    JS code

    import OptimizeCssAssetsPlugin from "optimize-css-assets-webpack-plugin"; import TerserPlugin from "terser-webpack-plugin"; import UglifyjsPlugin from "uglifyjs-webpack-plugin";

    const compressOpts = type => ({ cache: true,//cache file parallel: true,//parallel processing [

    ${type}Options
    ]: {beautify: false, compress: {drop_console: true}}//Compression configuration}); const compressCss = new OptimizeCssAssetsPlugin({ cssProcessorOptions: {autoprefixer: {remove: false },//Set autoprefixer to retain outdated style safe: true//Avoid cssnano recalculating z-index} }); const compressJs = USE_ES6? New TerserPlugin(compressOpts("terser")): new UglifyjsPlugin(compressOpts("uglify"));

    export default {//... optimization: {//... minimizer: [compressCss, compressJs]//code compression} };

against

Font/audio/video
File, really not relevant
Plugin
For our use, we can only ask everyone to use the corresponding compression tool before releasing the project to the production server. against
image
Files, mostly
Loader/Plugin
Some image processing tools are used during packaging, and some of the functions of these tools are hosted on foreign servers, which often results in installation failures. The specific solution can be found in the article "Talking about the dangerous pits of NPM mirroring" published by the author for answers.

In view of this, the author spent a little trick to develop a

Plugin
Used to cooperate
webpack
To compress images, please refer to tinyimg-webpack-plugin for details .

import TinyimgPlugin from "tinyimg-webpack-plugin"; export default { //... plugins: [ //... TinyimgPlugin() ] }; Copy code Copy code

Above

Build strategy
Are integrated into the author s open source bruce-cli , which is a React/Vue
brucerc.js
The file covers its default configuration, and only needs to focus on the writing of business code without paying attention to the writing of build code, making the project structure more concise. For details, please click here , remember to check the document when using, support a Star !

Image strategy

The strategy mainly revolves around

Image type
Do the relevant processing, and at the same time, the access cost is lower
Performance optimization strategy
. Just do the following two points.

  • Image selection : understand the characteristics of all image types and which application scenarios are most suitable
  • Image compression : use tools or scripts to compress them before deploying to the production environment

Image selection
Be sure to know what each image type
Volume/Quality/Compatibility/Request/Compression/Transparency/Scene
The relative value of such parameters can be quickly made to determine which type of image to use in which scene.

Types of

volume

quality

compatible

request

compression

Transparent

Scenes

JPG

small

in

high

Yes

Lossy

not support

Background image, carousel image, colorful image

PNG

Big

high

high

Yes

Lossless

stand by

Icon, transparency

SVG

small

high

high

Yes

Lossless

stand by

Icon, vector illustration

WebP

small

in

low

Yes

Both

stand by

See compatibility

Base64

It depends

in

high

no

Lossless

stand by

icon

Image Compression
Available in the above
Build strategy-compress resources
You can also use the tool to complete it yourself. As most of now
webpack
The image compression tool either fails to install or is a variety of environmental problems (
You know
), so the author still recommends to use the image compression tool to process the project before releasing the project to the production server, so that the operation is stable and will not increase the packaging time.

The useful image compression tools are nothing more than the following. If there are better tools, please add them in the comments!

tool

Open source

toll

API

Free trial

QuickPicture

There are many types of compression, good compression texture, volume limitation, and quantity limitation

ShrinkMe

There are many types of compression, general compression texture, no quantity limit, and volume limit

Squoosh

There are few compressible types, general compression texture, no quantity limit, and volume limit

TinyJpg

TinyPng

Zhitu

img-master

CDN
CDN

  • CDN
  • Cookie

CDN

CDN
/
CDN

CDN
CDN

CDN
CDN
(///)

CDN
OSS NOS Kodo
CDN

NOS

  • Cache-Control:no-store
  • Cache-Control:no-cache
  • Cache-Control:public/private
  • Expires:t/Cache-Control:max-age=t,s-maxage=t
  • Last-Modified/Etag

HTTP
/ /

304

  • Cache-Control:no-cache
    Last-Modified/ETag
  • Cache-Control:max-age=31536000
    HTML

  • CSS CSS
  • DOM DOM

CSS

CSS
  • ID
DOM
  • DOM
  • DOM
  • DOMFragment
    DOM
  • DOM/
    <script>
    defer
  • DOM/
    <script>
    async
  • DOM
  • display
    DOM
    DOM
  • DOM

  • V8
    V8

V8

juejin.cn/post/698167