preface
In daily development, we usually choose scaffolding vue-CLI, create-React-app, etc. However, it is a basic skill to understand and master Webpack to complete project engineering development
This paper is based on:
Webpack: 4.41.2 node: 10.15.1 YARN: 1.16.0
Webpack basic configuration
1.1 Initializing the React Project
- In the new directory
yarn init
- Install act-related packages
yarn add react react-dom axios
- Install Babel
We use ES6+ syntax a lot in development, but not all browsers have the ability to convert ES6+ syntax into javascript, so that’s why we use Babel, which converts ES6+ syntax into compatible JS syntax- The installation
babel
Core package and command line tools
yarn add @babel/core
yarn add @babel/cli
- The installation
babel
Plugin for preset configuration and syntax
yarn add @babel/preset-env
ES6 syntax is supported
yarn add @babel/preset-react
React syntax support
yarn add @babel/plugin-proposal-class-properties
Support for class attributes - The editor
.babelrc
Make the installed plug-ins and configurations take effect{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "entry", "corejs": 3 } ], "@babel/preset-react" ], "plugins": [ "@babel/plugin-proposal-class-properties" ] } Copy the code
- The installation
babel-polyfill
- By default, Babel only converts syntax, but not objects. Since the original browser did not have the syntax for objects such as Promise and Symbol, we had to adjust the configuration of Babel when we needed to use it
- We can use
babel-polyfill
To solve this problem. The principle is that it implements all object and instance methods of ES6+, but the disadvantage is that it contaminates the global space and built-in objects, and may cause object conflicts with the same name
yarn add @babel/polyfill
- The installation
1.2 use webpack
- The installation
yarn add webpack webpack-cli
- new
src/index.js
As a global entryimport "@babel/polyfill" // At the beginning import React from 'react' import ReactDOM from 'react-dom' import axios from 'axios' Copy the code
- create
webpack.config.js
const path = require('path'); module.exports = { entry: './src/index.js'.// Import file output: { // Export file (compiled) filename: 'bundle.js'.path: path.resolve(__dirname, 'dist')},// babel-loader will process files according to.babelrc module: { rules: [{test: /\.js$/, use: 'babel-loader'}}};Copy the code
yarn add babel-loader
1.3 integrated webapck – dev – server
yarn add webapck-dev-server
Quickly set up the local operating environmentyarn add html-webpack-plugin
Generate HTML in memory- Modify the
package.json
"scripts": { "dev": "webpack-dev-server --open --port 8081 --contentBase src --hot"."build": "webpack --mode production"."test": "echo \"Error: no test specified\" && exit 1" }, Copy the code
- Modify the
webpack.config.js
const path = require('path'); const htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: path.join(__dirname, './src/index.js'), output: { filename: 'bundle.js'.path: path.resolve(__dirname, 'dist')},plugins: [ new htmlWebpackPlugin({ template: path.join(__dirname, './index.html'), filename: 'index.html'})].module: { rules: [{test: /\.js$/, use: 'babel-loader'}},mode: 'development' }; Copy the code
- After integrating webpack-dev-server and http-webpack-plugin, accessing localhost:8081(HTML page in memory) will cause an error when importing CSS, images, less, fonts, etc files in HTML, which needs to be handled in a separate way
yarn add less less-loader css-loader style-loader file-loader
- Modify the
webpack.config.js
rules: [ {test: /\.js$/, use: 'babel-loader'}, {test: /\.css$/, use: ['style-loader'.'css-loader'] {},test: /\.less$/, use: ['style-loader'.'css-loader'.'less-loader'] {},test: /\.(eot|svg|ttf|woff|woff2|png)\w*/, use: 'file-loader'}]Copy the code
- Modified index. HTML
<script src="bundle.js"></script> Copy the code
1.4 Configuring the React Route
yarn add react-router react-router-dom
- In the configuration
react-router
Cannot access the page by entering the address or refreshing the child route
Cause: We configure only front-end routes through the React-Router, but WebPack does not recognize the front-end routes. If the server cannot match the path, it automatically forwards it to the 404 interface
Address:webpack.config.js
In the configuration:// Webpack returns to the home page by default if the path cannot be matched // This is controlled by the front-end route devServer: { historyApiFallback: true,}Copy the code
1.5 Distinguish between development environment and production environment
- in
webpack.config.js
To distinguish between development mode and production mode:const path = require('path'); module.exports = function(env, argv){ // 1. Use argv to determine whether the environment is development or production const isEnvDevelopment = argv.mode === 'development'| |! argv.mode;const isEnvProduction = argv.mode === 'production'; return{ // 2. Configure mode and devtool according to the environment mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development'.devtool: isEnvProduction ? 'source-map' : isEnvDevelopment && 'cheap-module-source-map'.entry: './src/index.js'.output: { filename: 'bundle.js'.path: path.resolve(__dirname, 'dist')},module: { rules: [{ test: /\.js$/, exclude: /node_modules/, use: 'babel-loader'}}}}]Copy the code
1.6 Development and Configuration
Source Map
: maps object code to source code
After passing through the wrapper, the browser executes object code. In development, when an error occurs, we want the error reported to be directly located in the original code, rather than display the target code, so we need to configuresource map
const path = require('path'); const htmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); module.exports = function(env, argv){ const isEnvDevelopment = argv.mode === 'development'| |! argv.mode;const isEnvProduction = argv.mode === 'production'; return{ mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development'.devtool: isEnvProduction ? 'source-map' : isEnvDevelopment && 'cheap-module-source-map'./ / modify entry: path.join(__dirname, './src/index.js'), output: { filename: 'bundle.js'.path: path.resolve(__dirname, 'dist'),},plugins: [ new htmlWebpackPlugin({ template: path.join(__dirname, './public/index.html'), filename: 'index.html'})].module: { rules: [{test: /\.js$/, use: 'babel-loader'}, {test: /\.css$/, use: ['style-loader'.'css-loader'] {},test: /\.less$/, use: ['style-loader'.'css-loader'.'less-loader'] {},test: /\.(eot|svg|ttf|woff|woff2|png)\w*/, use: 'file-loader'}},devServer: { historyApiFallback: true.contentBase: './dist'.hot: true}}}Copy the code
- Eslint and Prettier
- The purpose of Eslint is to check that code is conforming to the specification and give a hint
- 3, Prettier usually works with ESlints, where Prettier can detect code specification but not completely, while Prettier does not detect code specification
yarn add eslint babel-eslint
yarn add eslint-config-airbnb
yarn add eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react
- create
.eslintrc.js
module.exports = { // Parser is used to specify a parser. Eslint cannot parse ES6 syntax by itself and needs to be converted to babel-esLint "parser": "babel-eslint".// extends represents an Airbnb based specification "extends": ["airbnb"].// env tells ESLint not to use undefined if browser and ES6 objects are encountered "env": { browser: true.es6: true,},// rules is used to specify extended specification rules that override the configuration of Airbnb rules "rules": { 'react/jsx-filename-extension': [1, {extensions: ['.js']}], 'react/prop-types': 0.'react/prefer-stateless-function': 0.'react/no-array-index-key': 0.'no-console': 0.'jsx-ally/anchor-is-valid': 0.'react/destructuring-assignment': 0.'react/jsx-one-expression-per-line': 0}}Copy the code
- Performed manually
eslint
yarn eslint src/
Check the js file under SRC /npx eslint --fix src/
Autofix is not standardized and only lists those that cannot be autofixed
- Configuring a Path Alias
In development, we often configure path aliases to quickly locate files, improve efficiency and file import accuracy, usually with@
To represent thesrc
directoryresolve: { alias: { The '@': path.resolve('src')}}Copy the code
- Modular CSS
- Simple to use
Style - loader, CSS - loader
While it is possible to introduce CSS style files in JS, the following problems arise:- Global pollution:
CSS
File selectors are global, different file selectors of the same name, according tobuild
The sequence in the generated file, the later style overrides the previous style - The selector is complex and the naming rules are confusing
- Global pollution:
- After the use of CSS Module Module processing, for each JS file, its introduced CSS file is only effective for this file, which is similar to VUE
scoped
Attributes play a role - Modify the
webpack.config.js
{test: /\.css$/, use: ['style-loader'.'css-loader? modules']}, Copy the code
- Example:
- Principles of the CSS Module: each className is converted (plus hash value) according to certain rules to ensure its uniqueness, but only className and id can be converted
- Simple to use
- CSS compatibility Processing Enables the CSS to add different prefixes for different browsers, resolving browser compatibility problems
yarn add postcss-loader autoprefixer
- configuration
postcss.config.js
module.exports = { plugins: { 'autoprefixer': {}}};Copy the code
- Modify the
webpack.config.js
// The postCSs-loader should be placed before the less-loader, and converted from less to CSS, and then processed with postCSS module: { rules: [{test: /\.js$/, exclude: /node_modules/, enforce: "pre".use: 'babel-loader'}, {test: /\.css$/, include: [path.resolve(__dirname, 'src/styles'), /node_modules/].use: ['style-loader'.'css-loader'.'postcss-loader'] {},test: /\.css$/, exclude: [path.resolve(__dirname, 'src/styles'), /node_modules/].use: ['style-loader'.'css-loader? modules'.'postcss-loader'] {},test: /\.less$/, include: [path.resolve(__dirname, 'src/styles'), /node_modules/].use: ['style-loader'.'css-loader'.'postcss-loader'.'less-loader'] {},test: /\.less$/, exclude: [path.resolve(__dirname, 'src/styles'), /node_modules/].use: ['style-loader'.'css-loader? modules'.'postcss-loader'.'less-loader'] {},test: /\.(eot|svg|ttf|woff|woff2|png)\w*/, use: 'file-loader'}, { test: [/\.bmp$/./\.gif$/./\.jpe?g$/./\.png$/./\.svg$/].loader: 'url-loader'.options: { limit: 10000}}],},Copy the code
1.7 Production Environment Configuration
- copy
webpack.config.js
, rename towebpack.config.prod.js
- The editor
package.json
"scripts": { "dev": "webpack-dev-server --port 8081 --mode development"."build": "webpack --config webpack.prod.config.js --mode production"."watch": "webpack --watch"."test": "echo \"Error: no test specified\" && exit 1" }, Copy the code
- Modify the
webpack.prod.js
deletedevServer
configuration
At the end
To do this, we can use the following commands: yarn Run dev development environment to start the project, on port 8081 access yarn Run Build package compile project file, generate dist directory for some optimization configuration of Webpack, such as: Code separation, file volume compression, configuration caching, and hot updates using HMR modules in development environments are not covered, or will continue to be updated