【学习笔记】尚硅谷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代码
开始使用
资源目录
1 | webpack_code # 项目根目录(所有指令必须在这个目录运行) |
创建文件
- count.js
1 | export default function count(x, y) { |
- sum.js
1 | export default function sum(...args) { |
- main.js
1 | import count from "./js/count"; |
下载依赖
打开终端,来到项目根目录。运行以下指令:
- 初始化
package.json
1 | npm init -y |
此时会生成一个基础的 package.json
文件。
需要注意的是 package.json
中 name
字段不能叫做 webpack
, 否则下一步会报错
- 下载依赖
1 | npm i webpack webpack-cli -D |
启用Webpack
输出文件会打包在项目目录下 dist 文件夹下
- 开发模式
1 | # npx会临时改变环境变量,去调用node_moudle中 .bash 文件中的命令 |
- 生产模式
1 | # 此状态下打包会将ES6全部转为ES5 并且压缩代码 |
npx webpack
: 是用来运行本地安装 Webpack
包的。
./src/main.js
: 指定 Webpack
从 main.js
文件开始打包,不但会打包 main.js
,还会将其依赖也一起打包进来。
--mode=xxx
:指定模式(环境)。
Webpack
本身功能比较少,只能处理 js
资源,一旦遇到 css
等其他资源就会报错。(我们需要其他的Webpack工具来帮忙处理)
基本配置
五大核心概念
- entry(入口)
- 指示 Webpack 从哪个文件开始打包
- output(输出)
- 指示 Webpack 打包完的文件输出到哪里去,如何命名等
- loader(加载器)
- webpack 本身只能处理 js、json 等资源,其他资源需要借助 loader,Webpack 才能解析
- plugins(插件)
- 扩展 Webpack 的功能
- mode(模式)
- 开发模式:development
- 生产模式:production
准备Webpack配置文件
- 在项目根目录下新建文件:
webpack.config.js
1 | module.exports = { |
Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范
修改配置文件
- 配置文件
1 | // Node.js的核心模块,专门用来处理文件路径 |
- 运行指令
1 | # 此时webpack会根据配置文件进行打包 |
开发模式介绍
开发模式顾名思义就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:
- 编译代码,使浏览器能识别运行
- 开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源
- 代码质量检查,树立代码规范
- 提前检查代码的一些隐患,让代码运行时能更加健壮。
- 提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。
处理样式资源
- 学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl 样式资源
介绍
Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
我们找 Loader 都应该去官方文档中找到对应的 Loader,然后使用
官方文档找不到的话,可以从社区 Github 中搜索查询
Webpack 官方 Loader 文档open in new window
处理CSS资源
下载包
1 | # 需要下载 css-loader 与 style-loader 两个loader |
功能介绍
css-loader
:负责将 Css 文件编译成 Webpack 能识别的模块style-loader
:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容
此时样式就会以 Style 标签的形式在页面上生效
配置
1 | const path = require("path"); |
添加Css资源
- src/css/index.css
1 | .red { |
- src/main.js
1 | import count from "./js/count"; |
- public/index.html
1 |
|
运行指令
1 | npx webpack |
- 之后会神奇的发现CSS样式在页面中生效啦!
处理Less资源
下载包
1 | npm i less-loader less -D |
功能介绍
less-loader
:负责将 Less 文件编译成 Css 文件
配置
1 | const path = require("path"); |
添加Less资源
- src/less/index.less
1 | .pinkLess { |
- src/main.js
1 | import count from "./js/count"; |
- public/index.html
1 |
|
运行指令
1 | npx webpacl |
处理Styl资源
下载包
1 | npm i stylus-loader -D |
功能介绍
stylus-loader
:负责将 Styl 文件编译成 Css 文件
配置
1 | const path = require("path"); |
添加Styl资源
- src/styl/index.styl
1 | .box |
- src/main.js
1 | import { add } from "./math"; |
运行指令
1 | npx webpack |
处理Sass和Scss资源
下载包
1 | npm i sass-loader sass -D |
功能介绍
sass-loader
:负责将 Sass 文件编译成 css 文件sass
:sass-loader
依赖sass
进行编译
配置
1 | const path = require("path"); |
添加Sass资源
- src/sass/index.scss
1 | .blueScss { |
- src/sass/index.sass
1 | .greenSass |
- src/main.js
1 | import count from "./js/count"; |
运行指令
1 | npx webpack |
处理图片资源
过去在 Webpack4 时,我们处理图片资源通过 file-loader
和 url-loader
进行处理
现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源
配置
1 | const path = require("path"); |
添加图片资源
- src/img/jpegImg.jpeg
- src/img/pngImg.png
- src/img/gifImg.gif
使用图片资源
- src/css/index.css
1 | .jpegImg { |
运行指令
1 | npx webpack |
输出资源情况
- 此时如果查看 dist 目录的话,会发现多了三张图片资源
- 因为 Webpack 会将所有打包好的资源输出到 dist 目录下
- 为什么样式资源没有呢?
- 因为经过
style-loader
的处理,样式资源打包到 main.js 里面去了,所以没有额外输出出来
- 因为经过
对图片资源进行优化
- 将小于某个大小的图片转化成 data URI 形式(Base64 格式)
1 | const path = require("path"); |
- 优点:减少请求数量
- 缺点:体积变得更大
此时输出的图片文件就只有两张,有一张图片以 data URI 形式内置到 js 中了 (注意:需要将上次打包生成的文件清空,再重新打包才有效果)
修改输出资源的名称和路径
配置
1 | const path = require("path"); |
修改index.html
1 |
|
运行指令
1 | npx webpack |
- 此时输出文件目录:
- (注意:需要将上次打包生成的文件清空,再重新打包才有效果)
1 | ├── dist |
自动清空上次打包资源
配置
1 | const path = require("path"); |
运行指令
1 | 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
1 | import "./css/iconfont.css"; |
- public/index.html
1 | <!-- 使用字体图标 --> |
配置
1 | const path = require("path"); |
type: "asset/resource"
和type: "asset"
的区别:
type: "asset/resource"
相当于file-loader
, 将文件转化成 Webpack 能识别的资源,其他不做处理type: "asset"
相当于url-loader
, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式
运行指令
1 | npx webpack |
处理音频资源
配置
1 | const path = require("path"); |
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.json
中eslintConfig
:不需要创建文件,在原有文件基础上写
ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
具体配置
我们以 .eslintrc.js
配置文件为例:
1 | module.exports = { |
parserOptions 解析选项
1
2
3
4
5
6
7parserOptions: {
ecmaVersion: 6, // ES 语法版本
sourceType: "module", // ES 模块化
ecmaFeatures: { // ES 其他特性
jsx: true // 如果是 React 项目,就需要开启 jsx 语法
}
}rules 具体规则
"off"
或0
- 关闭规则"warn"
或1
- 开启规则,使用警告级别的错误:warn
(不会导致程序退出)"error"
或2
- 开启规则,使用错误级别的错误:error
(当被触发的时候,程序会退出)1
2
3
4
5
6
7
8
9
10
11
12rules: {
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 除了少数情况下不会有警告
],
}更多规则详见:规则文档
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
1
2
3
4
5
6
7
8
9// 例如在React项目中,我们可以这样写配置
module.exports = {
extends: ["react-app"],
rules: {
// 我们的规则会覆盖掉react-app的规则
// 所以想要修改规则直接改就是了
eqeqeq: ["warn", "smart"],
},
};
在Webpack中使用
下载包
1 | npm i eslint-webpack-plugin eslint -D |
定义Eslint配置文件
- .eslintrc.js
1 | module.exports = { |
- main.js
1 | // 配置好之后会发现报错 |
- webpack.config.js
1 | const path = require("path"); |
VSCode Webstorm 插件
- 不同的IDE都有对应的Eslint插件,可以对Eslint规则进行报错,还可以配置保存后一键修改,非常舒服。
Bable
- JavaScript 编译器。
- 主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中
配置文件
配置文件由很多种写法:
- babel.config.* :新建文件,位于项目根目录
babel.config.js
babel.config.json
- .babelrc.* :新建文件,位于项目根目录
.babelrc
.babelrc.js
.babelrc.json
package.json
中babel
:不需要创建文件,在原有文件基础上写
Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
具体配置
- babel.config.js
1 | module.exports = { |
presets 预设
简单理解:就是一组 Babel 插件, 扩展 Babel 功能
@babel/preset-env
: 一个智能预设,允许您使用最新的 JavaScript。@babel/preset-react
:一个用来编译 React jsx 语法的预设@babel/preset-typescript
:一个用来编译 TypeScript 语法的预设webpack.config.js
1 | const path = require("path"); |
打开打包后的 dist/static/js/main.js
文件查看,会发现箭头函数等 ES6 语法已经转换了
处理HTML资源
下载包
1 | npm i html-webpack-plugin -D |
配置
- webpack.config.js
1 | const path = require("path"); |
- public/index.html
1 |
|
运行指令
1 | npx webpack |
开发服务器&自动化
每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化
下载包
1 | npm i webpack-dev-server -D |
配置
- webpack.config.js
1 | const path = require("path"); |
运行指令
1 | npx webpack serve |
注意运行指令发生了变化
- 并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。
- 开发时我们只关心代码能运行,有效果即可,至于代码被编译成什么样子,我们并不需要知道。
生产模式介绍
- 生产模式是开发完成代码后,我们需要得到代码将来部署上线。
- 这个模式下我们主要对代码进行优化,让其运行性能更好。
优化主要从两个角度出发:
- 优化代码运行性能
- 优化代码打包速度
文件目录
1 | ├── webpack-test (项目根目录) |
修改 webpack.dev.js
1 | const path = require("path"); |
运行开发模式的指令:
1 | npx webpack serve --config ./config/webpack.dev.js |
修改 webpack.prod.js
1 | const path = require("path"); |
运行生产模式的指令:
1 | npx webpack --config ./config/webpack.prod.js |
配置运行命令
为了方便运行不同模式的指令,我们将指令定义在 package.json 中 scripts 里面
1 | // package.json |
以后启动指令:
- 开发模式:
npm start
或npm run dev
- 生产模式:
npm run build
CSS高级处理
生产CSS文件通过linke引入
- Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式
- 这样对于网站来说,会出现闪屏现象,用户体验不好
- 我们应该是单独的 Css 文件,通过 link 标签加载性能才好
下载包
1 | npm i mini-css-extract-plugin -D |
配置
- webpack.prod.js
- 这里加入了一个插件,在use里面加入了一个loader
1 | const path = require("path"); |
CSS兼容性处理
下载包
1 | npm i postcss-loader postcss postcss-preset-env -D |
配置
- webpack.prod.js
1 | const path = require("path"); |
兼容性控制
- 我们可以在
package.json
文件中添加browserslist
来控制样式的兼容性做到什么程度。
1 | { |
想要知道更多的 browserslist
配置,查看browserslist 文档open in new window
以上为了测试兼容性所以设置兼容浏览器 ie8 以上。
- 实际开发中我们一般不考虑旧版本浏览器了,所以我们可以这样设置:
1 | { |
合并配置
- webpack.prod.js
1 | const path = require("path"); |
CSS压缩
下载包
1 | npm i css-minimizer-webpack-plugin -D |
配置
- webpack.prod.js
1 | const path = require("path"); |
Html压缩JS压缩
- 默认生产模式已经开启了:html 压缩和 js 压缩
- 不需要额外进行配置
总结
本章节我们学会了 Webpack 基本使用,掌握了以下功能:
- 两种开发模式
- 开发模式:代码能编译自动化运行
- 生产模式:代码编译优化输出
- Webpack 基本功能
- 开发模式:可以编译 ES Module 语法
- 生产模式:可以编译 ES Module 语法,压缩 js 代码
- Webpack 配置文件
- 5 个核心概念
- entry
- output
- loader
- plugins
- mode
- devServer 配置
- Webpack 脚本指令用法
webpack
直接打包输出webpack serve
启动开发服务器,内存编译打包没有输出
留言
⛄太感谢谷谷啦,这套课程真的很棒!!!
⭐尚硅谷,让天下有学不完的知识!!!🤣