webpack|【webpack】从零开始配置webpack系列(基础篇)

从零开始配置webpack系列(基础篇)
文章目录

  • 从零开始配置webpack系列(基础篇)
    • 前言
      • 为什么需要打包工具?
      • 有哪些打包工具?
    • 1.基本使用与基本配置
      • 功能介绍
      • 开始使用
        • 1.文件目录
        • 2.下载依赖
        • 3.启用 webpack
        • 4.观察输出文件
      • 基本配置
        • 5大核心概念
        • webpack配置文件
        • 简单修改配置文件
    • 2.一些基础操作
      • 修改输出资源的名称和路径
      • 自动清空上次打包资源
      • 开发服务器&自动化
    • 3.处理 html 资源
    • 4.处理样式资源
      • 处理 Css 资源
      • 处理 Less 资源
      • 处理 Sass 和 Scss 资源
      • 处理 Styl 资源
    • 5.更多CSS处理
      • 提取 Css 成单独文件
      • Css 兼容性处理
      • Css 压缩
    • 6.处理 js 资源
      • Eslint
        • 在 Webpack 中使用
        • VSCode Eslint 插件
      • Babel
        • 配置文件
        • 具体配置
        • 在 Webpack 中使用
    • 7.处理字体图标资源
        • 添加字体图标资源
        • 配置
    • 8.处理图片资源
      • 配置
      • 添加图片资源
      • 使用图片资源
      • 输出资源情况
      • 对图片资源进行优化
    • 9.开发模式与生产模式介绍
      • 开发模式
      • 生产模式
      • 文件目录
      • 修改 webpack.dev.js
      • 修改 webpack.prod.js
      • 配置运行指令

前言 从零开始配置webpack系列(基础篇)
从零开始配置webpack系列(进阶篇)
从零开始配置webpack系列(优化篇)
从零开始配置webpack系列(原理篇)

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

有哪些打包工具?
  • Grunt
  • Gulp
  • Parcel
  • Webpack
  • Rollup
  • Vite

1.基本使用与基本配置 功能介绍
webpack 输出的文件叫做 bundle
webpack 本身功能是有限的:
  • 开发模式:仅能编译 JS 中的 ES Module 语法
  • 生产模式:能编译 JS 中的 ES Module 语法,还能压缩 JS 代码

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


2.下载依赖 打开终端,来到项目根目录。运行以下指令:
  • 初始化package.json
npm init -y

此时会生成一个基础的 package.json 文件。
需要注意的是 package.jsonname 字段不能叫做 webpack, 否则下一步会报错
  • 下载依赖
npm i webpack webpack-cli -D


3.启用 webpack
  • 开发模式
npx webpack ./src/main.js --mode=development

  • 生产模式
npx webpack ./src/main.js --mode=production

npx webpack: 是用来运行本地安装 webpack 包的。
./src/main.js: 指定 webpackmain.js 文件开始打包,不但会打包 main.js,还会将其依赖也一起打包进来。
--mode=xxx:指定模式(环境)。
一般情况下,我们都是直接使用简写形式 npx webpack
4.观察输出文件 默认 webpack 会将文件打包输出到 dist 目录下,我们查看 dist 目录下文件情况就好了

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

webpack配置文件 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", // 开发模式 };

然后运行指令npx webpack

2.一些基础操作 修改输出资源的名称和路径
在下面的配置中,我们将打包好的js文件放在 dist/js 目录中.
对于下面的图片的存放路径,后续会进行介绍.
const path = require("path"); module.exports = { entry: "./src/main.js", output: { path: path.resolve(__dirname, "dist"), filename: "dist/js/main.js", // 将 js 文件输出到 dist/js 目录中 }, module: { rules: [ generator: { // 将图片文件输出到 static/imgs 目录中 // 将图片文件命名 [hash:8][ext][query] // [hash:8]: hash值取8位 // [ext]: 使用之前的文件扩展名 // [query]: 添加之前的query参数 filename: "static/imgs/[hash:8][ext][query]", }, }, ], }, plugins: [], mode: "development", };


自动清空上次打包资源
当我们进行打包后,会生成一个dist目录,但是当我们再一次进行打包时,上一次生成的dist目录并不会清空,所以我们需要手动删除上一次的dist目录。
clean: true 自动将上次打包目录资源清空
const path = require("path"); module.exports = { entry: "./src/main.js", output: { path: path.resolve(__dirname, "dist"), filename: "dist/js/main.js", clean: true, // 自动将上次打包目录资源清空 }, module: { rules: [ generator: { // 将图片文件输出到 static/imgs 目录中 // 将图片文件命名 [hash:8][ext][query] // [hash:8]: hash值取8位 // [ext]: 使用之前的文件扩展名 // [query]: 添加之前的query参数 filename: "static/imgs/[hash:8][ext][query]", }, }, ], }, plugins: [], mode: "development", };


开发服务器&自动化
起初我们想要查看打包好的文件,都是通过点击打开dist目录下的index.html,通过插件open with live server 在浏览器中查看。
插件webpack-dev-server可以实现自动化,我们可以看到每次打包好的页面。
执行命令下载:
npm i webpack-dev-server -D

配置 webpack.config.js
// 开发服务器 devServer: { host: "localhost", // 启动服务器域名 port: "3000", // 启动服务器端口号 open: true, // 是否自动打开浏览器 },

整体文件
const path = require("path"); 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: [ generator: { // 将图片文件输出到 static/imgs 目录中 // 将图片文件命名 [hash:8][ext][query] // [hash:8]: hash值取8位 // [ext]: 使用之前的文件扩展名 // [query]: 添加之前的query参数 filename: "static/imgs/[hash:8][ext][query]", } ] }, plugins: [ 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-dev-server --open 或 npx webpack serve


3.处理 html 资源 首先安装插件:
npm install html-webpack-plugin -D

并且调整 webpack.config.js 文件:
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { //... plugins: [ // 实例化 html-webpack-plugin 插件 new HtmlWebpackPlugin() ] }

打包后,我们发现这个 dist/index.html 似乎与先前的 index.html 并没有关系, HtmlWebpackPlugin 会默认生成它自己的 index.html 文件,并且所有的 bundle(bundle.js) 会自动添加到 html 中。
而我们想要基于原来的 index.html 来生成打包后的 dist/index.html
可以对 html-webpack-plugin 插件进行配置来实现
plugins: [ // 实例化 html-webpack-plugin 插件 new HtmlWebpackPlugin({ template: './index.html', // 以src目录下的 index.html 作为模板创建打包文件 filename: 'app.html', // 打包生成的文件名称。默认为index.html// 设置所有资源文件注入模板的位置。 //可以设置的值 true|'head'|'body'|false,默认值为 true inject: 'body' }) ]


4.处理样式资源 webpack 本身是不能识别样式资源的,所以我们需要借助 loader 来帮助 webpack 解析样式资源。
处理 Css 资源
下载包
npm i css-loader style-loader -D

注意:需要下载两个 loader
功能介绍
  • 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", "css-loader"], }, ], }, plugins: [], mode: "development", };

添加 Css 资源
  • src/css/index.css
.box1 { width: 100px; height: 100px; background-color: pink; }

  • 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(打包好的文件)
webpack5 Hello Webpack5
src="https://www.it610.com/dist/main.js">


处理 Less 资源
下载包
npm i less-loader -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$/, use: ["style-loader", "css-loader", "less-loader"], }, ], }, plugins: [], mode: "development", };

添加 Less 资源
  • src/less/index.less
.box2 { width: 100px; height: 100px; background-color: deeppink; }

  • 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
webpack5 Hello Webpack5
src="https://www.it610.com/dist/main.js">


处理 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"], }, { test: /\.s[ac]ss$/, use: ["style-loader", "css-loader", "sass-loader"], }, ], }, plugins: [], mode: "development", };

添加 Sass 资源
  • src/sass/index.sass
/* 可以省略大括号和分号 */ .box3 width: 100px height: 100px background-color: hotpink

  • src/sass/index.scss
.box4 { width: 100px; height: 100px; background-color: lightpink; }

  • src/main.js
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"; console.log(count(2, 1)); console.log(sum(1, 2, 3, 4));

  • public/index.html
webpack5 Hello Webpack5
src="https://www.it610.com/dist/main.js">


处理 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));

  • public/index.html
webpack5 Hello Webpack5
src="https://www.it610.com/dist/main.js">


5.更多CSS处理 提取 Css 成单独文件
Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式
这样对于网站来说,会出现闪屏现象,用户体验不好
我们应该是单独的 Css 文件,通过 link 标签加载性能才好
下载包
npm i mini-css-extract-plugin -D

配置
  • webpack.prod.js
const path = require("path"); 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"], } ] }, plugins: [ 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 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", ] } ] }, plugins: [ 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"] }

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

合并配置
  • webpack.prod.js
const path = require("path"); 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"), } ] }, plugins: [ 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 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"), } ] }, plugins: [ 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", };


6.处理 js 资源 有人可能会问,js 资源 Webpack 不能已经处理了吗,为什么我们还要处理呢?
原因是 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: [], // ... };

  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 (当被触发的时候,程序会退出)
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 除了少数情况下不会有警告 ], }

  1. extends 继承
开发中一点点写 rules 规则太费劲了,所以有更好的办法,继承现有的规则。
现有以下较为有名的规则:
  • Eslint 官方的规则open in new window:eslint:recommended
  • Vue Cli 官方的规则open in new window:plugin:vue/essential
  • React Cli 官方的规则open in new window:react-app
// 例如在React项目中,我们可以这样写配置 module.exports = { extends: ["react-app"], rules: { // 我们的规则会覆盖掉react-app的规则 // 所以想要修改规则直接改就是了 eqeqeq: ["warn", "smart"], }, };


在 Webpack 中使用
  1. 下载包
npm i eslint-webpack-plugin eslint -D

  1. 定义 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 定义变量 }, };

  1. 修改 js 文件代码
  • main.js
import count from "./js/count"; import sum from "./js/sum"; // 引入资源,Webpack才会对其打包 import "./css/iconfont.css"; import "./css/index.css"; import "./less/index.less"; import "./sass/index.sass"; import "./sass/index.scss"; import "./styl/index.styl"; var result1 = count(2, 1); console.log(result1); var result2 = sum(1, 2, 3, 4); console.log(result2);

  1. 配置
  • 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: [ { // 用来匹配 .css 结尾的文件 test: /\.css$/, // use 数组里面 Loader 执行顺序是从右到左 use: ["style-loader", "css-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"], } ] }, plugins: [ new ESLintWebpackPlugin({ // 指定检查文件的根目录 context: path.resolve(__dirname, "src"), }), ], mode: "development", };


VSCode Eslint 插件 打开 VSCode,下载 Eslint 插件,即可不用编译就能看到错误,可以提前解决
但是此时就会对项目所有文件默认进行 Eslint 检查了,我们 dist 目录下的打包后文件就会报错。但是我们只需要检查 src 下面的文件,不需要检查 dist 下面的文件。
所以可以使用 Eslint 忽略文件解决。在项目根目录新建下面文件:
  • .eslintignore
# 忽略dist目录下所有文件 dist


Babel
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: [], };

  1. presets 预设
简单理解:就是一组 Babel 插件, 扩展 Babel 功能
  • @babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript。
  • @babel/preset-react:一个用来编译 React jsx 语法的预设
  • @babel/preset-typescript:一个用来编译 TypeScript 语法的预设
在 Webpack 中使用
  1. 下载包
npm i babel-loader @babel/core @babel/preset-env -D

  1. 定义 Babel 配置文件
  • babel.config.js
module.exports = { presets: ["@babel/preset-env"], };

  1. 修改 js 文件代码
  • main.js
import count from "./js/count"; import sum from "./js/sum"; // 引入资源,Webpack才会对其打包 import "./css/iconfont.css"; import "./css/index.css"; import "./less/index.less"; import "./sass/index.sass"; import "./sass/index.scss"; import "./styl/index.styl"; const result1 = count(2, 1); console.log(result1); const result2 = sum(1, 2, 3, 4); console.log(result2);

  1. 配置
  • 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: [ { // 用来匹配 .css 结尾的文件 test: /\.css$/, // use 数组里面 Loader 执行顺序是从右到左 use: ["style-loader", "css-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"], }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }, plugins: [ new ESLintWebpackPlugin({ // 指定检查文件的根目录 context: path.resolve(__dirname, "src"), }), ], mode: "development", };


7.处理字体图标资源 添加字体图标资源
  • src/fonts/iconfont.ttf
  • src/fonts/iconfont.woff
  • src/fonts/iconfont.woff2
  • src/css/iconfont.css
    • 注意字体文件路径需要修改
  • src/main.js
import { add } from "./math"; import count from "./js/count"; import sum from "./js/sum"; // 引入资源,Webpack才会对其打包 import "./css/iconfont.css"; 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));

  • public/index.html
webpack5 Hello Webpack5
src="https://www.it610.com/dist/static/js/main.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: [ { // 用来匹配 .css 结尾的文件 test: /\.css$/, // use 数组里面 Loader 执行顺序是从右到左 use: ["style-loader", "css-loader"], }, { 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 形式

8.处理图片资源 过去在 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: [ { // 用来匹配 .css 结尾的文件 test: /\.css$/, // use 数组里面 Loader 执行顺序是从右到左 use: ["style-loader", "css-loader"], }, { test: /\.(png|jpe?g|gif|webp)$/, type: "asset", }, ], }, plugins: [], mode: "development", };

添加图片资源
  • src/images/1.jpeg
  • src/images/2.png
  • src/images/3.gif
使用图片资源
  • src/less/index.less
.box2 { width: 100px; height: 100px; background-image: url("../images/1.jpeg"); background-size: cover; }

  • src/sass/index.sass
.box3 width: 100px height: 100px background-image: url("../images/2.png") background-size: cover

  • src/styl/index.styl
.box5 width 100px height 100px background-image url("../images/3.gif") background-size cover

输出资源情况
此时如果查看 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: [ { // 用来匹配 .css 结尾的文件 test: /\.css$/, // use 数组里面 Loader 执行顺序是从右到左 use: ["style-loader", "css-loader"], }, { test: /\.(png|jpe?g|gif|webp)$/, type: "asset", parser: { dataUrlCondition: { maxSize: 10 * 1024 // 小于10kb的图片会被base64处理 } } }, ], }, plugins: [], mode: "development", };


9.开发模式与生产模式介绍 开发模式
开发模式顾名思义就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:
  1. 编译代码,使浏览器能识别运行:开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源
  2. 代码质量检查,树立代码规范:提前检查代码的一些隐患,让代码运行时能更加健壮。提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。


生产模式
生产模式是开发完成代码后,我们需要得到代码将来部署上线。
这个模式下我们主要对代码进行优化,让其运行性能更好。
优化主要从两个角度出发:
  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
笔记均来自b站尚硅谷webpack入门到原理学习笔记

    推荐阅读