wepack4配置入门

news2024/11/17 16:32:23

一、 webpack 简介

1.1 webpack 是什么

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

在这里插入图片描述

webpack会从打包入口开始,找到所有的依赖(js/json/css/img/less/…),webpack会将这些依赖作为 chunk 块(代码块)。然后将 chunk 块中的各种文件内容转变为浏览器可以理解的内容:less -> css、es6语法 -> 浏览器可以理解的语法 … 这些转变后的打包产物称为bundle

Chunk是Webpack打包过程中,一堆module的集合。我们知道Webpack的打包是从一个入口文件开始,也可以说是入口模块,入口模块引用这其他模块,模块再引用模块。Webpack通过引用关系逐个打包模块,这些module就形成了一个Chunk。

如果我们有多个入口文件,可能会产出多条打包路径,一条路径就会形成一个Chunk。

在这里插入图片描述

1.2 webpack 五个核心概念

1.2.1 Entry

入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图

1.2.2 Output

输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名

1.2.3 Loader

Loader 让 webpack 能够去处理那些非 JavaScript 文件 (webpack 自身只理解 JavaScript)。
loader 将 webpack 不识别的资源翻译为 webpck 识别的资源。

1.2.4 Plugins

插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化压缩,一直到重新定义环境中的变量等。

1.2.5 Mode

模式(Mode)指示 webpack 使用相应模式的配置

选项描述特点
development会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。能让代码本地调试运行的环境
production会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin, UglifyJsPlugin 和 TerserPlugin。能让代码优化上线运行环境。

二、 webpack 的初体验

2.1 初始化配置

  1. 初始化 package.json

输入指令:

npm init
  1. 下载并安装 webpack

输入指令:

npm install webpack webpack-cli -g
npm install webpack webpack-cli -D
  • webpack-cli: webpack命令行,支持使用指令的方式使用webpack的功能。
  • -g: 全局安装
  • -D: 本地安装

2.2 编译打包应用

  1. 创建文件
// index.js
import data from './data.json';
console.log(data);
function add(x, y) {
  return x + y;
}
console.log(add(1, 2));
// package.json
{
  "name": "webpack_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack src/index.js -o build/built.js --mode=development",
    "pro": "webpack src/index.js -o build/built.js --mode=production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11"
  }
}
  1. 运行指令
  • 开发环境指令:
webpack src/index.js -o build/built.js --mode=development

webpack会以 ./src/index.js 为入口文件开始打包,打包后输出到 ./build/built.js。整体打包环境,是开发环境。

  • 生产环境指令:
webpack src/index.js -o build/built.js --mode=production

webpack会以 ./src/index.js 为入口文件开始打包,打包后输出到 ./build/built.js。 整体打包环境,是生产环境。

  1. 结论
  • webpack 能够编译打包 js 和 json 文件。
  • 能将 es6 的模块化语法转换成浏览器能识别的语法。
  • 生产环境比开发环境多一个压缩js代码。
  1. 问题
  • 不能编译打包 css、img 等文件。
  • 不能将 js 的 es6 基本语法转化为 es5 以下语法

三、 webpack 开发环境的基本配

3.1 创建配置文件

  1. 创建文件
  • webpack.config.js: webpack的配置文件
  • 作用: 指示 webpack 干哪些活(当你运行 webpack 指令时,会加载里面的配置)
  • 所有构建工具都是基于nodejs平台运行的,模块化默认采用commonjs
  1. 配置内容如下
const { resolve } = require("path"); // node 内置核心模块,用来处理路径问题。
module.exports = {
  entry: "./src/index.js", // 入口文件
  output: {
    // 输出配置
    filename: "built.js", // 输出文件名
    path: resolve(__dirname, "build"), // 输出文件路径配置
  },
  mode: "development", //开发环境
};
  1. 运行指令: webpack

3.2 打包样式资源

  1. 创建文件
/* index.css */
html, body{
  margin: 0;
  padding: 0;
  height: 100%;
  background-color: pink;
}
// index.js
// 引入样式资源
import './index.css';
import './index.less';
// index.less
#title {
  color: #fff;
}
  1. 下载安装 loader 包
npm i css-loader style-loader less-loader less -D
  1. 修改配置文件
// 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配置
      // 不同文件必须配置不同loader处理
      {
        // 匹配哪些文件
        test: /\.css$/,
        // 使用哪些loader进行处理
        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: [
    // 详细plugins的配置
  ],
  // 模式
  mode: "development", // 开发模式
  // mode: 'production'
};

  1. 运行指令: webpack

3.3 打包 HTML 资源

  1. 创建文件
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack</title>
</head>

<body>
  <h1 id="title">hello html</h1>
</body>

</html>
function add(x, y) {
  return x + y;
}

console.log(add(2, 3));
  1. 下载安装 plugin 包
npm install --save-dev html-webpack-plugin
  1. 修改配置文件
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)
    // 需求:需要有结构的HTML文件
    new HtmlWebpackPlugin({
      // 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
      template: "./src/index.html",
    }),
  ],
  mode: "development",
};

3.4 打包图片资源

  1. 创建文件
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack</title>
</head>
<body>
  <div id="box1"></div>
  <div id="box2"></div>
  <div id="box3"></div>
  <img src="./angular.jpg" alt="angular">
</body>
</html>
import './index.less';
#box1{
  width: 100px;
  height: 100px;
  background-image: url('./vue.jpg');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

#box2{
  width: 200px;
  height: 200px;
  background-image: url('./react.png');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

#box3{
  width: 300px;
  height: 300px;
  background-image: url('./angular.jpg');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
  1. 下载安装 loader 包
npm install --save-dev html-loader url-loader file-loader
  1. 修改配置文件
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$/,
        // 要使用多个loader处理用use
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        // 问题:默认处理不了html中img图片
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        // 使用一个loader
        // 下载 url-loader file-loader,url-loader 依赖 file-loader
        loader: "url-loader",
        options: {
          // 图片大小小于8kb,就会被base64处理
          // 优点: 减少请求数量(减轻服务器压力)
          // 缺点:图片体积会更大(文件请求速度更慢)
          limit: 8 * 1024,
          // 问题:因为url-loader默认使用es6模块化解析,而html-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",
};

3.5 打包其他资源

  1. 使用范围

不需要做任何处理,只需要原封不动输出即可,比如字体图标。

  1. 配置文件
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: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      // 打包其他资源(除了html/js/css资源以外的资源)
      {
        // 排除css/js/html资源
        exclude: /\.(css|js|html|less)$/,
        loader: "file-loader",
        options: {
          name: "[hash:10].[ext]",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",
};

3.6 devServer

  1. 作用

开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器),开发者只需要关注编码

  1. 配置文件
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: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      // 打包其他资源(除了html/js/css资源以外的资源)
      {
        // 排除css/js/html资源
        exclude: /\.(css|js|html|less)$/,
        loader: "file-loader",
        options: {
          name: "[hash:10].[ext]",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",

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

  • npx是执行Node软件包的工具,它从 npm5.2版本开始,就与npm捆绑在一起。
  • 默认情况下,首先检查路径中是否存在要执行的包(即在项目中);如果存在,它将执行;若不存在,意味着尚未安装该软件包,npx将安装其最新版本,然后执行它;
  1. 运行指令
npx webpack-dev-server

3.7 开发环境配置

  1. 目的

开发环境配置:能让代码运行(代码运行即可)

运行项目指令:

  • webpack: 会将打包结果输出出去
  • npx webpack-dev-server: 只会在内存中编译打包没有输出
  1. 配置文件
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      // loader的配置
      {
        // 处理less资源
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        // 处理css资源
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        loader: "url-loader",
        options: {
          limit: 8 * 1024,
          name: "[hash:10].[ext]",
          // 关闭es6模块化
          esModule: false,
          outputPath: "imgs",
        },
      },
      {
        // 处理html中img资源
        test: /\.html$/,
        loader: "html-loader",
      },
      {
        // 处理其他资源
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        loader: "file-loader",
        options: {
          name: "[hash:10].[ext]",
          outputPath: "media",
        },
      },
    ],
  },
  plugins: [
    // plugins的配置
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",
  devServer: {
    contentBase: resolve(__dirname, "build"),
    compress: true,
    port: 3000,
    open: true,
  },
};

  1. 运行指令
npx webpack-dev-server

四、 webpack 生产环境的基本配置

为什么要单独配置生产环境

  • 开发环境中将css放在了js中,导致js文件的体积变大
  • 因为将css放在了js中,所以只有加载完js,css才会生效,会导致出现闪现情况
  • 开发环境的目的是使得代码跑起来,能够调测;生产环境的目的是让代码跑的更快,更平稳。生产环境会使用代码压缩,css兼容性保障等手段
  • 压缩,兼容性等耗时较长,放在开发环境会使得构建较慢,不利于开发调测

4.1 提取 css 成单独文

  1. 下载插件
npm install --save-dev mini-css-extract-plugin
  1. 修改配置文件
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: 'js/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'
    }),
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名,默认名称是main.css
      filename: 'css/built.css'
    })
  ],
  mode: 'development'
};
  • style-loader: 创建style标签,将样式放入
  • MiniCssExtractPlugin.loader: 提取js中的css成单独文件

4.2 css 兼容性处理

  1. 下载 loader
npm install --save-dev postcss-loader postcss-preset-env
  1. 修改配置文件
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: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          /*
            css兼容性处理:postcss --> postcss-loader postcss-preset-env

            帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式

            "browserslist": {
              // 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
              "development": [
                "last 1 chrome version",
                "last 1 firefox version",
                "last 1 safari version"
              ],
              // 生产环境:默认是看生产环境
              "production": [
                ">0.2%",
                "not dead",
                "not op_mini all"
              ]
            }
          */
          // 使用loader的默认配置
          // 'postcss-loader',
          // 修改loader的配置
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                // postcss的插件
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    })
  ],
  mode: 'development'
};

  1. 修改 package.json
{
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }
}

4.3 压缩 css

  1. 下载安装包
npm install --save-dev optimize-css-assets-webpack-plugin
  1. 修改配置文件
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';

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                // postcss的插件
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    }),
    // 压缩css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  // optimization: {
  //   minimize: true,
  //   minimizer: [
  //     // 压缩 js
  //     new TerserWebpackPlugin(),
  //     // 压缩css 
  //     new OptimizeCssAssetsWebpackPlugin(),
  //   ],
  // },
  mode: 'development'
};
  • webpack官方文档介绍时并不是将 OptimizeCssAssetsWebpackPlugin 插件配置在plugins数组中。而是配置在 optimization.minimizer 数组中。
  • 原因是: 配置在plugins中,webpack就会在启动时使用这个插件。而配置在 optimization.minimizer中,就只会在optimization.minimize这个特性开启时使用。所以webpack推荐,像压缩类的插件,应该配置在optimization.minimizer数组中。以便于通过optimization.minimize统一控制。(生产环境会默认开启minimize)
  • 需要注意的是:如果配置了minimizer,就表示开发者在自定义压缩插件。内部的JS压缩器就会被覆盖掉。因此需要手动配置js压缩。

4.4 js 语法检查

  1. 下载安装包
npm install --save-dev eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
  1. 修改配置文件
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      /*
        语法检查: eslint-loader 依赖 eslint 库
          注意:只检查自己写的源代码,第三方的库是不用检查的
          设置检查规则:
            package.json中eslintConfig中设置~
              "eslintConfig": {
                // 继承 airbnb-base 的规则检查
                "extends": "airbnb-base"
              }
            airbnb(检查规则) --> eslint-config-airbnb-base  eslint-plugin-import eslint
      */
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "eslint-loader",
        options: {
          // 自动修复eslint的错误
          fix: true,
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",
};

  1. 配置 package.json

配置检查规则

{
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      // eslint不认识 window、navigator全局变量,支持浏览器端全局变量
      "browser": true
    }
  }
}

4.5 js 兼容性处理&es6语法转化

  1. 作用

将 es6 的语法转化为 es5 的语法

  1. 下载安装包
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/polyfill core-js
  1. 修改配置文件
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      /*
        js兼容性处理:babel-loader @babel/core (babel的核心库)
          1. 基本js兼容性处理 --> @babel/preset-env
            问题:只能转换基本语法,如promise高级语法不能转换
          2. 全部js兼容性处理 --> @babel/polyfill  
            问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了~
            使用方法:
              引入即可,在index.js中 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",
                  safari: "10",
                  edge: "17",
                },
              },
            ],
          ],
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",
};

4.6 js 压缩

  1. 产环境下会自动压缩js代码
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

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

生产环境下会启用 UglifyJsPlugin 插件,进行js压缩。

  1. 手动配置
    webpack认为,如果配置了minimizer,就表示开发者在自定以压缩插件。内部的JS压缩器就会被覆盖掉。

需要修改配置如下:

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const TerserWebpackPlugin = require("terser-webpack-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  optimization: {
    minimize: true,
    minimizer: [
      // 压缩 js
      new TerserWebpackPlugin(),
      // 压缩css
      new OptimizeCssAssetsWebpackPlugin(),
    ],
  },
  mode: "development",
};

4.7 HTML 压缩

  1. 修改配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

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
      }
    })
  ],
  mode: 'production'
};

4.8 生产环境配置

  1. 修改配置文件
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

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

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 还需要在package.json中定义browserslist
    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')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [...commonCssLoader]
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, 'less-loader']
      },
      /*
        正常来讲,一个文件只能被一个loader处理。
        当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
          先执行eslint 再执行babel
      */
      {
        // 在package.json中eslintConfig --> airbnb
        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',
                corejs: {version: 3},
                targets: {
                  chrome: '60',
                  firefox: '50'
                }
              }
            ]
          ]
        }
      },
      {
        test: /\.(jpg|png|gif)/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          outputPath: 'imgs',
          esModule: false
        }
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        exclude: /\.(js|css|less|html|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  mode: 'production'
};

五、 webpack 优化配置

5.1 性能优化总览

  1. 性能优化分类
  • 开发环境性能优化
  • 生产环境性能优化
  1. 开发环境性能优化
  • 优化打包构建速度
    • HMR
  • 优化代码调试
    • source-map
  1. 生产环境性能优化
  • 优化打包构建速度
    • oneOf
    • babel缓存
    • 多进程打包
    • externals
    • dll
  • 优化代码运行的性能
    • 缓存(hash-chunkhash-contenthash)
    • tree shaking
    • code split
    • 懒加载/预加载
    • pwa

5.2 HMR

  1. 介绍
  • HMR: hot module replacement 热模块替换 / 模块热替换
  • 作用:一个模块发生变化,会重新打包这一个模块(而不是打包所有模块) 极大提升构建速度
  • 样式文件:可以使用HMR功能: 因为style-loader内部实现了
  • js文件:默认不能使用HMR功能: 需要修改js代码,添加支持HMR功能的代码
    • 注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。
  • html文件: 默认不能使用HMR功能,同时会导致问题:html文件不能热更新了(本地写的html代码没有更新浏览器) (不用做HMR功能)
    • 解决:修改entry入口,将html文件引入 entry: ['./src/js/index.js', './src/index.html']
  1. js文件开启HMR功能
// index.js
// 引入
import print from './print';
import '../css/iconfont.css';
import '../css/index.less';

console.log('index.js文件被加载了~');

print();

function add(x, y) {
  return x + y;
}

console.log(add(1, 3));

if (module.hot) {
  // 一旦 module.hot 为true,说明开启了HMR功能。 --> 让HMR功能代码生效
  module.hot.accept('./print.js', function() {
    // 方法会监听 print.js 文件的变化,一旦发生变化,其他模块不会重新打包构建。
    // 会执行后面的回调函数
    print();
  });
}
// print.js
console.log('print.js被加载了~');

function print() {
  const content = 'hello print';
  console.log(content);
}

export default print;
  1. 配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: ['./src/js/index.js', './src/index.html'],
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // loader的配置
      {
        // 处理less资源
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        // 处理css资源
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          // 关闭es6模块化
          esModule: false,
          outputPath: 'imgs'
        }
      },
      {
        // 处理html中img资源
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        // 处理其他资源
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    // plugins的配置
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    // 开启HMR功能
    // 当修改了webpack配置,新配置要想生效,必须重新webpack服务
    hot: true
  }
};

5.3 source-map

  1. 简介

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

  1. 类别

[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. 内联和外部的区别
  • 外部生成了文件,内联没有(内联直接将source-map信息放在js里面了)
  • 内联构建速度更快
  1. source-map 的选择
  • 开发环境:速度快,调试更友好
    • 速度快(eval>inline>cheap>…) eval-cheap-souce-map > eval-source-map
    • 调试更友好: souce-map > cheap-module-souce-map > cheap-souce-map
    • 建议: eval-source-map(vue,react脚手架) / eval-cheap-module-souce-map
  • 生产环境:源代码要不要隐藏? 调试要不要更友好
    • 内联会让代码体积变大,所以在生产环境不用内联
    • nosources-source-map 全部隐藏
    • hidden-source-map 只隐藏源代码,会提示构建后代码错误信息
    • source-map(调试友好) / cheap-module-souce-map(速度快些)
  1. 配置信息
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: ['./src/js/index.js', './src/index.html'],
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // loader的配置
      {
        // 处理less资源
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        // 处理css资源
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          // 关闭es6模块化
          esModule: false,
          outputPath: 'imgs'
        }
      },
      {
        // 处理html中img资源
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        // 处理其他资源
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    // plugins的配置
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true
  },
  devtool: 'eval-source-map'
};

5.4 oneOf

  1. 解决问题
  • 不使用 oneOf 的情况下,所有的 rules 都会匹配一次,有的可以命中,有的无法命中。
  • 使用 oneOf 的情况下,oneOf 中的 loader 只会匹配一个
  • 优化生产环境打包构建速度
  1. 配置文件
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

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

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  "css-loader",
  {
    // 还需要在package.json中定义browserslist
    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"),
  },
  module: {
    rules: [
      {
        // 在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",
                    corejs: { version: 3 },
                    targets: {
                      chrome: "60",
                      firefox: "50",
                    },
                  },
                ],
              ],
            },
          },
          {
            test: /\.(jpg|png|gif)/,
            loader: "url-loader",
            options: {
              limit: 8 * 1024,
              name: "[hash:10].[ext]",
              outputPath: "imgs",
              esModule: false,
            },
          },
          {
            test: /\.html$/,
            loader: "html-loader",
          },
          {
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: "file-loader",
            options: {
              outputPath: "media",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/built.css",
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: "production",
};

5.5 缓存

  1. 缓存分类
  • babel缓存(让第二次打包构建速度更快)
    • cacheDirectory: true
  • 文件资源缓存(让代码上线运行缓存更好使用)
    • 使用场景: 服务器配置了缓存,用户会使用缓存文件,此时出了个bugfix版本,将变更的文件替换,如何使用户放弃缓存,使用新的文件
    • 文件资源缓存方法
      • hash: 每次wepack构建时会生成一个唯一的hash值。
        • 问题: 因为js和css同时使用一个hash值。 如果重新打包,会导致所有缓存失效。(可能我却只改动一个文件)
      • chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
        • 问题: js和css的hash值还是一样的因,为css是在js中被引入的,所以同属于一个chunk
      • contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样
  1. 配置文件
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

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

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  "css-loader",
  {
    // 还需要在package.json中定义browserslist
    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"),
  },
  module: {
    rules: [
      {
        // 在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"],
          },
          /*
            正常来讲,一个文件只能被一个loader处理。
            当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
              先执行eslint 在执行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: "babel-loader",
            options: {
              presets: [
                [
                  "@babel/preset-env",
                  {
                    useBuiltIns: "usage",
                    corejs: { version: 3 },
                    targets: {
                      chrome: "60",
                      firefox: "50",
                    },
                  },
                ],
              ],
              // 开启babel缓存
              // 第二次构建时,会读取之前的缓存
              cacheDirectory: true,
            },
          },
          {
            test: /\.(jpg|png|gif)/,
            loader: "url-loader",
            options: {
              limit: 8 * 1024,
              name: "[hash:10].[ext]",
              outputPath: "imgs",
              esModule: false,
            },
          },
          {
            test: /\.html$/,
            loader: "html-loader",
          },
          {
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: "file-loader",
            options: {
              outputPath: "media",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/built.[contenthash:10].css",
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: "production",
  devtool: "source-map",
};

5.6 tree shaking&树摇

  1. 目的

tree shaking:去除无用代码,减少代码体积

  1. 前提
  • 必须使用ES6模块化
  • 开启production环境
  1. 问题

可能会把 css@babel/polyfill (副作用)文件干掉

在package.json中配置:

  • “sideEffects”: false 所有代码都没有副作用(都可以进行tree shaking)
  • “sideEffects”: [“.css", ".less”] 不要进行 tree shaking
  1. 配置文件
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

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

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  "css-loader",
  {
    // 还需要在package.json中定义browserslist
    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"),
  },
  module: {
    rules: [
      {
        // 在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",
                    corejs: { version: 3 },
                    targets: {
                      chrome: "60",
                      firefox: "50",
                    },
                  },
                ],
              ],
              // 开启babel缓存
              // 第二次构建时,会读取之前的缓存
              cacheDirectory: true,
            },
          },
          {
            test: /\.(jpg|png|gif)/,
            loader: "url-loader",
            options: {
              limit: 8 * 1024,
              name: "[hash:10].[ext]",
              outputPath: "imgs",
              esModule: false,
            },
          },
          {
            test: /\.html$/,
            loader: "html-loader",
          },
          {
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: "file-loader",
            options: {
              outputPath: "media",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/built.[contenthash:10].css",
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: "production",
  devtool: "source-map",
};

5.7 code split

  1. 目的
  • 代码分割,将一份大的代码分割为多个代码,并行加载,提高加载速度
  • 实现按需加载
  1. 方式一: 多入口

通过多入口的方式拆分文件

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

module.exports = {
  // 单页面应用 单入口最终输出一个bundle
  // entry: './src/js/index.js',
  entry: {
    // 多页面应用 多入口:每个入口输出一个bundle
    index: "./src/js/index.js",
    test: "./src/js/test.js",
  },
  output: {
    // [name]:取文件名
    filename: "js/[name].[contenthash:10].js",
    path: resolve(__dirname, "build"),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
  ],
  mode: "production",
};

  1. 方式二: splitChunks
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]:取文件名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  /*
    1. 可以将node_modules中代码单独打包一个chunk最终输出
    2. 自动分析多入口chunk中,有没有公共的文件(如果公共文件太小,也不会单独生成chunk)。如果有会打包成单独一个chunk
  */
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  mode: 'production'
};
  1. 方式三: 通过js代码,让某个文件被单独打包成一个chunk
  • import动态导入语法:能将某个文件单独打包
  • webpackChunkName: 配置打包文件的名字,若不配置则为 0,1,2,3…
function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}

import(/* webpackChunkName: 'test' */ "./test")
  .then(({ mul, count }) => {
    // 文件加载成功~
    // eslint-disable-next-line
    console.log(mul(2, 5));
  })
  .catch(() => {
    // eslint-disable-next-line
    console.log("文件加载失败~");
  });

// eslint-disable-next-line
console.log(sum(1, 2, 3, 4));

5.8 lazy loading&懒加载

console.log('index.js文件被加载了~');

// import { mul } from './test';

document.getElementById('btn').onclick = function() {
  // 懒加载~:当文件需要使用时才加载~
  // 预加载 prefetch:会在使用之前,提前加载js文件 
  // 正常加载可以认为是并行加载(同一时间加载多个文件)  
  // 预加载 prefetch:等其他资源加载完毕,浏览器空闲了,再偷偷加载资源
  import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(({ mul }) => {
    console.log(mul(4, 5));
  });
};

预加载慎用,原因是兼容性问题比较大。

5.9 pwa & 渐进式网络开发应用程序(离线可访问)

  1. 现状

由于兼容性问题,应用并不广泛,有些大厂在用(淘宝)

  1. 下载安装包

通过 workbox(谷歌开源插件) 使用, webpack 需要安装 workbox-webpack-plugin

npm install --save-dev workbox-webpack-plugin
  1. 配置文件
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

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

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 还需要在package.json中定义browserslist
    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')
  },
  module: {
    rules: [
      {
        // 在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',
                    corejs: { version: 3 },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ],
              // 开启babel缓存
              // 第二次构建时,会读取之前的缓存
              cacheDirectory: true
            }
          },
          {
            test: /\.(jpg|png|gif)/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              outputPath: 'imgs',
              esModule: false
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader'
          },
          {
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: 'file-loader',
            options: {
              outputPath: 'media'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    }),
    new WorkboxWebpackPlugin.GenerateSW({
      /*
        1. 帮助serviceworker快速启动
        2. 删除旧的 serviceworker

        生成一个 serviceworker 配置文件(service-worker.js)~
      */
      clientsClaim: true,
      skipWaiting: true
    })
  ],
  mode: 'production',
  devtool: 'source-map'
};
import { mul } from "./test";
import "../css/index.css";

function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}

// eslint-disable-next-line
console.log(mul(2, 3));
// eslint-disable-next-line
console.log(sum(1, 2, 3, 4));

/*
  1. eslint不认识 window、navigator全局变量
    解决:需要修改package.json中eslintConfig配置
      "env": {
        "browser": true // 支持浏览器端全局变量
      }
   2. sw代码必须运行在服务器上
      方式一:直接使用 nodejs
      方式二:使用 serve 包
        npm i serve -g
        serve -s build 启动服务器,将build目录下所有资源作为静态资源暴露出去
*/
// 注册serviceWorker
// 处理兼容性问题
if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("/service-worker.js")
      .then(() => {
        console.log("sw注册成功了~");
      })
      .catch(() => {
        console.log("sw注册失败了~");
      });
  });
}

5.10 多进程打包

  1. 下载安装包
npm install --save-dev thread-loade
  1. 配置文件
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const WorkboxWebpackPlugin = require("workbox-webpack-plugin");

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

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  "css-loader",
  {
    // 还需要在package.json中定义browserslist
    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"),
  },
  module: {
    rules: [
      {
        // 在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/,
            use: [
              /* 
                放在某一个loader的后面,会对该loader开启多进程打包。 
                进程启动大概为600ms,进程通信也有开销。
                只有工作消耗时间比较长,才需要多进程打包
              */
              {
                loader: "thread-loader",
                options: {
                  workers: 2, // 进程2个
                },
              },
              {
                loader: "babel-loader",
                options: {
                  presets: [
                    [
                      "@babel/preset-env",
                      {
                        useBuiltIns: "usage",
                        corejs: { version: 3 },
                        targets: {
                          chrome: "60",
                          firefox: "50",
                        },
                      },
                    ],
                  ],
                  // 开启babel缓存
                  // 第二次构建时,会读取之前的缓存
                  cacheDirectory: true,
                },
              },
            ],
          },
          {
            test: /\.(jpg|png|gif)/,
            loader: "url-loader",
            options: {
              limit: 8 * 1024,
              name: "[hash:10].[ext]",
              outputPath: "imgs",
              esModule: false,
            },
          },
          {
            test: /\.html$/,
            loader: "html-loader",
          },
          {
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: "file-loader",
            options: {
              outputPath: "media",
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/built.[contenthash:10].css",
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
    new WorkboxWebpackPlugin.GenerateSW({
      /*
        1. 帮助serviceworker快速启动
        2. 删除旧的 serviceworker

        生成一个 serviceworker 配置文件~
      */
      clientsClaim: true,
      skipWaiting: true,
    }),
  ],
  mode: "production",
  devtool: "source-map",
};

5.11 externals

  1. 作用

防止将某些包输出到某些依赖中,比如jq我们希望从cdn链接中获取,不希望打包进来。

  1. 配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'production',
  externals: {
    // 拒绝jQuery被打包进来
    jquery: 'jQuery'
  }
};
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack</title>
</head>

<body>
  <h1 id="title">hello html</h1>
  <!-- 需要手动引入进来 -->
  <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
</body>

</html>

5.12 dll & 动态连接库

  1. 目的

使用dll技术,对某些库(第三方库:jquery、react、vue…)进行单独打包,这部操作是预先操作的。等到真正业务打包的时候就不需要打包这样文件了,只需要打包业务代码,引入预先打包好的第三方库。

  1. 配置文件
// webpack.dll.js
/*
  使用dll技术,对某些库(第三方库:jquery、react、vue...)进行单独打包
    当你运行 webpack 时,默认查找 webpack.config.js 配置文件
    需求:需要运行 webpack.dll.js 文件
      --> webpack --config webpack.dll.js
*/

const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    // 最终打包生成的[name] --> jquery
    // ['jquery'] --> 要打包的库是jquery
    jquery: ['jquery'],
  },
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'dll'),
    library: '[name]_[hash]' // 打包的库里面向外暴露出去的内容叫什么名字
  },
  plugins: [
    // 打包生成一个 manifest.json --> 提供和jquery映射
    new webpack.DllPlugin({
      name: '[name]_[hash]', // 映射库的暴露的内容名称
      path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
    })
  ],
  mode: 'production'
};

// webpack.config.js
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    // 告诉webpack哪些库不参与打包,同时使用时的名称也得变~
    new webpack.DllReferencePlugin({
      manifest: resolve(__dirname, 'dll/manifest.json')
    }),
    // 将某个文件打包输出去,并在html中自动引入该资源
    new AddAssetHtmlWebpackPlugin({
      filepath: resolve(__dirname, 'dll/jquery.js')
    })
  ],
  mode: 'production'
};

六、 webpack 配置详情

6.1 entry

入口起点

  1. 字符串
entry: './src/index.js'
  • 单入口
  • 打包形成一个chunk
  • 输出一个bundle文件
  • 此时chunk的名称默认是main
  1. 数组
entry: ['./src/index.js', './src/add.js']
  • 多入口
  • 所有入口文件最终只会形成一个chunk, 输出出去只有一个bundle文件。
  • 此时chunk的名称默认是main
  • 只有在HMR功能中让html热更新生效
  • 数组的文件一般是没有互相依赖关系的,但是又处于某些原因要将它们打包在一起
  1. 对象
  entry: {
    index: "./src/index.js",
    add: "./src/add.js"
  }
  • 多入口
  • 有几个入口文件就形成几个chunk,输出几个bundle文件
  • 此时chunk的名称是key
  1. 特殊用法
entry: {
    // 所有入口文件最终只会形成一个chunk, 输出出去只有一个bundle文件。
    index: ["./src/index.js", "./src/count.js"],
    // 形成一个chunk,输出一个bundle文件。
    add: "./src/add.js"
  }

6.2 output

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

module.exports = {
  entry: "./src/index.js",
  output: {
    // 文件名称(指定名称+目录)
    filename: "js/[name].js",
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, "build"),
    // 所有资源引入公共路径前缀,例如:'imgs/a.jpg' --> '/imgs/a.jpg'
    publicPath: "/",
    chunkFilename: "js/[name]_chunk.js", // 非入口chunk的名称
    // library: '[name]', // 整个库向外暴露的变量名
    // libraryTarget: 'window' // 变量名添加到哪个上 browser
    // libraryTarget: 'global' // 变量名添加到哪个上 node
    // libraryTarget: 'commonjs'
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: "development",
};

6.3 module

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

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'),
        // 优先执行
        enforce: 'pre',
        // 延后执行
        // enforce: 'post',
        // 单个loader用loader
        loader: 'eslint-loader',
        options: {}
      },
      {
        // 以下配置只会生效一个
        oneOf: []
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development'
};

6.4 resolve

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

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        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']
  }
};

6.5 devServer

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

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()],
  mode: 'development',
  resolve: {
    alias: {
      $css: resolve(__dirname, 'src/css')
    },
    extensions: ['.js', '.json', '.jsx', '.css'],
    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': ''
        }
      }
    }
  }
};

6.6 optimization

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
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: [
      {
        test: /\.css$/,
        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
      maxSiza: 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变化,在b文件中引入a文件,打包后b文件通过引用a文件的contenthash来引入a文件,修改a文件,a文件的contenthash变化自然会导致b文件发生变化
    runtimeChunk: {
      name: entrypoint => `runtime-${entrypoint.name}`
    },
    minimizer: [
      // 配置生产环境的压缩方案:js和css
      new TerserWebpackPlugin({
        // 开启缓存
        cache: true,
        // 开启多进程打包
        parallel: true,
        // 启动source-map
        sourceMap: true
      })
    ]
  }
};

参考

  • webpack中文文档
  • webpack二刷之五、生产环境优化(5.提取压缩CSS)

附录一 package.json

{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.4",
    "add-asset-html-webpack-plugin": "^3.1.3",
    "babel": "^6.23.0",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "file-loader": "^5.0.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "terser-webpack-plugin": "^2.3.5",
    "thread-loader": "^2.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "workbox-webpack-plugin": "^5.0.0"
  },
  "dependencies": {
    "jquery": "^3.4.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css"
  ]
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/380973.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习100天(三十二):032 KD树的构造和搜索

机器学习100天,今天讲的是:KD树的构造和搜索! 《机器学习100天》完整目录:目录 在 K 近邻算法中,我们计算测试样本与所有训练样本的距离,类似于穷举法。如果数据量少的时候,算法运行时间没有大的影响,但是如果数据量很大,那么算法运行的时间就会很长。这在实际的应用…

GFD563A101 3BHE046836R0101

GFD563A101 3BHE046836R0101关于高端涂布机张力控制系统方案的介绍高端涂布机张力控制系统方案涂布机是将具有某种功效的胶&#xff0c;或者油墨类物质均匀粘连在塑料薄膜、铝箔、纺织品等表面的机械设备。本系统从放卷到收卷共采用七台变频器&#xff0c;其中收放卷采用闭环张…

Databend 开源周报第 81 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.com 。Whats New探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。Accepted RFCsrfc: 查询结果缓存…

Cartesi 举办的2023 黑客马拉松

Cartesi 是具有 Linux 运行时的特定于应用程序的Rollups执行层。Cartesi 的特定应用程序 Optimistic Rollup 框架使区块链堆栈足够强大&#xff0c;开发人员可以构建计算密集型和以前不可能的去中心化实例。Cartesi 的 RISC-V 虚拟机支持 Linux 运行时环境&#xff0c;允许像你…

DevOps 学习笔记(二)| 使用 Harbor

文章目录1. 上传镜像到 Harbor2. 拉取 Harbor 镜像3. 使用 Jenkins 操作 Harbor1. 上传镜像到 Harbor 首先在CI/CD 服务器中配置 Docker mkdir -p /etc/docker/ cd /etc/docker/ vim daemon.json其中的 IP 地址为Harbor 服务器的 IP 地址 {"xxx": "xxxx"…

IGH主站通信测试csp模式(DC同步 preemrt)连通一从站并实现控制

IGH主站通信测试 linuxcnc配置基础机器人控制LinuxCNC与EtherCAT介绍&&PDO&SDO&#xff0c;搭建环境步骤 需要配置IGH主站的查看这篇文章 linux系统学习笔记7——一次性安装igh-ethercat主站 CSP模式 DC同步方式 preemrt实时补丁 直接上代码&#xff0c;这…

YOLOV7模型调试记录

先前的YOLOv7模型是pytorch重构的&#xff0c;并非官方提供的源码&#xff0c;而在博主使用自己的数据集进行实验时发现效果并不理想&#xff0c;因此生怕是由于源码重构导致该问题&#xff0c;此外还需进行对比实验&#xff0c;因此便从官网上下载了源码&#xff0c;进行调试运…

二叉树——二叉搜索树中的插入操作

二叉搜索树中的插入操作 链接 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c…

配置二层远程端口镜像案例

实验拓扑&#xff1a; 实验需求&#xff1a; 如图1所示&#xff0c;某公司行政部通过SwitchA与外部Internet通信&#xff0c;监控设备Server通过SwitchB与SwitchA相连。 现在希望Server能够远程对行政部访问Internet的流量进行监控。 操作步骤&#xff1a; 配置观察端口 # 在…

C/C++开发,无可避免的多线程(篇一).跨平台并行编程姗姗来迟

一、编译环境准备 在正式进入c/c多线程编程系列之前&#xff0c;先来搭建支持多线程编译的编译环境。 1.1 MinGW&#xff08;win&#xff09; 进入Downloads - MinGW-w64下载页面&#xff0c;选择MinGW-w64-builds跳转下载&#xff0c; 再次进行跳转&#xff1a; 然后进入下载页…

Fiddler抓包之Fiddler过滤器(Filters)调试

Filters&#xff1a;过滤器&#xff0c;帮助我们过滤请求。 如果需要过滤掉与测试项目无关的抓包请求&#xff0c;更加精准的展现抓到的请求&#xff0c;而不是杂乱的一堆&#xff0c;那功能强大的 Filters 过滤器能帮到你。 2、Filters界面说明 fiddler中的过滤 说明&#…

新增2000w播放、单月涨粉80w!13秒短视频竟成B站热门

知识区自从被设立为一级分区后&#xff0c;B站就成了大家口中的“互联网大学”&#xff0c;有什么不懂的知识就习惯上B站搜一搜、查一查。根据B站官方出具的创作者报告数据显示&#xff0c;除了众多自发原创知识作品的UP主以外&#xff0c;还有超过300位名师学者加入B站&#x…

【亲测可用】BEV Fusion (MIT) 环境配置

CUDA环境 首先我们需要打上对应版本的显卡驱动&#xff1a; 接下来下载CUDA包和CUDNN包&#xff1a; wget https://developer.download.nvidia.com/compute/cuda/11.6.2/local_installers/cuda_11.6.2_510.47.03_linux.run sudo sh cuda_11.6.2_510.47.03_linux.runwget htt…

pytorch-softmax解决分类问题,用fashion-mnist为例子,再走一遍数据获取到模型预测的流程。深度了解分类指标的递进关系

softmax回归 线性回归模型适用于输出为连续值的情景。在另一类情景中&#xff0c;模型输出可以是一个像图像类别这样的离散值。对于这样的离散值预测问题&#xff0c;我们可以使用诸如softmax回归在内的分类模型。和线性回归不同&#xff0c;softmax回归的输出单元从一个变成了…

当ChatGPT遇见Python

在如火如荼的 ChatGPT 大潮当中&#xff0c;已经衍生出了各种各样的周边产品。Python 作为著名的万金油工具&#xff0c;怎么能没有它的身影呢。今天我们就介绍两种通过 Python 调用 ChatGPT 的方法&#xff0c;一起来看看吧~chatgpt-wrapper这是一个开源在 GitHub 上的项目&am…

leetcode 236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自己的祖…

华为机试题:HJ86 求最大连续bit数(python)

文章目录&#xff08;1&#xff09;题目描述&#xff08;2&#xff09;Python3实现&#xff08;3&#xff09;知识点详解1、input()&#xff1a;获取控制台&#xff08;任意形式&#xff09;的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方…

Linux下 C/C++ NTP网络时间协议详解

NTP&#xff08;Network Time Protocol&#xff0c;网络时间协议&#xff09;是由RFC 1305定义的时间同步协议。它是通过网络在计算机系统之间进行时钟同步的网络协议。NTP 在公共互联网上通常能够保持时间延迟在几十毫秒以内的精度&#xff0c;并在理想条件下&#xff0c;它能…

Molecule:使用Jetpack Compose构建StateFlow流

Molecule:使用Jetpack Compose构建StateFlow流 看下面的jetpack compose片段&#xff1a; Composable fun MessageCard(message: Message) {Column {Text(text message.author)Text(text message.body)} }这段代码最有趣的部分是它实际上是reactive。其反应性为 通过Composa…

树链剖分(维护树上信息)

学习前请先掌握线段树&#xff1a;线段树&#xff08;维护区间信息&#xff09; 一&#xff0c;思想&#xff1a; 将一颗树拆成多条线性链以方便维护&#xff08;如线段树&#xff09;。 先给出以下定义&#xff08;通过这些定义我们就可以组成链&#xff09;&#xff1a; …