【学习笔记】尚硅谷Webpack5入门到原理 | 基础篇

WebPack5入门到原理

⛄最近报名了字节跳动的前端青训营,大作业是要做一个组件库项目。

⛄当我自信的打开IDE准备大展身手的时候发现一点思路都没有,网上搜罗了很多教程后发现自己对工程化的知识了解尚浅。

⛄于是就发现了谷谷的这套教程,真的讲的很好,学完Webpack就可以去搭建一个组件库脚手架了。

:本文是对尚硅谷 Web 前端之 Webpack5 教程的学习笔记记录,加入了一些自己的练习改动与思考。

推荐大家去看原视频:尚硅谷Webpack5入门到原理(面试开发一条龙)_哔哩哔哩_bilibili

前言

为什么需要打包工具?

  • 开发时,我们会使用框架(React、Vue),ES6模块化语法,Less/Sass等css 预处理器等语法进行开发。
  • 这样的代码要想在浏览器运行必须经过编译成浏览器能识别的JS、Css 等语法,才能运行。
  • 所以我们需要打包工具帮我们做完这些事。
  • 除此之外,打包工具还能压缩代码、做兼容性处理、提升代码性能等。

有哪些打包工具?

  • Grunt
  • Gulp
  • Parcel
  • Webpack
  • Rollup
  • vite
  • ...

基本使用

  • webpack是一个静态资源打包工具。
  • 它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。
  • 输出的文件就是编译好的文件,就可以在浏览器段运行了。
  • 我们将lebpack输出的文件叫做bundle 。

功能介绍

Webpack本身功能是有限的

  • 开发模式:仅能编译JS中的 ES Module语法,箭头函数等ES6语法不会编译
  • 生产模式:能编译JS中的ES Module语法,还能压缩JS代码

开始使用

资源目录

webpack_code # 项目根目录(所有指令必须在这个目录运行)
    └── src # 项目源码目录
        ├── js # js文件目录
        │   ├── count.js
        │   └── sum.js
        └── main.js # 项目主文件

创建文件

  • count.js
export default function count(x, y) {
  return x - y;
}
  • sum.js
export default function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}
  • main.js
import count from "./js/count";
import sum from "./js/sum";

console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));

下载依赖

打开终端,来到项目根目录。运行以下指令:

  • 初始化package.json
npm init -y

此时会生成一个基础的 package.json 文件。

需要注意的是 package.jsonname 字段不能叫做 webpack, 否则下一步会报错

  • 下载依赖
npm i webpack webpack-cli -D

启用Webpack

输出文件会打包在项目目录下 dist 文件夹下

  • 开发模式
# npx会临时改变环境变量,去调用node_moudle中 .bash 文件中的命令
npx webpack ./src/main.js --mode=development
  • 生产模式
# 此状态下打包会将ES6全部转为ES5 并且压缩代码
npx webpack ./src/main.js --mode=production

npx webpack: 是用来运行本地安装 Webpack 包的。

./src/main.js: 指定 Webpackmain.js 文件开始打包,不但会打包 main.js,还会将其依赖也一起打包进来。

--mode=xxx:指定模式(环境)。

Webpack 本身功能比较少,只能处理 js 资源,一旦遇到 css 等其他资源就会报错。(我们需要其他的Webpack工具来帮忙处理)

基本配置

五大核心概念

  1. entry(入口)
    • 指示 Webpack 从哪个文件开始打包
  2. output(输出)
    • 指示 Webpack 打包完的文件输出到哪里去,如何命名等
  3. loader(加载器)
    • webpack 本身只能处理 js、json 等资源,其他资源需要借助 loader,Webpack 才能解析
  4. plugins(插件)
    • 扩展 Webpack 的功能
  5. mode(模式)
    • 开发模式:development
    • 生产模式:production

准备Webpack配置文件

  • 在项目根目录下新建文件:webpack.config.js
module.exports = {
  // 入口
  entry: "",
  // 输出
  output: {},
  // 加载器
  module: {
    rules: [],
  },
  // 插件
  plugins: [],
  // 模式
  mode: "",
};

Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范

修改配置文件

  • 配置文件
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");

module.exports = {
  // 入口
  // 相对路径和绝对路径都行
  entry: "./src/main.js",
  // 输出
  output: {
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "main.js",
  },
  // 加载器
  module: {
    rules: [],
  },
  // 插件
  plugins: [],
  // 模式
  mode: "development", // 开发模式
};
  • 运行指令
# 此时webpack会根据配置文件进行打包
npx webpack

开发模式介绍

开发模式顾名思义就是我们开发代码时使用的模式。

这个模式下我们主要做两件事

  1. 编译代码,使浏览器能识别运行
    • 开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源
  2. 代码质量检查,树立代码规范
    • 提前检查代码的一些隐患,让代码运行时能更加健壮。
    • 提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。

处理样式资源

  • 学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl 样式资源

介绍

Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源

我们找 Loader 都应该去官方文档中找到对应的 Loader,然后使用

官方文档找不到的话,可以从社区 Github 中搜索查询

Webpack 官方 Loader 文档open in new window

处理CSS资源

下载包

# 需要下载 css-loader 与 style-loader 两个loader
npm i css-loader style-loader -D

功能介绍

  • css-loader:负责将 Css 文件编译成 Webpack 能识别的模块
  • style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容

此时样式就会以 Style 标签的形式在页面上生效

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [
          "style-loader", // 将js中css通过创建 style 标签添加 html 文件中生效
          "css-loader", // 将css资源编译成 commonjs 的模块到js中
        ],
      },
    ],
  },
  plugins: [],
  mode: "development",
};

添加Css资源

  • src/css/index.css
.red {
    color: red;
}
  • src/main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入 Css 资源,Webpack才会对其打包
import "./css/index.css";

console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
  • public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1 class="red">Hello Webpack</h1>
    <script src="../dist/main.js"></script>
</body>
</html>

运行指令

npx webpack
  • 之后会神奇的发现CSS样式在页面中生效啦!

处理Less资源

下载包

npm i less-loader less -D

功能介绍

  • less-loader:负责将 Less 文件编译成 Css 文件

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        // loader: 'xxx', 只能使用一个loader
        // use可以使用多个 loader
        use: ["style-loader", "css-loader", "less-loader"],
      },
    ],
  },
  plugins: [],
  mode: "development",
};

添加Less资源

  • src/less/index.less
.pinkLess {
    color: pink;
}
  • src/main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/index.css";
import "./less/index.less";

console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
  • public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1 class="red">Hello Webpack</h1>
    <h2 class="pinkLess">Hello Webpack Less</h2>
    <script src="../dist/main.js"></script>
</body>
</html>

运行指令

npx webpacl

处理Styl资源

下载包

npm i stylus-loader -D

功能介绍

  • stylus-loader:负责将 Styl 文件编译成 Css 文件

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
    ],
  },
  plugins: [],
  mode: "development",
};

添加Styl资源

  • src/styl/index.styl
.box 
  width 100px 
  height 100px 
  background-color pink
  • src/main.js
import { add } from "./math";
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
import "./styl/index.styl";

console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));

运行指令

npx webpack

处理Sass和Scss资源

下载包

npm i sass-loader sass -D

功能介绍

  • sass-loader:负责将 Sass 文件编译成 css 文件
  • sasssass-loader 依赖 sass 进行编译

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      // scss资源
      {
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
    ],
  },
  plugins: [],
  mode: "development",
};

添加Sass资源

  • src/sass/index.scss
.blueScss {
    color: blue;
}
  • src/sass/index.sass
.greenSass
    color: green
  • src/main.js
import count from "./js/count";
import sum from "./js/sum";
import "./css/index.css";
import "./less/index.less";

import "./sass/index.sass";
import "./sass/index.scss";

console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));

运行指令

npx webpack

处理图片资源

过去在 Webpack4 时,我们处理图片资源通过 file-loaderurl-loader 进行处理

现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  module: {
    rules: [
      // 图片配置
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
      },
    ],
  },
  plugins: [],
  mode: "development",
};

添加图片资源

  • src/img/jpegImg.jpeg
  • src/img/pngImg.png
  • src/img/gifImg.gif

使用图片资源

  • src/css/index.css
.jpegImg {
    height: 100px;
    width: 100px;
    background: url("../img/jpegImg.jpeg");
    background-size: cover;
}

.pngImg {
    height: 100px;
    width: 100px;
    background: url("../img/pngImg.png");
    background-size: cover;
}

.gifImg {
    height: 100px;
    width: 100px;
    background: url("../img/gifImg.gif");
    background-size: cover;
}

运行指令

npx webpack

输出资源情况

  • 此时如果查看 dist 目录的话,会发现多了三张图片资源
  • 因为 Webpack 会将所有打包好的资源输出到 dist 目录下
  • 为什么样式资源没有呢?
    • 因为经过 style-loader 的处理,样式资源打包到 main.js 里面去了,所以没有额外输出出来

对图片资源进行优化

  • 将小于某个大小的图片转化成 data URI 形式(Base64 格式)
const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  module: {
    rules: [
	  //	...
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        }
      },
    ],
  },
  plugins: [],
  mode: "development",
};
  • 优点:减少请求数量
  • 缺点:体积变得更大

此时输出的图片文件就只有两张,有一张图片以 data URI 形式内置到 js 中了 (注意:需要将上次打包生成的文件清空,再重新打包才有效果)

修改输出资源的名称和路径

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  },
  module: {
    rules: [
	  //	...
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
    ],
  },
  plugins: [],
  mode: "development",
};

修改index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 修改引用js的路径 -->
    <script src="../dist/static/js/main.js"></script>
</head>
<body>
    <h1 class="red">Hello Webpack</h1>
    <h2 class="pinkLess">Hello Webpack Less</h2>
    <h2 class="greenSass">Hello Webpack Sass</h2>
    <h2 class="blueScss">Hello Webpack Scss</h2>
    <div class="jpegImg"></div>
    <div class="pngImg"></div>
    <div class="gifImg"></div>
</body>
</html>

运行指令

npx webpack
  • 此时输出文件目录
    • (注意:需要将上次打包生成的文件清空,再重新打包才有效果)
├── dist
    └── static
         ├── imgs
         │    └── 7003350e.png
         └── js
              └── main.js

自动清空上次打包资源

配置

const path = require("path");
module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js",
    clean: true, // 自动将上次打包目录资源清空
  },
  module: {
    rules: [
		// ...
    ],
  },
  plugins: [],
  mode: "development",
};

运行指令

npx webpack

观察 dist 目录资源情况

处理字体图标资源

  • 这里以阿里巴巴矢量图标库为例
  • 图标库地址:https://www.iconfont.cn/

添加字体图标资源

  • src/fonts/iconfont.ttf
  • src/fonts/iconfont.woff
  • src/fonts/iconfont.woff2
  • src/css/iconfont.css

引入资源

  • src/main.js
import "./css/iconfont.css";
  • public/index.html
    <!-- 使用字体图标 -->
    <i class="iconfont icon-arrow-down"></i>
    <i class="iconfont icon-ashbin"></i>
    <i class="iconfont icon-browse"></i>

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空
  },
  module: {
    rules: [
      // 添加此处配置
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
    ],
  },
  plugins: [],
  mode: "development",
};

type: "asset/resource"type: "asset"的区别:

  1. type: "asset/resource" 相当于file-loader, 将文件转化成 Webpack 能识别的资源,其他不做处理
  2. type: "asset" 相当于url-loader, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式

运行指令

npx webpack

处理音频资源

配置

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空
  },
  module: {
    rules: [
      // 添加此处配置
      {
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
    ],
  },
  plugins: [],
  mode: "development",
};

JS兼容性与代码格式规范

Webpack 对 js 处理是有限的,只能编译 js 中 ES 模块化语法,不能编译其他语法,导致 js 不能在 IE 等浏览器运行,所以我们希望做一些兼容性处理。

其次开发中,团队对代码格式是有严格要求的,我们不能由肉眼去检测代码格式,需要使用专业的工具来检测。

  • 针对 js 兼容性处理,我们使用 Babel 来完成
  • 针对代码格式,我们使用 Eslint 来完成

我们先完成 Eslint,检测代码格式无误后,在由 Babel 做代码兼容性处理

ESLint

  • 可组装的 JavaScript 和 JSX 检查工具
  • 这句话意思就是:它是用来检测 js 和 jsx 语法的工具,可以配置各项功能
  • 我们使用 Eslint,关键是写 Eslint 配置文件,里面写上各种 rules 规则,将来运行 Eslint 时就会以写的规则对代码进行检查

配置文件

配置文件由很多种写法:

  • .eslintrc.*:新建文件,位于项目根目录
    • .eslintrc
    • .eslintrc.js
    • .eslintrc.json
    • 区别在于配置格式不一样
  • package.jsoneslintConfig:不需要创建文件,在原有文件基础上写

ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

具体配置

我们以 .eslintrc.js 配置文件为例:

module.exports = {
  // 解析选项
  parserOptions: {},
  // 具体检查规则
  rules: {},
  // 继承其他规则
  extends: [],
  // ...
  // 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
};
  1. parserOptions 解析选项

parserOptions: {

 ecmaVersion: 6, // ES 语法版本
 sourceType: "module", // ES 模块化
 ecmaFeatures: { // ES 其他特性
   jsx: true // 如果是 React 项目,就需要开启 jsx 语法
 }

}

  1. rules 具体规则
  • "off"0 - 关闭规则
  • "warn"1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
  • "error"2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
 ```javascript
 rules: {
   semi: "error", // 禁止使用分号
   'array-callback-return': 'warn', // 强制数组方法的回调函数中有 return 语句,否则警告
   'default-case': [
     'warn', // 要求 switch 语句中有 default 分支,否则警告
     { commentPattern: '^no default$' } // 允许在最后注释 no default, 就不会有警告了
   ],
   eqeqeq: [
     'warn', // 强制使用 === 和 !==,否则警告
     'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告
   ],
 }
 ```
 更多规则详见:[规则文档](https://eslint.bootcss.com/docs/rules/)
  1. extends 继承
  • 开发中一点点写 rules 规则太费劲了,所以有更好的办法,继承现有的规则。
 现有以下较为有名的规则:
 - [Eslint 官方的规则open in new window](https://eslint.bootcss.com/docs/rules/):`eslint:recommended`
 - [Vue Cli 官方的规则open in new window](https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-eslint):`plugin:vue/essential`
 - [React Cli 官方的规则open in new window](https://github.com/facebook/create-react-app/tree/main/packages/eslint-config-react-app):`react-app`
   ```javascript
   // 例如在React项目中,我们可以这样写配置
   module.exports = {
     extends: ["react-app"],
     rules: {
       // 我们的规则会覆盖掉react-app的规则
       // 所以想要修改规则直接改就是了
       eqeqeq: ["warn", "smart"],
     },
   };
   ```

在Webpack中使用

下载包

npm i eslint-webpack-plugin eslint -D

定义Eslint配置文件

  • .eslintrc.js
module.exports = {
  // 继承 Eslint 规则
  extends: ["eslint:recommended"],
  env: {
    node: true, // 启用node中全局变量
    browser: true, // 启用浏览器中全局变量
  },
  parserOptions: {
    ecmaVersion: 6,
    sourceType: "module",
  },
  rules: {
    "no-var": 2, // 不能使用 var 定义变量
  },
};
  • main.js
// 配置好之后会发现报错
var result1 = count(2, 1);
console.log(result1);
var result2 = sum(1, 2, 3, 4);
console.log(result2);
  • webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空
  },
  module: {
    rules: [
    ],
  },
  // 加入插件 Webpack 在编译时会对Eslint进行报错
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
    }),
  ],
  mode: "development",
};

VSCode Webstorm 插件

  • 不同的IDE都有对应的Eslint插件,可以对Eslint规则进行报错,还可以配置保存后一键修改,非常舒服。

Bable

  • JavaScript 编译器。
  • 主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中

配置文件

配置文件由很多种写法:

  • babel.config.* :新建文件,位于项目根目录
    • babel.config.js
    • babel.config.json
  • .babelrc.* :新建文件,位于项目根目录
    • .babelrc
    • .babelrc.js
    • .babelrc.json
  • package.jsonbabel:不需要创建文件,在原有文件基础上写

Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

具体配置

  • babel.config.js
module.exports = {
  // 预设
  presets: [],
};

presets 预设

简单理解:就是一组 Babel 插件, 扩展 Babel 功能

  • @babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript。
  • @babel/preset-react:一个用来编译 React jsx 语法的预设
  • @babel/preset-typescript:一个用来编译 TypeScript 语法的预设
  • webpack.config.js
const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空
  },
  module: {
    rules: [
      // 对js进行编译
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [],
  mode: "development",
};

打开打包后的 dist/static/js/main.js 文件查看,会发现箭头函数等 ES6 语法已经转换了

处理HTML资源

下载包

npm i html-webpack-plugin -D

配置

  • webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空
  },
  module: {
    rules: [],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "public/index.html"),
    }),
  ],
  mode: "development",
};
  • public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>webpack5</title>
    <!-- 去除对js的引入 HtmlWebpackPlugin 会自动引入 -->
  </head>
  <body>
	<!-- ... -->
  </body>
</html>

运行指令

npx webpack

开发服务器&自动化

每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化

下载包

npm i webpack-dev-server -D

配置

  • webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry: "./src/main.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
        clean: true, // 自动将上次打包目录资源清空
    },
    module: {
        rules: [
            // ...
        ],
    },
    plugins: [
        // ...
    ],
    // 开发服务器
    devServer: {
        host: "localhost", // 启动服务器域名
        port: "3000", // 启动服务器端口号
        open: true, // 是否自动打开浏览器
    },
    mode: "development",
};

运行指令

npx webpack serve

注意运行指令发生了变化

  • 并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。
  • 开发时我们只关心代码能运行,有效果即可,至于代码被编译成什么样子,我们并不需要知道。

生产模式介绍

  • 生产模式是开发完成代码后,我们需要得到代码将来部署上线。
  • 这个模式下我们主要对代码进行优化,让其运行性能更好。

优化主要从两个角度出发:

  1. 优化代码运行性能
  2. 优化代码打包速度

文件目录

├── webpack-test (项目根目录)
    ├── config (Webpack配置文件目录)
    │    ├── webpack.dev.js(开发模式配置文件)
    │    └── webpack.prod.js(生产模式配置文件)
    ├── node_modules (下载包存放目录)
    ├── src (项目源码目录,除了html其他都在src里面)
    │    └── 略
    ├── public (项目html文件)
    │    └── index.html
    ├── .eslintrc.js(Eslint配置文件)
    ├── babel.config.js(Babel配置文件)
    └── package.json (包的依赖管理配置文件)

修改 webpack.dev.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: undefined, // 开发模式没有输出,不需要指定输出目录
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    // clean: true, // 开发模式没有输出,不需要清空输出结果
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  // 其他省略
  devServer: {
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
  },
  mode: "development",
};

运行开发模式的指令:

npx webpack serve --config ./config/webpack.dev.js

修改 webpack.prod.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

运行生产模式的指令:

npx webpack --config ./config/webpack.prod.js

配置运行命令

为了方便运行不同模式的指令,我们将指令定义在 package.json 中 scripts 里面

// package.json
{
  // 其他省略
  "scripts": {
    "start": "npm run dev",
    "dev": "npx webpack serve --config ./config/webpack.dev.js",
    "build": "npx webpack --config ./config/webpack.prod.js"
  }
}

以后启动指令:

  • 开发模式:npm startnpm run dev
  • 生产模式:npm run build

CSS高级处理

生产CSS文件通过linke引入

  • Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式
  • 这样对于网站来说,会出现闪屏现象,用户体验不好
  • 我们应该是单独的 Css 文件,通过 link 标签加载性能才好

下载包

npm i mini-css-extract-plugin -D

配置

  • webpack.prod.js
  • 这里加入了一个插件,在use里面加入了一个loader
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

CSS兼容性处理

下载包

npm i postcss-loader postcss postcss-preset-env -D

配置

  • webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
        ],
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
          "less-loader",
        ],
      },
      {
        test: /\.s[ac]ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
          "sass-loader",
        ],
      },
      {
        test: /\.styl$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
          "stylus-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

兼容性控制

  • 我们可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。
{
  // 其他省略
  "browserslist": ["ie >= 8"]
}

想要知道更多的 browserslist 配置,查看browserslist 文档open in new window

以上为了测试兼容性所以设置兼容浏览器 ie8 以上。

  • 实际开发中我们一般不考虑旧版本浏览器了,所以我们可以这样设置:
{
  // 其他省略
  "browserslist": ["last 2 version", "> 1%", "not dead"]
}

合并配置

  • webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

// 获取处理样式的Loaders
// 谷谷太贴心了 上面代码耦合度比较高 这里直接写了一个函数处理 很好的做法
const getStyleLoaders = (preProcessor) => {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

CSS压缩

下载包

npm i css-minimizer-webpack-plugin -D

配置

  • webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
    // css压缩
    new CssMinimizerPlugin(),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

Html压缩JS压缩

  • 默认生产模式已经开启了:html 压缩和 js 压缩
  • 不需要额外进行配置

总结

本章节我们学会了 Webpack 基本使用,掌握了以下功能:

  1. 两种开发模式
  • 开发模式:代码能编译自动化运行
  • 生产模式:代码编译优化输出
  1. Webpack 基本功能
  • 开发模式:可以编译 ES Module 语法
  • 生产模式:可以编译 ES Module 语法,压缩 js 代码
  1. Webpack 配置文件
  • 5 个核心概念
    • entry
    • output
    • loader
    • plugins
    • mode
  • devServer 配置
  1. Webpack 脚本指令用法
  • webpack 直接打包输出
  • webpack serve 启动开发服务器,内存编译打包没有输出

留言

⛄太感谢谷谷啦,这套课程真的很棒!!!

⭐尚硅谷,让天下有学不完的知识!!!?

本文转载于网络 如有侵权请联系删除

相关文章

  • Springboot环境中多个DataSource基于自定义注解进行切换使用过程

    前面配置了mysql数据库的主从复制模式,在数据库上实现了master-slave配置,通过这种方式可以实现一主一从,或者一主多从,从而提升系统的高可用。 这是数据库层面的实现。在数据库实现了主从模式之后,我们需要考率的问题就是,在我们的应用代码中,如何将不同的数据库操作按需要分配到不同的数据库去执行。1.需要的依赖implementation'org.springframework.boot:spring-boot-starter' implementation'org.springframework.boot:spring-boot-starter-web' implementation'org.springframework.boot:spring-boot-starter-aop' implementation'mysql:mysql-connector-java:8.0.25' implementation'com.zaxxer:HikariCP:4.0.3'复制2.yml配置

  • NLU新里程碑,微软DeBERTa登顶SuperGLUE排行榜,显著超越人类

    机器之心报道参与:小舟、陈萍在最新的NLU测试基准SuperGLUE中,微软提出的DeBERTa登顶榜单,并超越人类。去年6月,来自微软的研究者提出一种新型预训练语言模型DeBERTa,该模型使用两种新技术改进了BERT和RoBERTa模型。8月,该研究开源了模型代码,并提供预训练模型下载。最近这项研究又取得了新的进展。微软最近通过训练更大的版本来更新DeBERTa模型,该版本由48个Transformer层组成,带有15亿个参数。本次扩大规模带来了极大的性能提升,使得单个DeBERTa模型SuperGLUE上宏平均(macro-average)得分首次超过人类(89.9vs89.8),整体DeBERTa模型在SuperGLUE基准排名中居于首位,以90.3的得分显著高出人类基线(89.8)。目前该模型以90.8的宏平均(macro-average)得分高居GLUE基准排名的首位。SuperGLUE排行榜,2021年1月6日。DeBERTa是一种基于Transformer,使用自监督学习在大量原始文本语料库上预训练的神经语言模型。像其他PLM一样,DeBERTa旨在学习通用语言表征,可

  • Android编程设计模式之Builder模式实例详解

    本文实例讲述了Android编程设计模式之Builder模式。分享给大家供大家参考,具体如下:一、介绍Builder模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细的控制对象的构造流程。该模式是为了将构建复杂对象的过程和它的部件解耦,使得构建过程和部件的表示隔离开来。因为一个复杂的对象有很多大量组成部分,例如车,有车轮、方向盘、发动机,还有各种小零件等,如何将这些部件装配成一辆汽车,这个装配过程很漫长,也很复杂,对于这种情况,为了在构建过程中对外部隐藏实现细节,就可以使用Builder模式将部件和组装过程分离,使得构建过程和部件都可以自由扩展,两者之间的耦合也降到最低。二、定义将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。三、使用场景(1)相同的方法,不同的执行顺序,产生不同的事件结果时。(2)多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时。(3)产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用,这个时候使用建造者模式非常合适。(4)当初始化一个对象特别复杂,如参数多,且很多参数都

  • CloudBase CMS 2.0 焕新升级,从「心」出发!

    CloudBaseCMS 是一个基于云开发+Node+React构建的HeadlessCMS系统。不久前,我们开源发布了 CloudBaseCMS(内容管理系统)1.0,收获了许多用户的喜爱。同时,我们也收到了用户的热心反馈,了解到CloudBaseCMS还存在一些不足之处,由此,我们决定持续打磨、优化CloudBaseCMS,来为广大用户提供更好的内容管理解决方案。经过长时间的充分准备和开源团队的共同努力,CloudBaseCMS2.0迎来了全新升级,正式与大家见面了!在2.0版本中,我们从用户的角度出发,进行了大刀阔斧地改进,并引入了许多好玩又走心的实用能力,下面就来一起看看吧~UI界面本次更新最重大的改变之一就是UI界面,我们采用新的设计规范,升级了CMS的UI界面交互,让它变得更为简洁、可拓展性更高,以简化二次开发的难度。新UI如下图所示:布局优化在CMS1.0中,当部分字段内容过长时,会挤压其他字段的显示空间,图片的大小也会显著影响内容集合的展示,造成不合理的显示效果,如下:而在CMS2.0中,我们优化了内容数据的展示效果,根据字段的类型不同,都做了对应的展示优化,以提供更好

  • Centos查看端口占用情况和开启端口命令

    Centos查看端口占用情况命令,比如查看80端口占用情况使用如下命令: lsof-itcp:80 列出所有端口 netstat-ntlp 1、开启端口(以80端口为例)    方法一:      /sbin/iptables-IINPUT-ptcp--dport80-jACCEPT 写入修改      /etc/init.d/iptablessave 保存修改     serviceiptablesrestart  重启防火墙,修改生效     方法二:     vi/etc/sysconfig/iptables 打开配置文件加入如下语句:     -AINPUT-ptcp-mstate--stateNEW-mtcp--dport80-jACCEPT 重启防火墙,修改完成 2、关闭端口    方法一:      /sbin/iptables-IINPUT-ptcp--dport80-jDROP 写入修改      /etc/init.d/iptablessave 保存修改     serviceiptablesrestart  重

  • 5. Jetpack源码解析---ViewModel基本使用及源码解析

    截止到目前为止,JetpackNote源码分析的文章已经有四篇文章了,这一系列的文章我的初衷是想仔细研究一下Jetpack,最终使用Jetpack组件写一个Demo,上一篇已经分析了LiveData,本篇文章将分析ViewModel. 1.背景Jetpack源码解析系列文章:1.Jetpack源码解析—看完你就知道Navigation是什么了?2.Jetpack源码解析—Navigation为什么切换Fragment会重绘?3.Jetpack源码解析—用Lifecycles管理生命周期4.Jetpack源码解析—LiveData的使用及工作原理上篇我们对LiveData进行了分析,已清楚了它的主要作用,我们再来温习一下:LiveData是一个可以感知Activity、Fragment生命周期的数据容器。其本身是基于观察者模式设计的,当LiveData所持有的数据发生改变时,它会通知对应的界面所持有该数据的UI进行更新,并且LiveData中持有Lifecycle的引用,所以只会在LifecycleOwner处于Active的状态下通知数据改变,果数据改变发生在非active状态,数据会

  • Java基于百度API的图片文字识别

    具体文档:http://ai.baidu.com/docs#/OCR-API/e1bd77f3准备工作:基于Java1.8版本控制:maven使用之前需要获取对应的项目API_KEY,SECRET_KEY,这些参数在使用API的时候必须用到,用于生成access_token。如何获取这些参数:在百度开发者中心申请一个“通用文字识别”项目,然后就可以获取到这些参数。准备工作都完成了,现在开始进行图像识别了。1.准备pom文件<!--https://mvnrepository.com/artifact/com.alibaba/fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.46</version> </dependency> <!--https://mvnrepository.com/artifact/org.apache

  • 聊聊storm的LinearDRPCTopologyBuilder

    序本文主要研究一下storm的LinearDRPCTopologyBuilder实例manualdrpc@Test publicvoidtestManualDRPC()throwsInvalidTopologyException,AuthorizationException,AlreadyAliveException{ TopologyBuilderbuilder=newTopologyBuilder(); DRPCSpoutspout=newDRPCSpout("exclamation");//Fields("args","return-info") //spout为DRPCSpout,组件id为drpc builder.setSpout("drpc",spout); builder.setBolt("exclaim",newManualExclaimBolt(),3).shuffleGrouping("drpc");//Fields("result&qu

  • 解决Octopress博客访问慢的问题

    解决Octopress博客访问慢的问题本博情况前身为http://androidyue.github.io新域名droidyue.com从Godaddy购买。DNS由DNSPod解析。内容存放在GithubPages。博客系统为Octopress必不可少的罗嗦买了这个域名已经一周了,已经决定博客的面向群体为汉语用户。但是发现国内访问还是超级慢,慢的让人无法接收了,当然具体原因,大家都懂得。没办法,尝试使用过安全宝,速度并没有明显替身,反而搜索引擎收录加少了,遂弃用。于是只好自己修改Octopress程序了。修改之前的访问速度以分钟计数。修改完成之后,秒开了有木有。清理没用的服务以下修改均修改_config.yml,以下可以根据自己的需要进行去除。去除Disqus评论去除上面红色区域的部分,打开文件找到DisqusComments,按照下面在每一行前面加#注释掉即可。1 2 3#DisqusComments #disqus_short_name:androidyue #disqus_show_comment_count:true去掉Github仓库展示1 2 3 4 5#Githubre

  • .NET Core采用的全新配置系统[10]: 配置的同步机制是如何实现的?

    配置的同步涉及到两个方面:第一,对原始的配置文件实施监控并在其发生变化之后从新加载配置;第二,配置重新加载之后及时通知应用程序进而使后者能够使用最新的配置。要了解配置同步机制的实现原理,先得从认识一个名为ConfigurationReloadToken的类型开始。目录 一、从ConfigurationReloadToken说起 二、Configuration对象与配置文件的同步 三、应用重新加载的配置 四、同步流程总结一、从ConfigurationReloadToken说起.NETCore绝大部分的数据同步场景下都使用到一个名为ChangeToken的对象,该对象绑定到某个需要被监控的对象,并该对象发生改变是对外发送通知,我们可以注册在被监控数据发生改变时可以自动执行的回调。在配置同步场景中,ConfigurationProvider会利用FileProvider监控配置文件的变化,并在变化时从新加载配置。ConfigurationReloadToken就是一个通知配置已经被重新加载的ChangeToken。ConfigurationReloadToken本质上是对一个Cancell

  • CF86D Powerful array

    题意翻译 题意:给出一个n个数组成的数列a,有t次询问,每次询问为一个[l,r]的区间,求区间内每种数字出现次数的平方×数字的值的和。 输入:第一行2个正整数n,t。 接下来一行n个正整数,表示数列a1​~an的值。 接下来t行,每行两个正整数l,r,为一次询问。 输出:t行,分别为每次询问的答案。 数据范围:1≤n,t≤2∗105,1≤ai≤106,1≤l,r≤n 题目描述 Anarrayofpositiveintegersa1,a2,...,ana_{1},a_{2},...,a_{n}a1​,a2​,...,an​isgiven.Letusconsideritsarbitrarysubarrayal,al+1...,ara_{l},a_{l+1}...,a_{r}al​,al+1​...,ar​,where1<=l<=r<=n1<=l<=r<=n1<=l<=r<=n.ForeverypositiveintegersssdenotebyKsK_{s}Ks​thenumberofoccurrencesofsssintothesub

  • find命令的使用

      查询redis占用端口号:  netstat-tnlp|grepredis       在以.conf结尾的文件里面查找含有aaa字符串的那一行  (-name后面可以写 "*.*" 即匹配所有的文件) find/-name"*.conf"|xargsgrep"aaa" 在当前目录下查找MEMBERINTERFACE这个字符串的文件find.-name'*'|xargsgrep"MEMBERINTERFACE"   在根目录下查找文件名find/-namehttpd.conf这个命令语法看起来很容易就明白了,就是直接在find后面写上-name,表明要求系统按照文件名查找,最后写上httpd.conf这个目标文件名即可。稍等一会系统会在计算机屏幕上显示出查找结果列表:etc/httpd/conf/httpd.conf   查找文件名还可以用 locate命令.如果没有locate命令,就yun下载一下 queue-callswaiting   打开一个文件,查找

  • CentOS 7 安装 Oracle 11.2.0.4

    一、安装环境 CentOSLinuxrelease7.2.1511(Core) OracleDatabase11gRelease2(11.2.0.4) 二、安装前准备 2.1修改主机名 修改/etc/sysconfig/network配置文件中的HOSTNAME变量 [root@xqzt~]#hostnamectlset-hostnameoracledb ####永久性修改 [root@xqzt~]#vi/etc/sysconfig/network NETWORKING=yes HOSTNAME=oracledb [root@xqzt~]#hostname oracledb复制 2.2添加主机名与IP对应记录 [root@xqzt~]#vi/etc/hosts 172.17.22.70oracledb复制 2.3关闭Selinux [root@oracledb~]#sed-i"s/SELINUX=enforcing/SELINUX=disabled/"/etc/selinux/config [root@oracledb~]#setenforce0复制 2.4firewall

  • C++.extern

    .h #pragmaonce externintg_i;/*声明,未分配内存*/ extern"C"int__cdeclfn1(inti,shortj);/*extern"C"即不进行名称粉碎*/ char__stdcallfn2(inti,shortj,charc); short__fastcallfn3(charc,inti,shortj); classA { public: A(){} ~A(){} intfn4(inti,shortj,charc); }; /************************************************************************/ /* ?.obj中存储名称粉碎信息 ?fn2@@YGDHFD@Z ?fn3@@YIFDHF@Z ?fn4@A@@QAEHHFD@Z ?fn2名称粉碎 @@YGDHFD参数信息 @Z返回值信息 @A类成员函数则包含类信息 可用C:\ProgramFiles(x86)\MicrosoftVisualStudio14.0\VC\bin\undname.exe查看函数声明 C

  • 容器化-Docker-1-速查手册-Docker常用命令

    目录备注常用命令Docker镜像管理(操作对象是镜像)Docker容器管理(操作对象是容器)容器外挂目录(宿主目录映射到容器中) 这篇文章的目的就是把最常用的命令列出来,没时间看速查命令使用 备注 实验环境:Centos7.43.10.0-693.el7.x86_64 常用命令 Docker镜像管理(操作对象是镜像) 检索镜像dockersearchredis 下载镜像dockerpulldocker.io/redis 下载运行dockerrun-i-t-d-p6379:6379--name=redis1docker.io/redis#逻辑:先找本地,本地没有搜镜像源,有下载运行,没有报错 查看镜像dockerimages 删除镜像dockerrmidocker.io/redis Docker容器管理(操作对象是容器) 运行一个容器dockerrun-itd-p6379:6379--name=redis1--cpus=3-m=3gdocker.io/redis 查看运行容器dockerps 查看运行和已经停止的容器dockerps-a 停止一个容器dockerstop19cf74

  • cad.net 图元反应器+图元事件

    cad内置的图元事件 usingAutodesk.AutoCAD.DatabaseServices; usingAutodesk.AutoCAD.EditorInput; usingAutodesk.AutoCAD.Runtime; usingAcap=Autodesk.AutoCAD.ApplicationServices.Application; usingAutodesk.AutoCAD.Geometry; usingSystem; namespaceJoinBox { #ifNET48 publicclassCommand_Test_MTextModified { [CommandMethod("Test_MTextModified",CommandFlags.Modal|CommandFlags.UsePickSet|CommandFlags.DocExclusiveLock)] publicvoidTest_MTextModified() { Databasedb=HostApplicationServices.WorkingDatabase;//当前的数据库 //usi

  • 手写哈希表bool find(int x)

    开放寻址法 intfind(intx){ intt=(x%N+N)%N;/正数负数都存到里面找个位置给他 while(h[t]!=null&&h[t]!=x){//如果这个位置有值但是不是那个位置就找下个位置 t++; if(t==N)t=0;//到了尽头回去 } returnt; } 复制 LLfind(intx,intt){//哈希记录两个值 LLkey=r*100ll+t;/正数负数都存到里面找个位置给他 intk=key%M; while(h[key]!=-1&&h[K]!=key){//如果这个位置有值但是不是那个位置就找下个位置 if(++k==M)k=0;//到了尽头回去 } if(h[k]==-1)h[k]=key,cnt[k]=0; returnk;//找到了 } 复制 https://www.acwing.com/problem/content/4614/ #include<iostream> #include<cstring> #include<algorithm> usingnamespac

  • NOI2019 游记

    day-1 广二真好看QAQ(要是我也能在这里读书就好了) 提供的餐饮好评QAQ 发现室友是雅礼集训时候的室友,衡水小姐姐zyn。 但是寝室没有网没有信号没有桌子真的不良心啊...... 发现小卖部没有开门,于是和bluesky,dreagonm,maomao和主席跑出去很远去万达买了水......结果回来它就开了....... 没网了,不写了 day0 本来准备睡到7点的六点多起床铃一响就睡不着了。吃完饭发现距离开幕式还有一个多小时,去自习室也没开门......于是只能回去睡觉。 开幕式暨NOI35周年颁奖典礼出锅不断 给姚期智先生写1946-今天是什么鬼,这这这不太合适吧...... 表演强行插入广告???为什么没有ccf啊喂 落雨天,零零零 司队tql,司队NOI横着走 好多放送事故......(逃) 顺便一提,主持人救场能力max,表白这个小姐姐qaq 中午睡了两个小时,下午参加笔试,心情紧张但最后还是AK了(又见到了zhf神仙,膜拜一波希望沾点灵气) 试机题有点令人惊恐......明示字符串,计数和交互题吗??那我完了啊,都一点不会啊嘤嘤嘤 不过......坐在NOI现场,竟

  • MySQL数据库

    一、多表查询 1.创建表01和02 CREATETABLEjing01( idintNOTNULLauto_incrementPRIMARYkey, a_noVARIANCE(20)notnull,#学号 b_nameVARIANCE(20)notnull#学生姓名 ) CHARACTERSETutf_8; 复制   

  • C# Enum,Int,String的互相转换 枚举转换

    Enum为枚举提供基类,其基础类型可以是除Char外的任何整型。如果没有显式声明基础类型,则使用Int32。编程语言通常提供语法来声明由一组已命名的常数和它们的值组成的枚举。 注意:枚举类型的基类型是除Char外的任何整型,所以枚举类型的值是整型值。 Enum提供一些实用的静态方法: (1)比较枚举类的实例的方法 (2)将实例的值转换为其字符串表示形式的方法 (3)将数字的字符串表示形式转换为此类的实例的方法 (4)创建指定枚举和值的实例的方法。 举例:enumColors{Red,Green,Blue,Yellow}; Enum-->String (1)利用Object.ToString()方法:如Colors.Green.ToString()的值是"Green"字符串; (2)利用Enum的静态方法GetName与GetNames: publicstaticstringGetName(TypeenumType,Objectvalue) publicstaticstring[]GetNames(TypeenumType) 例如:Enum.GetName

  • 攻防世界赛题分析

    大概花了六周左右的时间,刷了攻防世界的pwn题,刷到了第二名(有图为证),做的有几道题flag都拿到了,提交入口给关了,交上去的话应该第一了,本来想接着刷的,但连续遇到几次libc和赛题平台的问题,加上这个平台主要偏新手入门,而且我后面还有别的任务,种种原因,后面应该不会再在上面刷pwn了,要刷也到别的地方了(CTFCollege、BUUCTF) 排名截图(截止2022.07.21) 目录1000levels4-ReeHY-main-100format2AulNoleakhacknotebabyfengshuiecho_backRCalcHMI跑马灯supermarketeasyformatnobug250house_of_greyEasyPwnbabyheapmagicshellplayshaxiansecret_holderhouseoforange 1000levels 函数返回会恢复战帧,但是不会去破坏栈上内容,导致system函数地址仍然留在栈上 并列函数的EBP可能是相同的 提示我们如果源码看不出利用门道,可以看更细粒度的汇编 利用vsyscall绕过PI

相关推荐

推荐阅读