土拨鼠公主

Webpack学习笔记

第1章 Webpack简介

学习视频:https://www.bilibili.com/video/BV1e7411j7T5?p=1&spm_id_from=pageDriver

1.1Webpack是什么

Webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler).
在Webpack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理.
它根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle).

1.2Webpack五个核心概念

  • 1.2.1 Entry
    image

  • 1.2.2 Output
    image

  • 1.2.3 Loader
    image

  • 1.2.4 Plugins
    image

  • 1.2.5 Mode
    image

第2章webpack初体验

image

image

image

2.1 webpack打包样式资源(css,less)

/*
    webpack.config.js webpack的配置文件
    作用指示:webpack 干哪些活 (当你运行webpack 指令时,会加载里面的配置)
    所有构建工具都是基于nodejs平台运行的~ 模块化默认采用commonjs.
*/
// resolve 用来拼接绝对路径的方法
const { resolve } = require('path');
module.exports = {
  // webpack配置
  // 入口起点
  entry: './src/index.js',
  output: {
    // 输出文件名
    filename: 'built.js',
    // 输出路径
    // __dirname nodejs的变量,代表当前文件的目录绝对路径
    path: resolve(__dirname, 'build'),
  },
  // loader的配置
  module: {
    rules: [
      // 详细loader配置
      {
        test: /\.css$/,
        use: [
          // use数组中loader执行顺序:从右到左,从下到上依次执行
          // 创建style标签,将js中的样式资源插入进去,添加到head中生效
          'style-loader',
          // 将css文件变成commonjs模块加载js中,里面内容是样式字符串
          'css-loader',
        ],
      },
      {
        test:/.\less$/,
        use:[
          'style-loader',
          'css-loader',
          // 将less文件编译成css文件
          // 需要下载less-loader和 less
          'less-loader'
        ]
      }
    ],
  },
  // plugins 的配置
  plugins: [],
  // 模式
  mode: 'development',
  // mode:'production'
};

2.2 webpack打包html资源

/*
 loader: 1.下载 2.使用(配置loader)
 plugins:1.下载 2.引用 3.使用
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module:{
    rules:[
      // loader配置
    ]
  },
  plugins:[
    // plugins的配置
    // html-webpack-plugin
    // 功能:默认会创建一个空的html,自动引入打包输出的所有资源(JS/CSS)
    new HtmlWebpackPlugin({
      // 复制'./src/index.html' ,并自动引入打包输出的所有资源(JS/CSS)
      template:'./src/index.html'
    })
  ],
  mode:'development'
};

2.3 打包图片资源

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          // 要使用多个loader处理用use
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      {
        // 问题:默认处理不了html中的img图片 (webpack5时省略该图片loader配置,能默认处理而不需要该处配置)
        // 处理图片资源
        test:/\.(jpg|png|gif)$/,
        // webpack5已经弃用url-loader
        // 使用一个loader
        // 下载url-loader file-loader
        loader:'url-loader',
        options:{
          // 图片大小小于8kb,就会被base64处理
          // 优点:减轻请求数量(减轻服务器压力)
          // 缺点:图片体积会更大(文件请求速度更慢)
          limit:8*1024,
          // 问题:因为url-loader默认使用es6模块化解析,而htm-loader引入图片是commonjs
          // 解析时会出问题:[object Module]
          // 解决:关闭url-loader的es6模块化,使用commonjs解析
          esModule:false,
          // 给图片重命名,[hash:10]:取图片的hash的前10位,[ext]:取文件原来扩展名
          name: '[hash:10].[ext]'
        }
      },
      {
        test:/\.html$/,
        // 处理html文件的img图片(如则引入img,从而能被url-loader处理)
        loader:'html-loader'
      }
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  mode: 'development',
  // mode:'production'
};

2.4 打包其他资源(字体)

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 入口
  entry: './src/index.js',
  // 出口
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  // loader配置
  module: {
    rules: [
      // 打包css
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      // 打包其他资源(除了html/css/js以外的资源)
      {
        // 排除css/js/html
        // exclude: /\.(css|js|html)$/,
        // webpack file-loader弃用
        //loader:'file-loader'
        test:/\.ttf|eot|woff2?$/, // webpack5打包字体资源
        type: 'asset/resource',
        generator: {
          filename: 'font/[name].[hash:6][ext]',
        },
      },
    ],
  },
  //  插件
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  // 开发环境/生产环境
  mode: 'development',
  // mode:'production'
};

2.5 使用devServer

/*
  开发环境配置:能让代码运行
    运行项目指令:
      webpack 会将打包结果输出出去
      npx webpack serve 只会在内存中打包编译,没有输出
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 入口
  entry: './src/index.js',
  // 出口
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  // loader配置
  module: {
    rules: [
      // 打包css
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      // 打包其他资源(除了html/css/js以外的资源)
      {
        // 排除css/js/html
        // exclude: /\.(css|js|html)$/,
        // webpack file-loader弃用
        //loader:'file-loader'
        test: /\.ttf|eot|woff2?$/, // webpack5打包字体资源
        type: 'asset/resource',
        generator: {
          filename: 'font/[name].[hash:6][ext]',
        },
      },
    ],
  },
  //  插件
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  // 开发环境/生产环境
  mode: 'development',
  // mode:'production'

  // 开发服务器 devServer: 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
  // 特点:只会在内存中编译打包,不会有任何输出
  // 启动devServer指令为:npx webpack serve
  // 下载:webpack-dev-server
  devServer: {
    // 项目构建够路径
    static: {
      directory: resolve(__dirname, 'build'),
    },
    // 启动gzip压缩
    compress: true,
    // 所启动服务器的端口号
    port: 3003,
    // 自动打开浏览器
    open: true,
  },
};

第3章webpack开发环境的基本配置

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        // 使用资源模块处理字体
        test: /\.(eot|svg|ttf|woff|woff2)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[hash:5][ext]',
        },
      },
      {
        // 使用资源模块处理CSS
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        // 使用资源模块处理less
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      {
        // 使用资源模块处理图片
        test: /\.(jpg|png|gif)$/i,
        type: 'asset',
        parser: {
          // 转base64条件
          dataUrlCondition: {
            maxSize: 8 * 1024, //8kb
          },
          generator: {
            filename: 'images/[name][ext]',
          },
        },
      },
      {
        // 处理html中的图片
        test: /\.html$/,
        loader: 'html-loader',
        options:{
          esModule:false
        }
      },
    ],
  },
  plugins: [
    // 处理html资源
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  mode: 'development',
  devServer: {
    // 项目构建目录
    static:{
      directory:resolve(__dirname,'build'),
    },
    compress:true,  // gzip压缩
    open:true,      // 自动打开浏览器
    port:3003,      // 端口

  },
};

第4章 webpack生产环境基本介绍

4.1 将CSS提取成单独文件

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 创建style标签,将样式放入
          // 'style-loader',
          // 这个loader取代style-loader.作用:提取js中的css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件整合到js文件中
          'css-loader',
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    // 提取CSS成单独文件
    new MiniCssExtractPlugin({
      // 对输出的CSS文件进行重命名
      filename: 'css/built.css',
    }),
  ],
  mode: 'development',
};

4.2 CSS兼容性处理

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// 设置nodejs环境变量
process.env.NODE_ENV = 'development';

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          /*
            兼容性处理
            postcss:postcss-loader和postcss-preset-env
            识别对应的环境加载对应的配置
            该插件帮postcss找到package.json中的browserslist里面的配置,通过配置加载指定的css兼容性样式
            "browserslist":{
                             * 开发环境 :设置node环境变量 process.env.NODE_ENV = development
                              "development": [
                                  "last 1 chrome version",  // 兼容最近的一个chrome版本
                                  "last 1 firefox version",
                                  "last 1 safari version"
                              ],
                              * 生产环境: 默认是看生产环境
                              "production":[
                                  ">0.2%", 
                                  "not dead", // 不要已经丢弃的浏览器
                                  "not op_mini all" 不要所有的欧朋浏览器
                              ]
                          }
          */
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions:{
                plugins: [require('postcss-preset-env')()],
              }
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    new MiniCssExtractPlugin({
      filename: 'css/built.css',
    }),
  ],
  mode: 'development',
};

4.3 CSS压缩

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');

// 设置nodejs环境变量
// process.env.NODE_ENV = 'development';

// optimize-css-assets-webpack-plugin
module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 将CSS提取成单独文件
          MiniCssExtractPlugin.loader,
          'css-loader',
          // 兼容性处理
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [require('postcss-preset-env')()],
              },
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    new MiniCssExtractPlugin({
      filename: 'css/built.css',
    }),
    // 压缩文件(webpack5采用该插件:CssMinimizerWebpackPlugin)
    new OptimizeCssAssetsWebpackPlugin(),
  ],
  mode: 'development',
};

4.4 Eslint语法检查

// webpack.config.js
const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
    mode: "development",
    entry: './src/index.js',
    // devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist',
        compress: true,
        open: false
    },
    output: {
        publicPath: '/',
        // 指定打包后输出的文件名
        filename: 'js/app.[contenthash:10].js',
        // 指定打包后输出的目录
        path: path.resolve(__dirname, 'dist')
    },
    resolve: {
        alias: {
            # !!!!!!注意如果配置了此处 要安装步骤5的插件!!!!!!!! #
            "@": path.resolve(__dirname, 'src')
        }
    },
    module: {
        rules: [
         
        ]
    },
    plugins: [
        #使用 配置项都可以在eslint-webpack-plugin的github上找到
        new ESLintPlugin({
		    // 启用 ESLint 自动修复特性
            fix: true,
			// 指定需要检查的扩展名。
            extensions: ['js', 'json', 'coffee'],
			// 指定需要排除的文件及目录。必须是相对于 options.context 的相对路径
            exclude: '/node_modules/'
        }),
    ]
};
// package.json
"eslintConfig": {
    "extends": "airbnb-base",
    #!!!!如果没使用alias下面的不用配置!!!!!
    "settings": {
      "import/resolver": {
        "webpack": {
          "config": "webpack.config.js"
        }
      }
    }
  }

4.5 js兼容性处理

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      /*
        js兼容性处理:babel-loader @babel/core  @babel/preset-env
        1. 基本js兼容性处理 --> @babel/preset-env
          问题: 只能转换基本语法,如promise不能转换
        2. 全部js兼容性处理 -->@babel/polyfill不用写配置,引入即可(下载了,只需要引入即可:import '@babel/polyfill'; )
        问题:我只要解决部分的兼容性问题,但是将所有的兼容性代码引入,体积太大了
        3.需要做兼容性处理的就做:按需加载 --> core-js  
      */
      {
        test: /\.js$/,
        // 排除第三方库
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 预设:指示babel做怎么样的兼容性处理
          presets: [
            [
              '@babel/preset-env',
              {
                // 按需加载
                useBuiltIns: 'usage',
                // 指定core-js版本
                corejs: {
                  version: 3,
                },
                // 指定兼容性做到哪个版本浏览器
                targets: {
                  chrome: '60',
                  firefox: '60',
                  ie: '9',
                  edge: '17',
                  safari: '10',
                },
              },
            ],
          ],
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  module: 'development',
};

4.6 压缩html和js

js压缩

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  // 生产环境下会自动压缩js代码
  module: 'production',
};

html压缩

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // 压缩html
      minify: {
        // 移出空格
        collapseWhitespace: true,
        // 移出注释
        removeComments: true,
      },
    }),
  ],
  // 生产环境下会自动压缩js代码
  module: 'production',
};

第5章webpack生产环境的基本配置

const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');

// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';

// 复用loader
const commonCssLoader = [
  // 这个loader取代style-loader.作用:提取js中的css成单独文件
  MiniCssExtractPlugin.loader,
  // 将css文件整合(加载)到js文件中
  'css-loader',
  // 兼容性处理
  {
    // 还需要在package.json中定义browserslist
    /*"browserslist":{
                             * 开发环境 :设置node环境变量 process.env.NODE_ENV = development
                              "development": [
                                  "last 1 chrome version",  // 兼容最近的一个chrome版本
                                  "last 1 firefox version",
                                  "last 1 safari version"
                              ],
                              * 生产环境: 默认是看生产环境
                              "production":[
                                  ">0.2%", 
                                  "not dead", // 不要已经丢弃的浏览器
                                  "not op_mini all" 不要所有的欧朋浏览器
                              ]
                          }
              */
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()],
    },
  },
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  modules: {
    rules: [
      {
        test: /\.css$/,
        use: [...commonCssLoader],
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, 'less-loader'],
      },
      /*
        正常来讲,一个文件只能被一个loader处理,
        当一个文件要被多个loader处理,name一定要指定loader执行的顺序
        先执行eslint 在执行babel
      */
      {
        // js语法检查  在package.json中添加eslintConfig -->airbnb
        /*
        在package.json中添加eslintConfig -->airbnb
        "eslintConfig": {
                  "extends": "airbnb-base"
                   }
        */
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true,
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                // 按需加载
                useBuiltIns: 'usage',
                // 指定core-js版本
                corejs: {
                  version: 3,
                },
                // 指定兼容性做到哪个版本浏览器
                targets: {
                  chrome: '60',
                  firefox: '60',
                  ie: '9',
                  edge: '17',
                  safari: '10',
                },
              },
            ],
          ],
        },
      },
      {
        // 处理图片资源
        test: /\.(jpg|png|gif)/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          outputPath: 'imgs',
          esModule: false,
        },
      },
      {
        // 处理HTML资源中的图片
        test: /\.html/,
        loader: 'html-loader',
      },
      {
        // 处理其他资源
        exclude: /\.(js|css|less|html|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          output: 'media',
        },
      },
    ],
  },
  plugins: [
    // 提取CSS成单独文件
    new MiniCssExtractPlugin({
      // 对输出的CSS文件进行重命名
      filename: 'css/built.css',
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // html压缩 移出空格,注释
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: 'production',
};

第5章webpack优化配置

5.1 开发环境性能优化

  • 优化打包构建速度
  • 优化代码调试

5.2 生产环境性能优化

  • 优化打包构建速度
  • 优化代码运行的性能

5.3 HMR: hot module replacement 热模块替换 / 模块热替换

/*
  HMR: hot module replacement 热模块替换 / 模块热替换
      作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
           极大提升构建速度

           样式文件:可以使用HMR功能,因为style-loader内部实现了~
           js文件:默认不能使用HMR功能 -->需要修改js代码,添加支持HMR功能的代码
             注意:HMR功能对js的处理,只能处理非入口js文件的其他文件.
           html文件:默认不能使用HMT功能,同时会导致问题:html文件不能热更新了
             解决:修改entry入口,将html文件引入
*/

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: ['./src/index.js','./src/index.html']
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        // 使用资源模块处理字体(其他资源)
        test: /\.(eot|svg|ttf|woff|woff2)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[hash:5][ext]',
        },
      },
      {
        // 使用资源模块处理CSS
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        // 使用资源模块处理less
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      {
        // 使用资源模块处理图片
        test: /\.(jpg|png|gif)$/i,
        type: 'asset',
        parser: {
          // 转base64条件
          dataUrlCondition: {
            maxSize: 8 * 1024, //8kb
          },
          generator: {
            filename: 'images/[name][ext]',
          },
        },
      },
      {
        // 处理html中的图片
        test: /\.html$/,
        loader: 'html-loader',
        options: {
          esModule: false,
        },
      },
    ],
  },
  plugins: [
    // 处理html资源
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  mode: 'development',
  devServer: {
    // 项目构建目录
    static: {
      directory: resolve(__dirname, 'build'),
    },
    compress: true, // gzip压缩
    open: true, // 自动打开浏览器
    port: 3003, // 端口
    hot: true, //开启HMR功能 (当修改了webpack配置,新配置要想生效,必须重启webpack服务)
  },
};

5.4 source-map: 一种提供源代码到构建后代码映射技术(如果构建后代码出错,通过映射关系可以追踪到源代码错误)

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: ['./src/index.js', './src/index.html'],
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        // 使用资源模块处理字体(其他资源)
        test: /\.(eot|svg|ttf|woff|woff2)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[hash:5][ext]',
        },
      },
      {
        // 使用资源模块处理CSS
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        // 使用资源模块处理less
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      {
        // 使用资源模块处理图片
        test: /\.(jpg|png|gif)$/i,
        type: 'asset',
        parser: {
          // 转base64条件
          dataUrlCondition: {
            maxSize: 8 * 1024, //8kb
          },
          generator: {
            filename: 'images/[name][ext]',
          },
        },
      },
      {
        // 处理html中的图片
        test: /\.html$/,
        loader: 'html-loader',
        options: {
          esModule: false,
        },
      },
    ],
  },
  plugins: [
    // 处理html资源
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  mode: 'development',
  devServer: {
    // 项目构建目录
    static: {
      directory: resolve(__dirname, 'build'),
    },
    compress: true, // gzip压缩
    open: true,
    port: 3003,
    hot: true,
  },
  devtool: 'source-map',
};
/*
  source-map: 一种提供源代码到构建后代码映射技术(如果构建后代码出错,通过映射关系可以追踪到源代码错误)
  参数:
  [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
   
  source-map:外部
    错误代码准确信息 和 源代码的错误位置
  inline-source-map:内联
    只生成一个内联source-map
    错误代码准确信息 和 源代码的错误位置
  hidden-source-map:外部
    错误代码错误原因,但是没有错误位置
    不能追踪源代码错误,只能提示到构建后代码的错误位置
  eval-source-map:内联
    每一个文件都生成对应的source-map,都在eval函数中
    错误代码准确信息 和 源代码的错误位置  
  nosources-source-map:外部
    错误代码准确信息,但是没有任何源代码信息
  cheap-source-map:外部
    错误代码准确信息 和源代码错误位置
    只能精确到行
  cheap-module-source-map:外部
    错误代码准确信息 和源代码错误位置
    只能精确到行
    module会将loader的source map加入
  内联和外部的区别: 1.外部生成了文件,内联没有  2.内联构建速度更快
  
  开发环境:速度快,调试更友好
      速度快(eval>inline>cheap>...)
        eval-cheap-source-map
        eval-source-map
      调试更友好
        source-map
        cheap-module-source-map
        cheap-source-map
        
      -->eval-source-map / eval-cheap-module-source-map  
  生产环境:源代码要不要隐藏?调试要不要更友好
    内联会让代码体积变大,所以生产环境不用内联
    nosources-source-map 全部隐藏
    hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

    -->source-map/cheap-module-source-map

*/

5.5 oneOf:生产环境提升打包构建速度

const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');

// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';

// 复用loader
const commonCssLoader = [
  // 这个loader取代style-loader.作用:提取js中的css成单独文件
  MiniCssExtractPlugin.loader,
  // 将css文件整合(加载)到js文件中
  'css-loader',
  // 兼容性处理
  {
    // 还需要在package.json中定义browserslist
    /*"browserslist":{
                             * 开发环境 :设置node环境变量 process.env.NODE_ENV = development
                              "development": [
                                  "last 1 chrome version",  // 兼容最近的一个chrome版本
                                  "last 1 firefox version",
                                  "last 1 safari version"
                              ],
                              * 生产环境: 默认是看生产环境
                              "production":[
                                  ">0.2%", 
                                  "not dead", // 不要已经丢弃的浏览器
                                  "not op_mini all" 不要所有的欧朋浏览器
                              ]
                          }
              */
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()],
    },
  },
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  modules: {
    rules: [
      {
        // js语法检查  在package.json中添加eslintConfig -->airbnb
        /*
        在package.json中添加eslintConfig -->airbnb
        "eslintConfig": {
                  "extends": "airbnb-base"
                   }
        */
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true,
        },
      },
     {
       // 以下loader只会匹配一个
       // 注意:不能有两个配置处理同一种类型文件
       oneOf:[
        {
          test: /\.css$/,
          use: [...commonCssLoader],
        },
        {
          test: /\.less$/,
          use: [...commonCssLoader, 'less-loader'],
        },
        /*
          正常来讲,一个文件只能被一个loader处理,
          当一个文件要被多个loader处理,name一定要指定loader执行的顺序
          先执行eslint 在执行babel
        */
        {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  // 按需加载
                  useBuiltIns: 'usage',
                  // 指定core-js版本
                  corejs: {
                    version: 3,
                  },
                  // 指定兼容性做到哪个版本浏览器
                  targets: {
                    chrome: '60',
                    firefox: '60',
                    ie: '9',
                    edge: '17',
                    safari: '10',
                  },
                },
              ],
            ],
          },
        },
        {
          // 处理图片资源
          test: /\.(jpg|png|gif)/,
          loader: 'url-loader',
          options: {
            limit: 8 * 1024,
            name: '[hash:10].[ext]',
            outputPath: 'imgs',
            esModule: false,
          },
        },
        {
          // 处理HTML资源中的图片
          test: /\.html/,
          loader: 'html-loader',
        },
        {
          // 处理其他资源
          exclude: /\.(js|css|less|html|jpg|png|gif)/,
          loader: 'file-loader',
          options: {
            output: 'media',
          },
        },
       ]
     }
    ],
  },
  plugins: [
    // 提取CSS成单独文件
    new MiniCssExtractPlugin({
      // 对输出的CSS文件进行重命名
      filename: 'css/built.css',
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // html压缩 移出空格,注释
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: 'production',
};

5.6 缓存:生产环境缓存的配置

视屏教程地址:https://www.bilibili.com/video/BV1e7411j7T5?p=23&spm_id_from=pageDriver

const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');

/* 
  缓存:
     babel缓存
         cacheDirectory:true
		 -->让第二次打包构建速度更快
     文件资源缓存
         hash: 每次webpack构建时会生成一个唯一的哈希值
         问题: 因为js和css同时使用一个hash值.
               如果重新打包,会导致所有缓存失效.
         chunkhash: 根据chunk生成的hash值.如果打包来源于同一个chunk,那么hash值就一样
         问题: js和css的hash值还是一样的.
         因为css是在js中被引入的,所以属于同一个chunk
         contenthash: 根据文件的内容生成hash值.不同文件hash值一定不一样.
		 -->让代码上线运行缓存更好使用
*/

// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';

// 复用loader
const commonCssLoader = [
  // 这个loader取代style-loader.作用:提取js中的css成单独文件
  MiniCssExtractPlugin.loader,
  // 将css文件整合(加载)到js文件中
  'css-loader',
  // 兼容性处理
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()],
    },
  },
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build'),
  },
  modules: {
    rules: [
      {
        // js语法检查  在package.json中添加eslintConfig -->airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true,
        },
      },
      {
        // 以下loader只会匹配一个
        // 注意:不能有两个配置处理同一种类型文件
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader],
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader'],
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    // 按需加载
                    useBuiltIns: 'usage',
                    // 指定core-js版本
                    corejs: {
                      version: 3,
                    },
                    // 指定兼容性做到哪个版本浏览器
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      edge: '17',
                      safari: '10',
                    },
                  },
                ],
              ],
              // 开启babel缓存  第二次构建时,会读取之前的缓存
              cacheDirectory: true,
            },
          },
          {
            // 处理图片资源
            test: /\.(jpg|png|gif)/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              outputPath: 'imgs',
              esModule: false,
            },
          },
          {
            // 处理HTML资源中的图片
            test: /\.html/,
            loader: 'html-loader',
          },
          {
            // 处理其他资源
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: 'file-loader',
            options: {
              output: 'media',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    // 提取CSS成单独文件
    new MiniCssExtractPlugin({
      // 对输出的CSS文件进行重命名
      filename: 'css/built.[contenthash:10].css',
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // html压缩 移出空格,注释
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: 'production',
  // 映射
  devtool: 'source-map',
};

5.7 tree shaking(树摇/树震):

const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');

/* 
  tree shaking: 去除无用代码
       前提: 1. 必须使用ES6模块化  2.开启production环境 -->同时满足,自动开启tree shaking
       作用: 减少代码体积

       在package.json中配置
         "sideEffects": false  所有代码都没有副作用(都可以进行tree shaking)
         问题: 可能会把css/@babel/polyfill(副作用)文件干掉
         "sideEffects": ["*.css","*.less"]
*/

// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';

// 复用loader
const commonCssLoader = [
  // 这个loader取代style-loader.作用:提取js中的css成单独文件
  MiniCssExtractPlugin.loader,
  // 将css文件整合(加载)到js文件中
  'css-loader',
  // 兼容性处理
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()],
    },
  },
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build'),
  },
  modules: {
    rules: [
      {
        // js语法检查  在package.json中添加eslintConfig -->airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true,
        },
      },
      {
        // 以下loader只会匹配一个
        // 注意:不能有两个配置处理同一种类型文件
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader],
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader'],
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    // 按需加载
                    useBuiltIns: 'usage',
                    // 指定core-js版本
                    corejs: {
                      version: 3,
                    },
                    // 指定兼容性做到哪个版本浏览器
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      edge: '17',
                      safari: '10',
                    },
                  },
                ],
              ],
              // 开启babel缓存  第二次构建时,会读取之前的缓存
              cacheDirectory: true,
            },
          },
          {
            // 处理图片资源
            test: /\.(jpg|png|gif)/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              outputPath: 'imgs',
              esModule: false,
            },
          },
          {
            // 处理HTML资源中的图片
            test: /\.html/,
            loader: 'html-loader',
          },
          {
            // 处理其他资源
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: 'file-loader',
            options: {
              output: 'media',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    // 提取CSS成单独文件
    new MiniCssExtractPlugin({
      // 对输出的CSS文件进行重命名
      filename: 'css/built.[contenthash:10].css',
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // html压缩 移出空格,注释
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: 'production',
  // 映射
  devtool: 'source-map',
};

5.8 code split:代码分割

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 单入口
  //entry: './src/js/index.js',
  entry: {
    index: './src/js/index.js',
    test: './src/js/test/js',
  },
  output: {
    // name: 取文件名(取index/test)
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build'),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // html压缩 移出空格,注释
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  // 可以将node_modules中代码单独打包成一个chunk最终输出
  // 自动分析多入口chunk中,有没有公共的文件.如果有会打包成一个单独chunk
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
  mode: 'production',
};

代码分割之方法3

![image](https://img2022.cnblogs.com/blog/2560128/202202/2560128-20220215174904713-157394179.png)

5.9 懒加载和预加载

![image](https://img2022.cnblogs.com/blog/2560128/202202/2560128-20220215181052264-376673648.png)

PWA:渐进式网络开发应用程序

多进程打包

externals

dll (动态连接库)

性能优化总结

### WEBPACK 性能优化

- 开发环境性能优化
- 生产环境性能优化

#### 开发环境性能优化

- 优化打包构建速度
  - HMR
- 优化代码调试
  - source-map

#### 生产环境性能优化

- 优化打包构建速度
  - onfOf
  - babel 缓存
  - 多进程打包
  - externals(让某些库不打包,直接通过 cdn 连接引入)
  - dll(让某些库不打包,单独打包)
- 优化代码运行的性能
  - 缓存(hash-chunkhash-contenthash)
  - tree shaking(树摇)
  - code split(代码分割)
  - 懒加载/预加载
  - PWA(渐进式网络应用开发技术/离线访问技术)

第6章 webpack详细配置

webpack详细配置之entry

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

/* 
  entry:入口起点
    1.string --> './src/index.js'
      单入口(应用最多)
      打包形成一个chunk.输出一个bundle文件
      此时chunk的名称默认是 main
    2.array -->  ['./src/index.js','./src/add.js']
      多入口
      所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件.
        -->只有在HMR功能中让html热更新生效
    3.object -->entry: { index: './src/index.js', add: './src/add.js' },
      多入口
      有几个入口文件就形成几个chunk,输出几个bundle文件
      此时chunk的名称就是key

      -->特殊用法
        { 
           // 所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件.
            index: ['./src/index.js', './src/count.js'], 
           // 形成一个chunk,输出一个bundle文件 
            add: './src/add.js' 
        }
*/
module.exports = {
  // entry: './src/index.js',
  entry: { index: ['./src/index.js', './src/count.js'], add: './src/add.js' },
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'build'),
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
};

webpack详细配置之output

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    // 文件名称(可以指定名称+目录)
    filename: 'js/[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
    // (一般适用于生产环境)所有资源引入公共路径前缀-->'imgs/a.jpg'-->'/imgs/a.jpg'
    publicPath: '/',
    chunkFilename: '[name]_chunk.js', // 非入口chunk的名称

    // 一般结合dll一起使用
    //library: '[name]', // 整个库向外暴露的变量名
    //libraryTarget:'window',// 变量名添加到哪个上 browser
    //libraryTarget:'global',// 变量名添加到哪个上 node
    //libraryTarget:'commonjs',
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
};

webpack详细配置之module

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    // 文件名称(可以指定名称+目录)
    filename: 'js/[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      // loader 配置
      {
        test: /\.css$/,
        // 多个loader 用use
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.js$/,
        // 排除node_modules下的js文件
        exclude: /node_modules/,
        // 只检查src下面的js文件
        include: resolve(__dirname, 'src'),
        // pre 优先执行  ,post 延后执行
        enforce: 'pre',
        // 单个loader
        loader: 'eslint-loader',
      },
      {
        // 以下配置只会生效一个
        oneOf: [],
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
};

webpack详细配置之resolve(用来解析模块的规则)

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/js/index.js',
  output: {
    // 文件名称(可以指定名称+目录)
    filename: 'js/[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      // loader 配置
      {
        test: /\.css$/,
        // 多个loader 用use
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
  // 解析模块的规则
  resolve: {
    // 配置解析模块路径别名: 优点可以简写路径  缺点:写路径时没有提示
    alias: {
      $css: resolve(__dirname, 'src/css'),
    },
    // 配置省略文件路径的后缀名
    extensions: ['.js', '.json', 'jsx', '.css'],
    // 告诉 webpack 解析模块是去找哪个目录
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
  },
};

webpack详细配置之devServer

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/js/index.js',
  output: {
    // 文件名称(可以指定名称+目录)
    filename: 'js/[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      // loader 配置
      {
        test: /\.css$/,
        // 多个loader 用use
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
  // 解析模块的规则
  resolve: {
    // 配置解析模块路径别名: 优点可以简写路径  缺点:写路径时没有提示
    alias: {
      $css: resolve(__dirname, 'src/css'),
    },
    // 配置省略文件路径的后缀名
    extensions: ['.js', '.json', 'jsx', '.css'],
    // 告诉 webpack 解析模块是去找哪个目录
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
  },
  // 用于开发环境
  devServer: {
    // 运行代码的目录
    contentBase: resolve(__dirname, 'build'),
    // 监视contentBase 目录下的所有文件,一旦文件发生变化就会 reload(重载)
    watchContentBase: true,
    watchOptions: {
      // 忽略文件
      ignored: /node_modules/,
    },
    // 启动gzip压缩
    compress: true,
    // 端口
    port: 5000,
    // 域名
    host: 'localhost',
    // 自动浏览器
    open: true,
    // 开启HMR功能
    hot: true,
    // 不需要显示启动服务器日志信息
    clientLogLevel: 'none',
    // 除了一些基本启动信息以外,其他内容都不要显示
    quiet: true,
    // 如果出现错误,不要全屏提示
    overlay: false,
    // 服务器代理 -->解决开发环境跨域问题
    proxy: {
      // 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器 (3000)
      '/api': {
        target: 'http://localhost:3000',
        // 发送请求时,请求路径重写:将 /api/xxx  --> /xxx (去掉/api)
        pathRewrite: {
          '^/api': '',
        },
      },
    },
  },
};

webpack详细配置之optmization

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
const TerserWebpackPlugin = require('terser-webpack-plugin');

module.exports = {
  entry: './src/js/index.js',
  output: {
    // 文件名称(可以指定名称+目录)
    filename: 'js/[name].[contenthash:10].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
    chunkFilename: 'js/[name].[contenthash:10]_chunk.js',
  },
  module: {
    rules: [
      // loader 配置
      {
        test: /\.css$/,
        // 多个loader 用use
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'production',
  resolve: {
    alias: {
      $css: resolve(__dirname, 'src/css'),
    },
    extensions: ['.js', '.json', 'jsx', '.css'],
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      // 默认值,可以不写
      /* minSize: 30 * 1024, // 分割的chunk最小为30kb
      maxSize: 0, // 最大没有限制
      minChunks: 1, // 要提取的chunk最少被引用1次
      maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
      maxInitialRequests: 3, // 入口js文件最大并行请求数量
      automaticNameDelimiter: '~', // 名称连接符
      name: true, // 可以使用命名规则
      cacheGroups: {
        // 分割chunk的组
        // node_modules文件会被打包到vendors 组的chunk中. -->vendors~XXX.js
        // 满足上面的公共规则,如:大小超过30KB,至少被引用一次.
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          // 优先级
          priority: -10,
        },
        default: {
          // 要提取的chunk最少被引用2次
          minChunks: 2,
          priority: -20,
          // 如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用.而不是重新打包模块
          reuseExistingChunk: true,
        },
      }, */
    },
    // 将当前模块的记录其他模块的hash单独打包为一个文件 runtime
    // 解决:修改a文件导致b文件的contenthash变化
    runtimeChunk: {
      name: (entrypoint) => `runtime-${entrypoint.name}`,
    },
    // 配置生产环境的压缩方案:js和css
    minimizer: {
      new TerserWebpackPlugin({
        // 开启缓存
        cache:true,
        // 开启多进程打包
        parallel:true,
        // 启用source-map
        sourceMap:true,
      })
    },
  },
};

第7章 webpack5介绍和使用


第8章 总结webpack

posted on 2021-11-10 18:41  土拨鼠公主  阅读(47)  评论(0编辑  收藏  举报

导航