This is a series of articles on the basic of WebPack js optimization, JS compatibility handling, how to use WebPack to make some browsers incompatible with ES6/ES7,React JSX escape to ES5, how to use ESLint code verification in the development environment for a unified style. HTML compression, and other webpackage 5 configurations such as resolve, noParse, IgnorePlugin, output.library, output. libraryTarget.
Official start:
Prepare the skills
Basic NodeJS knowledge and NPM instructions
Note: the webpack version used in this series is: “webpack”: “^5.68.0”,
“Webpack – cli” : “^ 4.9.2”,
JS Compatibility processing
Use babel-loader to handle JS compatibility issues
Babel is actually a platform for compiling JavaScript. It can escape ES6/ES7,React JSX to ES5
1. If it’s just basic JS compatibility, just add presets to babel-loader and use @babel/preset-env for some general syntax-compatibility
Use @babel/runtime-corejs3 and @babel/plugin-transform-runtime before webPack4 use @babel/polyfill before webPack4
The downside of this is that I only solve part of the compatibility problem, but I import all the compatibility code, which is too bulky
3, need to do compatibility processing to do: as needed to load use — “core-js”
Install @babel/core and babel-loader @babel/present-env
Install dependencies
- Babel-loader uses Babel and Webpack to translate JavaScript files
- @babel/@babel/coreBabel compilation core package
- babel-preset-env
- React can be used instead of the @babel/@babel/preset-reactReact preset
- @babel/plugin-proposal-decorators compile class and object decorators into ES5
- @babel/plugin-proposal-class-properties Transforms static class properties and initializes properties declared by syntax using properties
npm i babel-loader @babel/core @babel/preset-env @babel/preset-react -D
Copy the code
npm i @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-property-in-object @babel/plugin-proposal-private-methods -D
Copy the code
2. Modify the webpack.config.js configuration file
{ test: /.jsx? $/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [['@babel/preset-env', {// Load useBuiltIns as needed: 'usage', // Specify core-JS version corejs: {version: Targets: {Chrome: '60', Firefox: '60', IE: '9', Safari: '10', edge: '17' } }], '@babel/preset-react' ], plugins: [ ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-private-property-in-object", { "loose": true }], ["@babel/plugin-proposal-private-methods", { "loose": true }], ["@babel/plugin-proposal-class-properties", { loose: true }], ] } } },Copy the code
The. / SRC/index. Js modified
// ./src/index/js import dataJson from './data.json'; import './index.css'; import './index.less'; import './index.scss'; import './assets/icons/iconfont.css'; Function add(x, y) {return x + y; } console.log(add(1, 2)); console.log(dataJson, 'dataJson'); // js const logo = require('./assets/ vite.png'); const img = new Image(); img.src = logo; document.body.appendChild(img); class Person { constructor() { this.name = 'hello' } setName(name) { this.name = name } } let p1 = new Person(); P1. Elegantly-named setName (' webpack5 series'); console.log(p1.name) const total = [1, 2, 3, 4].reduce((a, b) => a + b) console.log('total', total)Copy the code
New jsconfig. Json
{
"compilerOptions": {
"experimentalDecorators": true
}
}
Copy the code
Run webpack
The reduce method, which previously did not support arrays under IE11, is now compatible
ESLint code verification
Syntax check ESLint
Rule:cloud.tencent.com/developer/c…
ESlint syntax checks configuration instructions
Install eslint-webpack-plugin :(this plugin uses eslint to find and fix problems in JavaScript code.)
Note: only check your own source code, third-party libraries do not have to check
Note: If you don’t have ESLint >= 7 installed, you’ll need to install it via NPM first:
Install and configure the eslint-webpack-plugin
1) install eslint-webpack-plugin :(this plugin uses eslint to find and fix problems in JavaScript code.)
NPM install eslint-webpack-plugin –save-dev note: if eslint >= 7 is not installed, you will need to install it via NPM:
npm install eslint --save-dev
Copy the code
2) Configuration: webpack.config.js file:
const ESLintPlugin = require('eslint-webpack-plugin'); Plugins: [new ESLintPlugin({exclude:'node_modules', // exclude eslint from node_modules folder fix:true // automatically fix JS format errors})],Copy the code
Setting check Rules
Js Style Guide library: Airbnb
By setting the rule of plug-in: eslint – config – reality – base: refer to the official document: www.npmjs.com/package/esl…
The default export includes all ESLint rules, including ECMAScript 6+. It requires esLint and eslint-plugin-import
Eslint-import-resolver-webpack (this is required if an alias is configured in webpack.config.js and an alias is used when importing)
use
1, install,
npm i eslint-config-airbnb-base eslint-plugin-import @babel\eslint-parser --save-dev
Copy the code
2) Configuration: two ways:
Method 1:.eslintrc.js file add:
module.exports = {"extends": "airbnb-base"
}
Copy the code
Method 2: Package. json file to add: // Inherit the Airbnb style. For details, you can check the airbnb style in Github
"eslintConfig": { "extends": "airbnb-base"}
Copy the code
Run webpack
Warning Unexpected console statement no-console, you can add // eslint-disable-next-line to the js file above the console.log() output You can ignore the warning prompt for the output statement.
No – indef changes
Json file to add: // Inherit airbnb style. For details, check airbnb repository on Github
"eslintConfig": {
"extends": "airbnb-base",
"env": {
"browser": true
}
}
Copy the code
To the.eslintrc.js file add:
module.exports = {
"parser": "@babel/eslint-parser",
"extends": "airbnb-base",
"parserOptions": {
"ecmaVersion": 2015,
"requireConfigFile": false,
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"impliedStrict": true,
"classes": true
}
},
"rules": {
"semi": "error",
"no-console": "off",
"linebreak-style": "off",
"eol-last": "off"
//"indent":["error",2]
},
"env": {
"browser": true,
"node": true
}
}
Copy the code
Eslintrc.js will not report errors during compilation, use.eslintrc.js because it also added the closing error “no-console”
No use of babel-ESLint, the deprecated babel-esLint parser does not support the ES6 module and can be updated
Install React
npm i eslint-plugin-react eslint-plugin-react-hooks and eslint-plugin-jsx-a11y -D
Copy the code
Ps: Note that we no longer use eslint-loader but eslint-webpack-plugin instead.
Js compressed
- Terser-webpack-plugin is a plug-in that optimizes and compresses JS resources
Mode :’production’ will automatically start a series of plugins, including automatic compression
use
1, install,
npm i terser-webpack-plugin -D
Copy the code
2. Modify webpack.config.js
reference
const TerserPlugin = require('terser-webpack-plugin');
Copy the code
use
optimization: { minimizer: [ new CssMinimizerWebpackPlugin(), new TerserPlugin(), ], minimize: // If you also want to enable CSS optimizations in your development environment, set optimization.minimize to true:},Copy the code
HTML compression
Or the previous HtmlWebpackPlugin to add related attributes can be
Add minify to new HtmlWebpackPlugin in webpack.config.js
New HtmlWebpackPlugin({// copy the './index.html' file and automatically import all the resources (js/ CSS) that package the output. Template: './index.html', minify: CollapseWhitespace: true, // remove comment removeComments: true}}),Copy the code
Run webpack
See code compression in Build \index.html
Image optimization
1. We also put the pictures in a folder
Test: /.(jpe? G | PNG | | GIF SVG) $/, type: "asset", the generator: {/ / and the output. AssetModuleFilename is the same, the time of this writing is introduced into will also add the filename path: 'imgs/[name].[hash:6][ext]' }, }Copy the code
Run webpack
Check the build folder and find an IMGS folder containing all the images we introduced
Viewing the browser also works
2. We can also change output
Output: {// output name string (default) filename template of entry chunk filename: 'js/[name].[contenthash:10].js', // the output path __dirname nodejs variable represents the directory of the current file. The absolute path must be an absolute path (using node.js's path module) path: resolve(__dirname, 'build'), assetModuleFilename:'imgs/[contenthash:6][ext]' }Copy the code
Ps: What is the priority of the first and second methods?
Set in generator in loader
The generator: {/ / and the output assetModuleFilename is the same, the time of this writing is introduced into will also add the filename path: '/ imgs [name]. [6] hash: [ext]'}Copy the code
The priority is a little higher
3, we know that when the image is smaller than a certain size, base64 image is used to reduce the request
Test: /.(jpe? G | PNG | | GIF SVG) $/, type: "asset", / / / / parsing parser: {/ / base64 conditions dataUrlCondition: {maxSize: 25 * 1024, / / 25 KB}}, the generator: {/ / and the output. AssetModuleFilename is the same, the time of this writing is introduced into will also add the filename path: 'imgs/[name].[hash:6][ext]' }, }Copy the code
If type: “asset/inline”, the resource will be loaded inline and packed, but the image size will be base64 and the HTML will be too bulky.
Type: “asset”, which is automatic, determines the size of the resource by default. If the resource file is larger than 8K, it is asset/resource. If the resource file is smaller, it is “asset/inline”.
Run webpack
Check the build/ IMGS folder and notice that an image file is missing
Viewing a browser
Fewer images are displayed in Base64 format because they are smaller than the size we set.
resolve
1, extensions,
If you specify extension, you don’t need to add a file extension to require or import
Webpack attempts to parse modules from left to right in the extensions configuration array
resolve: {
extensions: [".js",".jsx",".json",".css"]
}
Copy the code
Note that:
- High frequency file name suffix in front;
- After manual configuration, the default configuration will be overwritten
If you want to keep the default configuration, you can use… The extended operator represents the default configuration, for example
resolve: {
extensions: ['.js', '...'],
}
Copy the code
2, alias
Configuring aliases speeds up WebPack’s search for modules
Resolve :{// Alias :{'@': resolve(' SRC '), 'components': resolve(' SRC /components'),}}Copy the code
use
// use SRC alias @import '@/index.css'Copy the code
3 、modules
Configure the directory in which webpack looks for third-party modules. By default, only node_modules is used to look for third-party modules. If you have modules in a folder in your project that are frequently imported and don’t want to write a long path, you can simplify this by configuring resolve.modules.
-
For modules that declare dependencies directly (like react), Webpack does a path search similar to Node.js, searching the node_modules directory
-
This directory is just for use
resolve.modules Copy the code
Default configuration for field configuration
resolve: { modules: ['node_modules'], } Copy the code
If you can be sure that all third-party dependencies in your project are in node_modules in the project root directory
resolve: { modules: [resolve(__dirname, 'node_modules')], } Copy the code
4、 mainFields
Some third-party modules provide multiple pieces of code, such as bootstrap. You can view the package.json file of bootstrap:
{
"style": "dist/css/bootstrap.css",
"sass": "scss/bootstrap.scss",
"main": "dist/js/bootstrap",
}
Copy the code
Resolve. MainFields default configuration is [‘browser’, ‘main’], which first looks for the brower field in the corresponding dependency package.json, and if not, looks for the main field.
For example: import ‘bootstrap’ By default, find the file specified in the main field of the corresponding dependency package.json, dist/js/bootstrap.
If we want import ‘bootsrap’ to find CSS files by default, we can configure resolve.mainFields to:
module.exports = {
//....
resolve: {
mainFields: ['style', 'main']
}
}
Copy the code
When package.json is not present in the directory, we say that the index.js file in the directory will be used by default, which can also be configured
Resolve: {mainFiles: ['index'], // You can add other default file names},Copy the code
Ps: By default, package.json files are found by the name of the main field in the file
Resolve: {// set target === "web" or target === "webworker". ['browser', 'module', 'main'], // target values are other, mainFields default values are: mainFields: ["module", "main"],}Copy the code
5, resolveLoader
ResolveLoader has the same set of attributes as the Resolve object above, but is only used to resolve the Loader package for WebPack.
In general, keep the default configuration, but if you have a custom Loader, you need to configure it, it may not be able to find the Loader error
noParse
module.noParse
Field that can be used to configure which module file contents do not need to be parsed- Large third-party libraries that do not need to resolve dependencies (i.e., no dependencies) can be configured through this field to improve the overall build speed
Import mechanisms such as import, require, and define cannot be used in module files that are ignored using noParse
module.exports = { // ... The module: {noParse: / jquery | lodash /, / / / / or regular expressions using the function noParse (content) {return/jquery | lodash /. The test (content)},}}Copy the code
IgnorePlugin
IgnorePlugin is used to ignore specific modules so that WebPack does not pack those specified modules
1 src/index.js
import moment from 'moment';
import 'moment/locale/zh-cn'
console.log(moment().format('MMMM Do YYYY, h:mm:ss a'));
Copy the code
2 webpack.config.js
import moment from 'moment';
console.log(moment);
new webpack.IgnorePlugin({
//A RegExp to test the context (directory) against.
contextRegExp: /moment$/,
//A RegExp to test the request against.
resourceRegExp: /^./locale/
new MiniCSSExtractPlugin({
filename:'[name].css'
})
Copy the code
- The first is a regular expression that matches the path of the introduced module
- The second is the name of the directory in which the module is matched
Cross domain, server proxy
We know that in the development phase, we call other third-party API interfaces, if different domains will appear cross-domain, we can not develop. You can’t use mock data forever, and you still need a real interface for both the front and back.
Change the devServer
// DevServer is used to automate (automatically compile, automatically open browser, automatically refresh browser...) NPX webpack-dev-server = NPX webpack-dev-server = NPX webpack-dev-server DevServer: {// NPX webpack-dev-server: {// NPX webpack-dev-server: {// NPX webpack-dev-server: Resolve (__dirname, 'build'), // enable gzip compress: true, // port: 8888, // automatically open browser: true, // enable HMR function hot: Proxy: {'/ API ': {target: 'http://localhost:5000', pathRewrite: {'/ API ': {target: 'http://localhost:5000', pathRewrite: { '^/api': '' } } } }Copy the code
onBeforeSetupMiddleware
-
OnBeforeSetupMiddleware can be used to intercept partial requests returning specific content, or to implement simple data mocks, before being processed by the Webpack-dev-server static resource middleware.
devServer: { onBeforeSetupMiddleware(devServer){// express() devServer.app.get('/api/users', (req, res) => { res.json([{ id: 1 }, { id: 2 }]); }); }}Copy the code
webpack-dev-middleware
Webpack-dev-middleware is a middleware that provides webpack-dev-server static service capabilities in Express
npm install webpack-dev-middleware --save-dev
const express = require('express');
const app = express();
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackOptions = require('./webpack.config');
webpackOptions.mode = 'development';
const compiler = webpack(webpackOptions);
app.use(webpackDevMiddleware(compiler, {}));
app.listen(3000);
Copy the code
- The advantage of webpack-dev-server is that it is relatively simple to install dependencies and run commands directly
- While the use of
webpack-dev-middleware
The advantage of webPack-dev-Server is that you can quickly add webpack-Dev-server functionality to existing Express code, while using Express to add additional functionality as needed, such as mock services, proxy API requests, and so on
Thank you
This is the end of this introduction, then will be sorted out webpack knowledge system content sharing, enjoy looking forward to, thank you for reading ~~