Webpack
1、Webpack介绍
Webpack 是一个用于现代 JavaScript 应用程序的模块打包工具,它能将项目中的各种资源(JavaScript、CSS、图片等)打包成一个或多个文件,以便在浏览器中高效地加载和运行,Webpack 的核心概念和主要功能包括
核心概念 | 描述 |
---|---|
入口 | ① 指定Webpack打包的起点。通常是项目的主文件,比如 src/main.js ② 可以是单一入口或多个入口 |
输出 | ① 指定Webpack打包后的文件存放位置和文件名 ② 通常配置在 webpack.config.js 文件中 |
加载器 | ① Webpack 自身只能理解 JavaScript 和 JSON 文件。为了处理其他类型的文件(如 CSS、图片等),需要使用加载器 ② 加载器用于转换模块的源代码,例如 css-loader 用于加载 CSS 文件,babel-loader 用于将 ES6+ 代码转换为兼容性更好的 JavaScript 代码 |
插件 | ① 插件用于执行范围更广的任务,比如优化打包文件、注入环境变量、压缩代码等 ② 例如 HtmlWebpackPlugin 可以生成一个自动引用打包文件的 HTML 文件 |
模块 | ① Webpack 中一切皆模块。JavaScript 文件、CSS 文件、图片等都被视为模块 ② 模块是通过加载器和插件进行处理的基本单位 |
依赖图 | ① Webpack 会从入口文件开始,递归地构建一个包含所有项目模块的依赖图 ② 通过这个依赖图,Webpack 能够找出模块之间的依赖关系,从而进行打包 |
主要功能 | 描述 |
---|---|
代码拆分 | ① 通过代码拆分可以将应用程序分割成多个小包,以便按需加载,提升性能 ② 常见的代码拆分方法包括动态导入和多入口文件 |
热模块替换 | ① HMR 允许在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面 ② 这对于开发过程中的调试和快速迭代非常有帮助 |
资源处理 | ① Webpack 可以处理各种静态资源,如图片、字体等,通过适当的加载器可以将这些资源包含到打包文件中 |
树摇 | ① 通过分析代码中的依赖关系,移除那些没有被使用的代码,从而减小打包文件的体积 ② 这主要依赖于 ES6 模块系统的静态结构特性 |
优化和压缩 | ① Webpack 提供了多种优化和压缩选项,如代码压缩、文件合并、缓存优化等,帮助减少打包文件的大小,提高加载速度 |
2、基础篇
2.1、尝试使用
使用npm init -y
初始化文件夹并创建文件结构如下
webpack_code/ # 项目根目录(所有指令必须在这个目录运行)
├── public/ # 存放静态文件
│ └── index.html
├── src/ # 项目源码目录
│ ├── js/ # js文件目录
│ │ ├── count.js
│ │ └── sum.js
│ └── main.js # 项目主文件
└── package.json
// 修改一下package.json
{
"name": "webpack_code", // 这里不能叫做webpack
"version": "1.0.0",
"description": "",
"main": "./src/main.js", // 这里需要修改成我们目录的入口文件
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
}
}
// 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,3))
console.log(sum(2,3,4,5))
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello World!</h1>
<script src="../src/main.js"></script>
</body>
</html>
此时无论是是运行index.html或者是 node main.js 都会出错,因为对于浏览器来说不认识 ES6 模块化语法(import),对于node来说,它只支持 commonJS 的模块化语法(require),因此此时就需要对这些文件进行打包
安装依赖:npm i webpack webpack-cli -D
webpack: 是一个静态模块打包工具
webpack-cli:是 Webpack 的命令行接口工具,提供了在终端中使用 Webpack 的能力
打包命令:npx webpack --mode=development ./src/main.js
,以下是注意点
1、npx是能够将当前目录的node_modules/bin临时添加为环境变量,因此才能够使用webpack命令,当然也可以将webpack进行全局安装然后直接使用,如果之前采用全局安装,则可以使用webpack --mode=development ./src/main.js
进行打包
2、路径中的斜杆必须是/
不能是\
,否则会报错
3、打包后的文件默认是./dist/main.js
如果要自己指定的话,可以加 -o 选项npx webpack --mode=development ./src/main.js -o 输出的路径
–mode的两个模式 | 描述 |
---|---|
development | ① 未压缩的代码:输出的代码不会被压缩和混淆,仅能编译ES6的模块化语法,便于调试和阅读 ② 包含完整的 Source Map:使用 eval-source-map 或其他高质量的 Source Map 选项,帮助开发者在浏览器中调试源代码 ③ 更快的增量编译:针对开发流程进行了优化,编译速度更快,适合频繁修改代码时使用 ④ 启用一些开发辅助工具:例如,启用 Hot Module Replacement (HMR) 热模块替换功能,使得在不刷新整个页面的情况下更新模块 |
production | ① 代码压缩和混淆:使用 TerserPlugin 等工具对代码进行压缩和混淆,以减少文件大小并提升加载速度 ② 移除未使用的代码(Tree Shaking)移除代码中未引用的部分,减小最终打包的文件体积 ③ 优化模块和插件:用一些优化插件,如 DefinePlugin 以便注入环境变量,MiniCssExtractPlugin 用于提取 CSS 到独立文件等 ④ 较少的 Source Map:通常使用 source-map 或 hidden-source-map 生成较小的 Source Map,以便在生产环境中使用而不暴露源码 ⑤ 更严格的编译设置:生产模式下会对代码进行更严格的优化和检查,确保上线代码的质量 |
做完上面的步骤之后,可以看到文件结构如下,我们可以观察dist/main.js中的代码,发现还有一些箭头函数等ES6的语法,因为在开发环境下只能编译 ES6 的模块化语法,其他的 ES6 语法还不能编译;如果使用npx webpack --mode=production ./src/main.js
即生产模式进行打包,打包后的文件点开会发现体积很小
webpack_code/
├── dist/
│ └── main.js # 打包后的文件
├── node_modules/
├── public/
│ └── index.html
├── src
│ ├── js
│ │ ├── count.js
│ │ └── sum.js
│ └── main.js # 项目主文件
└── package.json
现修改一下public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello World!</h1>
<!-- 使用打包后的js文件 -->
<script src="../dist/main.js"></script>
</body>
</html>
2.2、配置文件
在上面的示例中,我们发现在运行webpack命令进行打包的时候,要写很多东西,什么–mode模式啊、-o输出路径啊啥啥的很是麻烦,再加上后续还要给webpack装上一些加载器、插件啥的,如果都写在一行命令里那显然是不合适的,因此我们可以将配置写在一个配置文件 webpack.config.js 中,来简化我们的打包流程
webpack_code/
├── dist/
│ └── main.js
├── node_modules/
├── public/
│ └── index.html
├── src
│ └── main.js
├── webpack.config.js # 创建webpack的配置文件
└── package.json
然后按照webpack的五大核心概念:入口、输出、加载器、插件、模式配置成一个对象并进行暴露,由于配置文件最终要使用 NodeJS 来运行,因此暴露的语法要是 NodeJS 能够识别的语法,即CommonJS的暴露语法(require),而不能是 ES6 的暴露语法(import)
// webpack.config.js
const path = require("path");
module.exports = {
//入口
entry: path.join(__dirname, "src/main.js"),
//输出
output: {
path: path.join(__dirname, "dist"), // 输出到的目录
filename: "main.js", // 输出到path目录下的文件
clean: true,// 每次打包的时候会先删掉dist目录下的各文件(之前打包生成的)
},
//加载器
module: {
rules: [
//loader的配置
],
},
//插件
plugins: [
//插件的配置
],
//模式
mode: "development",
};
然后现在要进行打包的时候,就只需执行npx webpack
(针对局部安装)/ webpack
(针对全局安装,下面用这种)即可了,其原理是当我们在执行打包命令的时候,会先在执行命令的目录下寻找有没有webpack.config.js文件,有的话就按照里面的配置来进行打包
在 2.1 的示例中,我们还有配置 webpack.config.js 文件,并且在执行打包命令的时候我们还没有声明一些选项例如输出路径 -o,而webpack还是会给我们为该选项提供默认的配置,也就是dist/main.js,相当于有一个隐形的 webpack.config.js 文件如下
const path = require("path");
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, "dist"),
filename: "main.js",
},
mode: 'production'
};
2.3、处理样式资源
Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源,我们找 Loader 都应该去 官方文档 中找到对应的 Loader,然后使用,官方文档找不到的话,可以从社区 Github 中搜索查询
2.3.1 处理 css 资源
① 首先是要安装处理 css 资源的loader
安装:npm i css-loader style-loader -D
② 在main.js中可以引入css文件
// src/main.js
// 引入js
import count from './js/count'
import sum from './js/sum'
// 引入css
import './css/index.css'
// 业务
console.log(count(2,3))
console.log(sum(2,3,4,5))
③ 修改webpack配置文件
//加载器
module: {
rules: [
{
test: /\.css$/i, // 当检测到以.css结尾的文件时(也就是css文件)使用下面的loader
use: [ // 执行顺序是从后往前,即先执行css-loader、再执行style-loader
"style-loader", //将js中css的代码通过创建style标签的形式添加到html文件中进行生效
"css-loader", // 将css资源编译成commonjs的模块放入到js中
],
},
],
}
④ 运行webpack
进行打包,可以发现打包成功了,css代码打包后也在dist/main.js中,当我们在public/index.html中导入这个js文件之后,就可以使用到我们写的样式了;如果没有配置处理 css 的loader,那么在打包过程中遇到了 import ‘./css/index.css’ 这一行代码是会报错导致打包失败的
2.3.2 处理 less 资源
安装:npm i less-loader -D
// rules中添加配置
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
Tip:less-loader用于将less先转换为css代码,下同
2.3.3 处理 Sass/Scss 资源
安装:npm i sass-loader sass -D
// rules中添加配置
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],