文章目录
【前端目录贴】
参考视频:尚硅谷Webpack5入门到原理
课件地址
1. 基本使用
1.1 功能介绍
Webpack
是一个静态资源打包工具。
它会以一个
或多个
文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。
输出的文件就是编译好的文件,就可以在浏览器段运行了。
我们将Webpack
输出的文件叫做bundle
。
Webpack 本身功能是有限的:
- 开发模式:仅能编译 JS 中的
ES Module
语法- 生产模式:能编译 JS 中的
ES Module
语法,还能压缩 JS 代码
1.2 开始使用
- 资源目录
webpack_code # 项目根目录(所有指令必须在这个目录运行)
└── src # 项目源码目录
├── js # js文件目录
│ ├── count.js
│ └── sum.js
└── main.js # 项目主文件
└── public # 静态资源目录
└── test.html #html文件
- 创建文件
count.js
function count(a, b) {
return a-b;
}
module.exports=count;
sum.js
function sum(...args) {
a=0;
for (let i = 0; i < args.length; i++) {
a+=args[i];
}
return a;
}
module.exports=sum;
main.js
var count = require('./js/count');
var sum = require('./js/sum');
console.log(count(3,5))
console.log(sum(1,2,3))
- 安装webpack和webpack-cli依赖
npm i webpack webpack-cli -D
- 打包
# 开发模式 npx webpack ./src/main.js --mode=development
# 生产模式 npx webpack ./src/main.js --mode=production
npx webpack
: 是用来运行本地安装 Webpack 包的
./src/main.js
: 指定 Webpack 从 main.js 文件开始打包,不但会打包 main.js,还会将其依赖也一起打包进来。
--mode=xxx
:指定模式(环境)。
- 观察输出文件
默认
Webpack
会将文件打包输出到dist
目录下,我们查看 dist 目录下文件情况就好了
- 总结
Webpack 本身功能比较少,只能处理
js 资源
,一旦遇到 css 等其他资源就会报错。
所以我们学习 Webpack,就是主要学习如何处理其他资源。
1.3 基本配置
1.3.1 介绍
- entry(入口)
指示 Webpack 从哪个文件开始打包
- output(输出)
指示 Webpack 打包完的文件输出到哪里去,如何命名等
- loader(加载器)
webpack 本身只能处理 js、json 等资源,其他资源需要借助 loader,Webpack 才能解析
- plugins(插件)
扩展 Webpack 的功能
- mode(模式)
主要由两种模式:
开发模式:development
生产模式:production(会进行压缩)
1.3.2 准备 Webpack 配置文件
在项目根目录下新建文件:webpack.config.js
(Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范)
module.exports = {
// 入口
entry: "",
// 输出
output: {},
// 加载器
module: {
rules: [],
},
// 插件
plugins: [],
// 模式
mode: "",
};
1.4 开发模式介绍
开发模式顾名思义就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:
- 编译代码,使浏览器能识别运行
开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源- 代码质量检查,树立代码规范
提前检查代码的一些隐患,让代码运行时能更加健壮。
提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。
1.5 处理样式资源
Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
Webpack 官方 Loader 文档
1.5.1 处理css资源
下载包:
npm i css-loader style-loader -D
下载包:npm i css-loader css-loader -D
此时样式就会以 Style 标签的形式在页面上生效
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
module.exports = {
// 入口
// 相对路径和绝对路径都行
entry: "./src/main.js",
// 输出
output: {
// path: 文件输出目录,必须是绝对路径
// path.resolve()方法返回一个绝对路径
// __dirname 当前文件的文件夹绝对路径
path: path.resolve(__dirname, "dist"),
// filename: 输出文件名
filename: "main2.js",
},
// 加载器
module: {
rules: [
{
test: /\.css$/i,//只检测.css文件
use: [//执行顺序,从右到左,(从上到下)
'style-loader', //将js中css通过创建style标签添加到html文件中生效
'css-loader'//将css资源编译成Commonjs的模块js中
]
}
],
},
// 插件
plugins: [],
// 模式
mode: "development", // 开发模式
};
1.5.2 处理less资源
下载包:
npm i style-loader -D
下载包:npm i css-loader -D
下载包:npm i less-loader -D
{
test: /\.less$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'sass-loader',//将less编译成css文件
],
}
1.5.3 处理sass/scss资源
下载包:
npm i style-loader -D
下载包:npm i css-loader -D
下载包:npm i less-loader -D
{
test: /\.s[ac]ss$/i,
use: [
// 将 JS 字符串生成为 style 节点
'style-loader',
// 将 CSS 转化成 CommonJS 模块
'css-loader',
// 将 Sass 编译成 CSS
'sass-loader',
],
}
1.5.4 处理stylus资源
下载包:
npm i style-loader -D
下载包:npm i css-loader -D
下载包npm i stylus -D
下载包npm i style-loader -D
{
test: /\.styl$/,
use: [
"style-loader",
"css-loader",
"stylus-loader", // 将stylus编译成css文件
]
}
**打包报错如下,不知道为啥,没找到原因**
1.5.5 处理图片资源
过去在 Webpack4 时,我们处理图片资源通过
file-loader
和url-loader
进行处理
现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源
- 使用图片资源
.box2 {
width: 100px;
height: 100px;
background-image: url("../images/1.jpeg");
background-size: cover;
}
- 配置加载器
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
// 小于10kb的图片转base64
// 优点:减少请求数量 缺点:体积会更大
maxSize: 10 * 1024, // 10kb
},
}
}
1.5.6 修改输出文件目录
- 修改入口文件目录
// 输出
output: {
// path: 文件输出目录,必须是绝对路径,(代表所有文件的输出路径)
// path.resolve()方法返回一个绝对路径
// __dirname 当前文件的文件夹绝对路径
path: path.resolve(__dirname, "dist"),
// filename: 输出文件名
//入口文件打包输出文件名
filename: "js/main2.js",
}
- 修改图片输出目录
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
// 小于10kb的图片转base64
// 优点:减少请求数量 缺点:体积会更大
maxSize: 10 * 1024, // 10kb
},
},
generator:{//输出目录
//输出文件名称
//[hash:10] hash值只取前10位
filename: "static/images/[hash:10][ext][query]",
}
}
1.5.7 自动清空上次打包内容
output: {
// path: 文件输出目录,必须是绝对路径,(代表所有文件的输出路径)
// path.resolve()方法返回一个绝对路径
// __dirname 当前文件的文件夹绝对路径
path: path.resolve(__dirname, "dist"),
// filename: 输出文件名
//入口文件打包输出文件名
filename: "js/main2.js",
/**
* 自动清空上次打包的内容: 在打包前,将path整个目录内容清空,在进行打包.
*/
clean:true
}
1.5.8 处理字体图标资源
- 下载字体图标文件
- 打开阿里矢量图库
- 选择想要的图标添加到购物车,统一下载到本地
- 添加字体图标资源
src/fonts/iconfont.ttf
src/fonts/iconfont.woff
src/fonts/iconfont.woff2
src/css/iconfont.css
- 引入资源
// 引入资源,Webpack才会对其打包
import “./css/iconfont.css”;
- 使用图标
<!-- 使用字体图标 -->
<i class="iconfont icon-arrow-down"></i>
<i class="iconfont icon-ashbin"></i>
<i class="iconfont icon-browse"></i>
1.5.9 处理其他资源
和前面一样,统一处理
test: /\.(ttf|woff2?|map4|map3|avi)$/
1.5.10 处理js资源
有人可能会问,js 资源 Webpack 不能已经处理了吗,为什么我们还要处理呢?
原因是 Webpack 对 js 处理是有限的,只能编译 js 中ES 模块化语法
,不能编译其他语法
,导致 js 不能在 IE 等浏览器运行,所以我们希望做一些兼容性处理。
其次开发中,团队对代码格式是有严格要求的,我们不能由肉眼去检测代码格式,需要使用专业的工具来检测。
- 针对 js 兼容性处理,我们使用 Babel 来完成
- 针对代码格式,我们使用 Eslint 来完成
我们先完成Eslint
,检测代码格式无误后,在由Babel
做代码兼容性处理
1.5.10.1 Eslint
可组装的 JavaScript 和 JSX 检查工具。
这句话意思就是:它是用来检测 js 和 jsx 语法的工具,可以配置各项功能
我们使用 Eslint,关键是写 Eslint 配置文件,里面写上各种 rules 规则,将来运行 Eslint 时就会以写的规则对代码进行检查
- 配置文件
.eslintrc.*
–新建文件,位于项目根目录.eslintrc
.eslintrc.js
.eslintrc.json
package.json
中eslintConfig
–不需要创建文件,在原有文件基础上写
ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
- 具体配置
我们以 .eslintrc.js 配置文件为例
module.exports = {
// 解析选项
parserOptions: {},
// 具体检查规则
rules: {},
// 继承其他规则
extends: [],
// ...
// 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
};
- 在 Webpack 中使用
- 安装包:
npm i eslint-webpack-plugin eslint -D
- 定义 Eslint 配置文件
.eslintrc.js
const ESLintPlugin = require('eslint-webpack-plugin'); ... module.exports = { // 继承 Eslint 规则 extends: ["eslint:recommended"], env: { node: true, // 启用node中全局变量 browser: true, // 启用浏览器中全局变量 }, parserOptions: { ecmaVersion: 6, sourceType: "module", }, rules: { "no-var": 2, // 不能使用 var 定义变量 }, };
- 配置
webpack.config.js
:const ESLintWebpackPlugin = require("eslint-webpack-plugin"); .... plugins: [ new ESLintWebpackPlugin({ // 指定检查文件的根目录 context: path.resolve(__dirname, "src"), }), ] ....
- 执行指令
npx webpack
- Eslint 插件,即可不用编译就能看到错误,可以提前解决
但是此时就会对项目所有文件默认进行 Eslint 检查了,我们 dist 目录下的打包后文件就会报错。但是我们只需要检查 src 下面的文件,不需要检查dist
下面的文件。
所以可以使用 Eslint 忽略文件解决。在项目根目录新建下面文件:.eslintignore
# 忽略dist目录下所有文件 dist
1.5.10.2 Babel
- 配置文件
babel.config.*
:新建文件,位于项目根目录babel.config.js
babel.config.json
.babelrc.*
:新建文件,位于项目根目录.babelrc
.babelrc.js
.babelrc.json
package.json
中babel
:不需要创建文件,在原有文件基础上写
Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
- 具体配置
我们以 babel.config.js 配置文件为例
module.exports = {
// 预设
presets: [],
};
# presets 预设
# 简单理解:就是一组 Babel 插件, 扩展 Babel 功能
@babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript。
@babel/preset-react:一个用来编译 React jsx 语法的预设
@babel/preset-typescript:一个用来编译 TypeScript 语法的预设
- 在 Webpack 中使用
- 下载包:
npm i babel-loader @babel/core @babel/preset-env -D
- 定义 Babel 配置文件
babel.config.js
module.exports = { presets: ["@babel/preset-env"], };
- 配置
webpack.config.js
module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', //options: { //与babel.config.js重复,可以单独配置文件 // presets: ['@babel/preset-env'], // }, }, }, ]; }
- 执行指令
npx webpack
备注:也可以将options配置放在单独的文件中
1.5.11 处理html资源
- 下载包
npm i html-webpack-plugin -D
- 配置
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); ... plugins: [ new HtmlWebpackPlugin({ //模板:一public/test.html文件创建新的html(index.html)文件 //新的html文件特点,1.结构和原来一致,2.自动引入打包的main.js template: path.resolve(__dirname,"public/test.html") }) ]
- 执行指令
npx webpack
备注: test.html可以放在其他位置,且名称编译后为index.html,且不需要引入main.js
1.6 开发服务器&自动化
每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化
- 下载包
npm i webpack-dev-server -D
- 配置
webpack.config.js
module.exports={ devServer: { host: "localhost", // 启动服务器域名 port: "3000", // 启动服务器端口号 open: true, // 是否自动打开浏览器 } }
- 运行
npx webpack serve
注意
:注意运行指令发生了变化,并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下
。
开发时我们只关心代码能运行,有效果即可,至于代码被编译成什么样子,我们并不需要知道。
1.7 生产模式介绍
生产模式是开发完成代码后,我们需要得到代码将来部署上线。
这个模式下我们主要对代码进行优化,让其运行性能更好。
优化主要从两个角度出发
:
优化代码运行性能
优化代码打包速度
1.7.1 文件目录
├── 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 (包的依赖管理配置文件)
1.7.2 修改 webpack.dev.js
因为文件目录变了,所以所有
绝对路径
需要回退一层目录才能找到对应的文件,相对路径
不变
output: {
path: undefined, // 开发模式没有输出,不需要指定输出目录
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
// clean: true, // 开发模式没有输出,不需要清空输出结果
}
...
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
]
- 运行开发模式指令
npx webpack serve --config ./config/webpack.dev.js
1.7.3 修改 webpack.prod.js
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
}
...
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: "production",
- 运行生产模式的指令
npx webpack --config ./config/webpack.prod.js
1.7.4 配置运行指令
为了方便运行不同模式的指令,我们将指令定义在 package.json 中 scripts 里面
//无需使用npx,会自动合并命令目录
"scripts": {
"start": "npm run dev",
"dev": "webpack serve --config ./config/webpack.dev.js",
"build":" webpack --config ./config/webpack.prod.js"
}
以后启动指令:
开发模式:npm start
或npm run dev
生产模式:npm run build
1.8 CSS处理
( Css、Less、Sass、Scss、Styl 都会处理)
Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式
这样对于网站来说,会出现闪屏现象(会先处理js文件,较慢)
,用户体验不好
我们应该是单独的 Css 文件,通过 link 标签加载性能才好(经过测试,也会闪屏哎??)
- 安装包
npm i mini-css-extract-plugin -D
- 配置
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); ... 所有"style-loader"都替换为MiniCssExtractPlugin.loader ... plugins: [ new MiniCssExtractPlugin({ filename:'static/css/main.css' }) ]