End of webpack4: Join Tencent IM Configuration Strategy to Achieve Extreme Optimization of Front-end Engineering Environment

  css, html, html5, javascript, node.js

图片描述

webpackTo package all resources

Without knowing it,webpackHas been secretly updated to4.34Version, I decided, this is the last one to write this yearwebpackUnless it is updated to version 5, I will spend the rest of this year onGolangAnd the ecology of the back end

Before reading this article, suppose you are rightwebpackHave a certain understanding, if not, can look at my handwriting beforeReactAndVueArticles on Scaffolding

Right herewebpackThe performance optimization of the makes several statements:

  • In some extremely complex environments, doublepackage.jsonDocuments, that is, to implement three packaging
  • At the time of code division, lower than18KThere is no need to pack up the files ofchunk,httpToo many requests affect performance instead.
  • prerenderAndPWAMutually exclusive, this problem has not been solved for the time being.
  • babelCaching compiles cached indexes, that ishashValue, very eat memory, remember to clean up memory after each development
  • babel-polyfillOn-demand loading is suitable for some very complex scenarios
  • prefetch,preloadIt is obvious to optimize and improve the first screen.
  • No matter what technology stack is, code division must be done, otherwise it is a garbage project.
  • Multi-thread compilation also significantly improves the construction speed.
  • Code division fitPWA+Pre-rendering+preloadIs the peak of the first screen optimization, butpwaUnable to cache pre-renderedhtmlFile

textualwebpackMainly forReactTechnology stack, the realization function is as follows:

  • Hot Update of Development Mode
  • RecognitionJSXFile
  • RecognitionclassComponent
  • Code obfuscation and compression to prevent decompilation and encryption of code
  • ConfigurationaliasAlias, simplificationimportLong field of
  • Isomorphism straight out,SSRBased onNodeDo middleware)
  • RealizationjavaScriptThetree shakingShake tree optimization to remove useless code
  • RealizationCSSThetree shaking
  • Recognitionasync / awaitAnd arrow functions
  • react-hot-loaderRecordreactPage retention statusstate
  • PWAFunction, hot refresh, take over the browser immediately after installation, still allow websites to be accessed and add websites to the desktop on the mobile phone.
  • preloadPreload resourcesprefetchRequest resources on demand
  • CSSModular, not afraid of naming conflicts
  • Small picturebase64To deal with
  • File Suffix Savedjsx js jsonWait
  • Realize React lazy loading, on-demand loading, code division and support server-side rendering
  • Supportless sass stylusEqual pretreatment
  • code splitingOptimize the loading time of the first screen to prevent a file from being too large.
  • joindns-prefetchAndpreloadPre-request necessary resources to speed up first screen rendering (JD.com strategy)
  • joinprerender, greatly speed up the first screen rendering speed
  • Extract common codes and package them into onechunk
  • Each ..chunkThere is a correspondingchunkhashEach file has a correspondingcontenthashTo make it easier for browsers to distinguish between caches
  • Picture compression
  • CSSCompression
  • IncreaseCSSPrefix compatible with various browsers
  • Under the specified folder for packaging and outputting various files
  • CachebabelTo speed up the compilation speed
  • One for each entry filechunkAfter packaging, the corresponding file is alsocode spliting
  • DeleteHTMLComments on documents and other useless content
  • Delete the old packaged code for each compilation.
  • willCSSThe files are extracted separately.
  • Babel not only caches the compilation results, but also starts multi-thread compilation after the first compilation, which greatly accelerates the construction speed.
  • Wait ….

In essence,webpackIs a modernJavaScriptStatic module packager for applications (module bundler)。 WhenwebpackWhen processing an application, it recursively constructs a dependency graph (dependency graph), which contains each module required by the application, and then packages all these modules into one or morebundle

webpackPacking principle

  • Identify entry file
  • Module dependencies are identified layer by layer. (Commonjs、amdOr es6import,webpackWill analyze it. To obtain code dependencies)
  • webpackWhat you do is analyze the code. Convert code, compile code, output code
  • Finally, the packaged code is formed.
  • These are all.webpackSome basic knowledge of, for understandingwebpackThe working mechanism of is very helpful.

Comfortable development experience helps to improve our development efficiency, and optimizing the development experience is also crucial.

  • Component hot refresh, CSS hot refresh
  • Since the introduction of hot refresh in webpack, the experience of front-end developers in open environment has been greatly improved.
  • There is no hot refresh capability, after we modify a component

clipboard.png

  • After adding thermal refresh

clipboard.png

Take a lookReactTechnology stack, How to Connect Hot Refresh in Construction

  • No matter what technology stack is, it needs to be indevAdd in modewebpack.HotModuleReplacementPluginplug-in
devServer: {
 contentBase: '../build',
 open: true,
 port: 5000,
 hot: true
 },

Note: It can also be implemented by react-hot-loader, refer to official documents for details.

Code division is also required in development mode to speed up page opening.

optimization: {
 runtimeChunk: true,
 splitChunks: {
 chunks: 'all',
 MinSize: 10000, // to improve cache utilization, this needs to be done at http2/spdy
 MaxSize: 0,// There is no limit
 MinChunks: 3,// share the minimum number of chunk and will not be extracted until the number of uses exceeds this value.
 MaxAsyncRequests: 5,///Maximum Asynchronous chunk
 MaxInitialRequests: 5,// maximum number of synchronized chunks
 AutomaticNamedLimiter:' ~',//Multiple Pages Share chunk Naming Separator
 name: true,
 CacheGroups: {// Declared Public chunk
 vendor: {
 //Filter modules to be entered
 test: module => {
 if (module.resource) {
 const include = [/[\\/]node_modules[\\/]/].every(reg => {
 return reg.test(module.resource);
 });
 const exclude = [/[\\/]node_modules[\\/](react|redux|antd)/].some(reg => {
 return reg.test(module.resource);
 });
 return include && !  exclude;
 }
 return false;
 },
 name: 'vendor',
 Priority: 50,// Determine the priority of module entry
 Reuseexistingchunk: true//reuse existing modules
 },
 react: {
 test({ resource }) {
 return /[\\/]node_modules[\\/](react|redux)/.test(resource);
 },
 name: 'react',
 priority: 20,
 reuseExistingChunk: true,
 },
 antd: {
 test: /[\\/]node_modules[\\/]antd/,
 name: 'antd',
 priority: 15,
 reuseExistingChunk: true,
 },
 },
 }
 }

Briefly explain the above configuration

  • Enter the common part of node_modulesvendor.js bundleChina;
  • Enter react’s family caskreact.js bundleChina;
  • If the project depends onantd, then willantdInto the individualbundleChina; (In fact, there is no need to do this. You can look at the followingbabelConfiguration, higher performance)
  • The remaining service modules will automatically extract common blocks if they are referenced more than 3 times.

Note that the above configuration is only for everyone to see, in fact, this configuration code division, higher performance

optimization: {
 runtimeChunk: true,
 splitChunks: {
 chunks: 'all',
 }
 }

react-hot-loaderRecordreactPage retention statusstate

yarn add react-hot-loader

//Write this in the entry file
 
 import React from "react";
 import ReactDOM from "react-dom";
 import { AppContainer } from "react-hot-loader";  -1. first introduce appcontain.
 import { BrowserRouter } from "react-router-dom";
 import Router from "./router";
 
 /* Initialization */
 renderWithHotReload(Router);  -2. Initialization
 
 /* Hot Update */
 If (module.hot)-3, hot update operation
 module.hot.accept("./router/index.js", () => {
 const Router = require("./router/index.js").default;
 renderWithHotReload(Router);
 });
 }
 
 
 Function Rendering WithHotreload (Router)-4. Define Rendering Function
 ReactDOM.render(
 <AppContainer>
 <BrowserRouter>
 <Router />
 </BrowserRouter>
 </AppContainer>,
 document.getElementById("app")
 );
 }

Then you can try refreshing again

ReactOn-demand loading of, with code partitioning, each on-demand loaded component will be separately partitioned into a file after packaging.

import React from 'react'
import loadable from 'react-loadable'
import Loading from '../loading'
const LoadableComponent = loadable({
loader: () => import('../Test/index.jsx'),
loading: Loading,
});
class Assets extends React.Component {
render() {
return (
<div>
< div > this will load < /div > on demand
<LoadableComponent />
</div>
)
}
}

export default Assets

:: Accessionhtml-loaderRecognitionhtmlFile

{
test: /\.(html)$/,
loader: 'html-loader'
}

Configure alias

resolve: {
modules: [
path.resolve(__dirname, 'src'),
path.resolve(__dirname,'node_modules'),
],
alias: {
components: path.resolve(__dirname, '/src/components'),
},
}

joineslint-loader

{
enforce:'pre',
test:/\.js$/,
exclude:/node_modules/,
include:resolve(__dirname,'/src/js'),
loader:'eslint-loader'
}

resolveParse the configuration to save all file suffixesjs jsx json, add configuration

resolve: {
 extensions: [".js", ".json", ".jsx"]
 }

joinHTMLFile compression, will automatically get startedjsFile injectionhtmlOptimizationHTMLFile

new HtmlWebpackPlugin({
 template: './public/index.html',
 minify: {
 removeComments: true,
 collapseWhitespace: true,
 removeRedundantAttributes: true,
 useShortDoctype: true,
 removeEmptyAttributes: true,
 removeStyleLinkTypeAttributes: true,
 keepClosingSlash: true,
 minifyJS: true,
 minifyCSS: true,
 minifyURLs: true,
 }
 }),

SSRIsomorphism Direct Output Thermal Debugging

  • Usingwebpack watch+nodemonThe combined mode realizes the rightSSRSupport for thermal debugging.nodeRequired for servicehtml/jsviawebpackPlug-in dynamic output, whennodemonAfter detecting the change, it will restart automatically.htmlAll static resources in the file are replaced bydevUnder the mode of resources, and maintainsocketConnect to the automatic update page.
  • After thermal debugging is realized, the debugging process is greatly shortened, which is consistent with the debugging experience of common non-direct output mode. The following is the flow chart of SSR thermal debugging:

clipboard.png

joinbabel-loaderAnd analysisJSX ES6syntacticbabel preset

  • @babel/preset-reactanalysisJsx syntax
  • @babel/preset-envanalysises6Grammar
  • @babel/plugin-syntax-dynamic-importanalysisreact-loadableTheimportLoad on demand withcode splitingFunction
  • ["import", { libraryName: "antd-mobile", style: true }],Antd-mobile on-demand loading
{
 loader: 'babel-loader',
 Options: {//jsx syntax
 presets: ["@babel/preset-react",
 //tree shaking loads babel-polifill on demand
 ["@babel/preset-env", { "modules": false, "useBuiltIns": "false", "corejs": 2 }]],
 plugins: [
 //Support import Lazy Loading
 "@babel/plugin-syntax-dynamic-import",
 //andt-mobile Loading on Demand true is less, and' css' can be written if the value of less style is not used.
 ["import", { libraryName: "antd-mobile", style: true }],
 //Identify class Components
 ["@babel/plugin-proposal-class-properties", { "loose": true }],
 ],
 cacheDirectory: true
 },
 }

In particular, if the computer performance is not high, it is not recommended to turn it on.babelCache index, eat memory very much, remember to clean up memory after each development

jointhread-loaderInbabelTurn on multithreading after first compilation.

const os = require('os')
 {
 loader: 'thread-loader',
 options: {
 workers: os.cpus().length
 }
 }

Add separate extractionCSSdocumentaryloaderAnd plug-ins

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

{
test: /\.(less)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader', options: {
modules: true,
localIdentName: '[local]--[hash:base64:5]'
}
},
{loader:'postcss-loader'},
{ loader: 'less-loader' }
]
}

new MiniCssExtractPlugin({
filename:'[name].[contenthash:8].css'
}),

CSSThetree shaking

const PurifyCSS = require('purifycss-webpack')
 const glob = require('glob-all')
 plugins:[
 //Clear useless css
 new PurifyCSS({
 paths: glob.sync([
 //to do CSS Tree Shaking path file
 Path. resolve (_ _ dirname,'./src/*. html'),//please note that we also need to tree shaking html files.
 path.resolve(__dirname, './src/*.js')
 ])
 })
 ]

Carry out on small picturesbase64Handle, reducehttpThe number of requests, and the output file unified packaging processing

{
test: /\.(jpg|jpeg|bmp|svg|png|webp|gif)$/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[name].[hash:8].[ext]',

}
}, {
exclude: /\.(js|json|less|css|jsx)$/,
loader: 'file-loader',
options: {
outputPath: 'media/',
name: '[name].[hash].[ext]'
}
}
]
}]
},

Add separate extractionCSSdocumentaryloaderAnd plug-ins

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
 
 {
 test: /\.(less)$/,
 use: [
 MiniCssExtractPlugin.loader,
 {
 loader: 'css-loader', options: {
 modules: true,
 localIdentName: '[local]--[hash:base64:5]'
 }
 },
 {loader:'postcss-loader'},
 { loader: 'less-loader' }
 ]
 }
 
 new MiniCssExtractPlugin({
 filename:'[name].[contenthash:8].css'
 }),

Add compressioncssPlug-in for

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
new OptimizeCssAssetsWebpackPlugin({
cssProcessPluginOptions:{
preset:['default',{discardComments: {removeAll:true} }]
}
}),

Add a plug-in that empties the last package file with each package output file.

const CleanWebpackPlugin = require('clean-webpack-plugin')

new CleanWebpackPlugin()

Add picture compression

{
 test: /\.(jpg|jpeg|bmp|svg|png|webp|gif)$/,
 
 use:[
 {loader: 'url-loader',
 options: {
 limit: 8 * 1024,
 name: '[name].[hash:8].[ext]',
 outputPath:'/img'
 }},
 {
 loader: 'img-loader',
 options: {
 plugins: [
 require('imagemin-gifsicle')({
 interlaced: false
 }),
 require('imagemin-mozjpeg')({
 progressive: true,
 arithmetic: false
 }),
 require('imagemin-pngquant')({
 floyd: 0.5,
 speed: 2
 }),
 require('imagemin-svgo')({
 plugins: [
 { removeTitle: true },
 { convertPathData: false }
 ]
 })
 ]
 }
 }
 ]
 
 
 
 }

Add code obfuscation, decompile

var JavaScriptObfuscator = require('webpack-obfuscator');

//   ...

// webpack plugins array
plugins: [
new JavaScriptObfuscator ({
rotateUnicodeArray: true
}, ['excluded_bundle_name.js'])
],

joinPWAThe plug-in for,WorkboxPlugin

  • pwaIn fact, if this technology is to be used well, it still needs some efforts. It has its life cycle and the side effects brought about by hot updates in browsers, etc., which need careful study. You can refer to Baidu’slavasHistory of Framework Development ~
const WorkboxPlugin = require('workbox-webpack-plugin')


new WorkboxPlugin.GenerateSW({
Clients claim: true//let the browser be taken over immediately.
Skipwaiting: true//jump the queue to the front immediately after updating the sw file.
importWorkboxFrom: 'local',
include: [/\.js$/, /\.css$/, /\.html$/,/\.jpg/,/\.jpeg/,/\.svg/,/\.webp/,/\.png/],
}),

Add pre-renderingprerener

new PreloadWebpackPlugin({
rel: 'preload',
as(entry) {
if (/\.css$/.test(entry)) return 'style';
if (/\.woff$/.test(entry)) return 'font';
if (/\.png$/.test(entry)) return 'image';
return 'script';
},
include: 'allChunks'
//include: ['app']
}),

This one of minewebpackConfiguration, no matter how complex the environment, can be done

  • webpackIt is really, really important. If it is not used well, it will always be a primary front end.
  • As long aswebpackIf you don’t update it to 5, it won’t come out later.webpackThe article
  • webpack4The finale, thank you
  • In the future, there will be some cross-platform technology, nativejavascript,TS,GolangSuch as content of the article