1. Generate package.json file

npm init -y

2. Install

webpack

webpack ebpack-cli

cnpm install --save-dev webpack webpack-cli
Copy the code
/ / config/webpack.com mon. Config. Js common configuration
const path = require('path');/ / CD in turn

module.exports = {
  entry: { // Entry (project entry)
    index: './src/index.js'./ / directory
    framework: ['react'.'react-dom']./ / module
  },
  
  output: {//output (export file)
    filename: 'js/[name].[chunkhash:8].bundle.js'.// Not sure about the package name
    path: path.resolve(__dirname, '.. /dist'),//__dirname always points to the absolute path of the file
    clean: true.// Each package clears the output directory.
  }
  
  module: {//module (module handling)
    rules: [// Configure in Rules: recognize the file type and use the relevant loader for conversion...]}plugins: [ //plugin (loader can not do any processing can be assigned to plugin)
    new HtmlWebpackPlugin({ // A plug-in is a function...}})]optimization: { / / optimization...}},Copy the code

webpack-merge

webpack-merge

Configure the production/development environment through a “common” configuration.

cnpm install --save-dev webpack-merge
Copy the code

Const {merge} = require(‘webpack-merge’); Introduce the merge function to use

/ / config/ebpack. Prod. Config. Js production environment configuration
const {merge} = require('webpack-merge'); // merge (function)
const common = require('./webpack.common.config.js');// Introduce a common configuration

//merge is similar to joining strings
module.exports = merge(common, {···});Copy the code

HtmlWebpackPlugin automatically compiles HTML and introduces JS files

html-webpack-plugin

cnpm install --save-dev html-webpack-plugin
Copy the code

Const HtmlWebpackPlugin = require(‘html-webpack-plugin’); And then configure the plugins attribute to use

/ / config/ebpack. Prod. Config. Js production environment configuration
const HtmlWebpackPlugin = require('html-webpack-plugin');

//merge is similar to joining strings
module.exports = merge(common, {···// A plug-in is a function
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', \\ The HTML file name of the output after packagingtemplate: 'public/index.html', \\ use (input HTML) as a templateinject: 'body', \\ introduce js at the bottom of the body.minify: {\\[Compressed HTML file](HTTPS://github.com/jantimon/html-webpack-plugin#minification)
        removeComments: true, \\ remove commentscollapseWhitespace: true, \\ remove Spaces},})]});Copy the code

React

react react-dom react-router-dom

cnpm install --save react react-dom react-router-dom
Copy the code

Babel translation js/JSX

babel-loader @babel/preset-react @babel/preset-env @babel/core

  • Babel-loader: Use Babel and webpack to translate JavaScript files.
  • @babel/preset- React: Preset JSX
  • @babel/preset-env: Paraphrase ES2015+ syntax
  • Babel /core: the core module of Babel
cnpm install --save-dev babel-loader @babel/preset-react @babel/preset-env @babel/core
Copy the code

Json configuration file is added in the root directory. Use: ‘babel-loader’ in module.rules

/ / config/webpack.com mon. Config. Js common configuration
module. Exports = {...module: {
    rules: [{test: /\.(js|jsx)$/.// Indicates a matching rule, which is a regular expression
        use: 'babel-loader'.// Indicates the loader that will be used for processing the matching file
        exclude: /node_modules/.//exclude tells us that we do not need to translate the files in "node_modules"}}}]Copy the code

Style – loader and CSS – loader

style-loader css-loader

cnpm install --save-dev style-loader css-loader  
Copy the code

The execution sequence of Webpack Loader is from right to left. When it encounters a file with a suffix of. CSS, it will introduce the corresponding style file when it encounters “@import” and other statements. Use style-loader to generate a style tag for the final CSS code and place it in the head tag. Put style-loader before CSS-loader

/ / config/webpack.com mon. Config. Js common configuration
module. Exports = {...module: {
    rules: [the {...test: /\.css$/,
        use: [ 
          'style-loader'./ / MiniCssExtractPlugin. Loader instead
          'css-loader'}]}}Copy the code

Mini-css-extract-plugin packages CSS separate files

mini-css-extract-plugin

Const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’); , then configure plugins, and finally modify loader to use.

cnpm install --save-dev mini-css-extract-plugin
Copy the code
/ / config/webpack.com mon. Config. Js common configuration
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); / / introduction
module. Exports = {...plugins: [
    / /...
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash].css'.chunkFilename: 'css/[id].[hash].css',]}})Copy the code
/ / config/webpack.com mon. Config. Js common configuration
module. Exports = {...module: {
    rules: [{test: /\.css$/,
        use: [ 
          MiniCssExtractPlugin.loader,
          'css-loader'}]}}Copy the code

CssMinimizerWebpackPlugin compress CSS

css-minimizer-webpack-plugin

cnpm install css-minimizer-webpack-plugin --save-dev
Copy the code

Const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’); And then configure Optimization to use.

/ / config/webpack. Prod. Config. Js common configuration
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module. Exports = {...optimization: {...minimizer: [
      `... `./ / use `... 'syntax to extend existing minimizer
      new CssMinimizerPlugin(),
    ],
  },
}
Copy the code

Less – loader translated less

less less-loader

cnpm install --save-dev less less-loader
Copy the code

Set loader usage in Rules.

/ / config/webpack. Prod. Config. Js common configuration
module. Exports = {...module: {
    rules: [the {...test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'.'less-loader']},]}}Copy the code

Sass – loader translated sass

Sass -loader sass is dart sass

cnpm install sass-loader sass --save-dev
Copy the code

Set loader usage in Rules.

/ / config/webpack. Prod. Config. Js common configuration
module. Exports = {...module: {
    rules: [the {...test: /\.(sass|scss)$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'.'sass-loader']},]}}Copy the code

Postcss – loader translated CSS

postcss-loader postcss

cnpm install --save-dev postcss-loader postcss
Copy the code

Postcss is a tool for compiling CSS. It is similar to Babel for js. Use the next generation CSS syntax 2. Automatically complete browser prefixes 3. Automatically convert PX to REM 4.

1. Install a postcss plug-in. For example, CNPM install Autoprefixer –save-dev. Create postcss.config.js in the root directory. 3. Set loader in rules

//postcss.config.js #postcss configuration file
module.exports = {
  plugins: [
    require('autoprefixer') ({browsers: ['last 5 version'.'> 1%'.'ie >=8']]}});Copy the code
/ / config/webpack. Prod. Config. Js common configuration
module.exports = merge(common, {
  / /...
  module: {
    rules: [{test: /\.css$/,
        use: [ 
          MiniCssExtractPlugin.loader,
          'css-loader'.'postcss-loader'] {},test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'.'postcss-loader'.'less-loader'] {},test: /\.(scss|sass)$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'.'postcss-loader'.'sass-loader']},]},/ /...
});
Copy the code

Built-in Asset Modules to manage resources (loading images, fonts, etc.)

Set asset/ Resource in Rules to split resources into separate files, And export the url asset/inline to export the resource as dataURL (url(data:)) asset/source to export the resource as source code asset automatically selects export as a separate file or DataURL format (default 8KB)

//postcss.config.js #postcss configuration file
module. Exports = {...module: {
     rules: [the {...// Load images
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource'}, {// Load fonts
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',},],},};Copy the code

Eslint-plugin-react-hooks Enforces two hook rules

eslint eslint-plugin-react-hooks

cnpm install eslint eslint-plugin-react-hooks --save-dev
Copy the code

Set in package.json

//package.json{...// Your ESLint configuration
  "eslintConfig": {
    "plugins": [
      "react-hooks"]."rules": {
      "react-hooks/rules-of-hooks": "error".// Check the Hook rules
      "react-hooks/exhaustive-deps": "warn" // Check for effect dependencies...}}},Copy the code

React Router Dom

react-router-dom

cnpm install react-router-dom --save
Copy the code

Configure the development server to resolve the BrowserRouter refresh “cannot GET /URL” issue

/ / config/webpack.com mon. Config. Js default environment configuration
output: {
    publicPath: '/'.// The SRC prefix used to weave ...},Copy the code
/ / config/webpack. Dev. Config. Js development environment configuration...module.exports = merge(common, {···devServer: {
    historyApiFallback: true.// Default to index, solve BrowserRouter refresh "cannot GET /URL" problem...},...},Copy the code

SplitChunksPlugin code split and deduplicated

Webpack v4 + cabin

Configure optimization.splitchunks to use

/ / config/ebpack. Prod. Config. Js production environment configuration
module.exports = merge(common, {···optimization: {
    splitChunks: {
      chunks: 'all'.// Select which chunks to optimize.
      minSize: 20000.// The minimum size (bytes) of chunk to be generated.
      minChunks: 1.// The minimum number of chunks that must be shared before splitting.
      //maxSize: 0, // Try to split chunks larger than maxSize into smaller chunks.
      maxAsyncRequests: 30.// Maximum number of parallel requests when loading on demand.
      maxInitialRequests: 30.// The maximum number of parallel requests at the entry point.
      enforceSizeThreshold: 50000.// Volume thresholds and other restrictions that enforce detaching (minRemainingSize, maxAsyncRequests, maxInitialRequests) will be ignored.
      cacheGroups: {  // Defines the module that needs to be removed
        framework: {
          test: "framework".// Match the entry name
          name: "framework".enforce: true
        },
        vendors: {
          priority: -10.test: /node_modules/.// Matches the imported module in the directory
          filename: 'js/vendors/[name].[chunkhash:8].bundle.js'.// Output path
          name: "vendor".enforce: true,},},},},},});Copy the code

Js terser webpack – plugin compression

Webpack v5 bring

/ / config/ebpack. Prod. Config. Js production environment configuration
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true.minimizer: [new TerserPlugin()],
  },
};
Copy the code

Webpack-dev-server Development server

webpack-dev-server

cnpm install webpack-dev-server --save-dev
Copy the code
/ / config/webpack. Dev. Config. Js development environment configuration...const webpack = require('webpack');

module.exports = merge(common, {···devServer: {
    historyApiFallback: true.//BrowserRouter resolves the issue of refreshing "cannot GET /URL"
    contentBase: path.resolve(__dirname, '.. /dist'),
    open: true.port: 9000.compress: true.hot: true // Hot update plug-in is required to enable hot update
  },
  plugins: (...new webpack.HotModuleReplacementPlugin(), // WebPack hot update plugin]});Copy the code
// Package. json configuration of the development environment
  "scripts": {..."start": "webpack serve --inline --config ./config/webpack.dev.config.js",...},Copy the code

3. The directory

  frontend
  |- config Use webpack-merge to configure different environments
      |- webpack.common.config.js
      |- webpack.prod.config.js
      |- webpack.dev.config.js
      
  |- node_modules # depend on the package| - · · · | - publicPublic file storage address
      |- index.html
  |- src
      |- images
          |-111.jpg
      |- index.js
      |- app.js
      |- app.less
  |- babel.config.json # Babel configuration file
  |- package.json
  |- postcss.config.js


Copy the code

4. Configuration

package.json

//package.json
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1".// command: webpack --config option to specify the configuration file
    "start": "webpack serve --inline --config ./config/webpack.dev.config.js"."build": "webpack --config ./config/webpack.prod.config.js"
  },
  // Your ESLint configuration
  "eslintConfig": {
    "plugins": [
      "react-hooks"]."rules": {
      "react-hooks/rules-of-hooks": "error".// Check the Hook rules
      "react-hooks/exhaustive-deps": "warn" // Check for effect dependencies}},Copy the code

postcss.config.js

//postcss.config.js
module.exports = {
    plugins: [
      require('autoprefixer') ({browsers: ['last 5 version'.'> 1%'.'ie >=8']]}});Copy the code

Babel configuration

Root directory new babel.config.json configuration related “presets” :

//babel.config.json
{
    "presets": [["@babel/env",
        {
          "targets": {
            "edge": "17"."firefox": "60"."chrome": "67"."safari": "11.1"
          },
          "useBuiltIns": "usage"."corejs": "3.6.4 radar echoes captured."}]."@babel/preset-react"]}Copy the code

Use HtmlWebpackPlugin to use code separation (and de-duplication)

– Common configurations
/ / config/webpack.com mon. Config. Js common configuration
const path = require('path');/ / CD in turn

module.exports = {
  // Entry (project entry)
  entry: {
    index: './src/index.js'.framework: ['react'.'react-dom'],},//output (export file)
  output: {
    publicPath: '/'.// The SRC prefix used to weave 
    filename: 'js/bundle.js'.path: path.resolve(__dirname, '.. /dist'),//__dirname always points to the absolute path of the file
    clean: true.// Each package clears the output directory.
  }
  
  //module (module handling)
  // Configure in Rules: recognize the file type and use the relevant loader for conversion
  module: {
    rules: [{test: /\.(js|jsx)$/.// Indicates a matching rule, which is a regular expression
        use: 'babel-loader'.// Indicates the loader that will be used for processing the matching file
        exclude: /node_modules/.//exclude tells us that we do not need to translate the files in "node_modules"
      },
      {
        test: /\.css$/,
        use: [ 
          MiniCssExtractPlugin.loader,
          'css-loader' ,
          'postcss-loader',]}, {test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'.'postcss-loader'.'less-loader'] {},test: /\.(sass|scss)$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'.'postcss-loader'.'sass-loader'] {},// Load images
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource'}, {// Load fonts
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',]}}//plugin (loader can not do any processing can be assigned to plugin)
  plugins: [
    / /...
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash].css'.chunkFilename: 'css/[id].[hash].css',]}})Copy the code
– Configure the production environment
/ / config/ebpack. Prod. Config. Js production environment configuration
const {merge} = require('webpack-merge'); // merge (function)
const common = require('./webpack.common.config.js');// Introduce a common configuration

const HtmlWebpackPlugin = require('html-webpack-plugin');

//merge is similar to joining strings
module.exports = merge(common, {
  mode: 'production'.devtool: 'source-map'.output: { // Give the packaged JS file an indefinite name
    filename: 'js/[name].[chunkhash:8].bundle.js',},// A plug-in is a function
  plugins: [
    newHtmlWebpackPlugin({\\ automatically compiles HTML and introduces JS filesfilename: 'index.html', \\ The HTML file name of the output after packagingtemplate: 'public/index.html', \\ use (input HTML) as a templateinject: 'body', \\ introduce js at the bottom of the body.minify: {\\[Compressed HTML file](HTTPS://github.com/jantimon/html-webpack-plugin#minification)
        removeComments: true, \\ remove commentscollapseWhitespace: true, \\ remove Spaces},})],optimization: {
    splitChunks: {
      chunks: 'all'.// Select which chunks to optimize.
      minSize: 20000.// The minimum size (bytes) of chunk to be generated.
      minChunks: 1.// The minimum number of chunks that must be shared before splitting.
      //maxSize: 0, // Try to split chunks larger than maxSize into smaller chunks.
      maxAsyncRequests: 30.// Maximum number of parallel requests when loading on demand.
      maxInitialRequests: 30.// The maximum number of parallel requests at the entry point.
      enforceSizeThreshold: 50000.// Volume thresholds and other restrictions that enforce detaching (minRemainingSize, maxAsyncRequests, maxInitialRequests) will be ignored.
      cacheGroups: { // Defines the module that needs to be removed
        framework: {
          test: "framework".name: "framework".enforce: true
        },
        vendors: {
          priority: -10.test: /node_modules/.// Matches the imported module in the directory
          filename: 'js/vendors/[name].[chunkhash:8].bundle.js'.// Output path
          name: "vendor".enforce: true,}}},minimize: true./ / compression
  minimizer: [new TerserPlugin(),], / / compression}});Copy the code
– Configuring the development environment
/ / config/webpack. Prod. Config. Js development environment configuration
const path = require('path');
const {merge} = require('webpack-merge');
const common = require('./webpack.common.config.js');

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(common, {
  mode: 'development'.devtool: 'eval-source-map'.output: {
    filename: 'js/[name].[hash:8].bundle.js',},devServer: {
    contentBase: path.resolve(__dirname, '.. /dist'),
    open: true.port: 9000.compress: true.hot: true.// Hot update plug-in is required to enable hot update
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html'.inject: 'body'.hash: false
    }),
    new webpack.HotModuleReplacementPlugin(),// WebPack hot update plugin]});Copy the code