主题
webpack(一)
本页对应 webpack,共 7 段视频,约 1 小时 32 分。
学习目标
- 能说明 Webpack 作为静态模块打包工具的作用,独立完成项目初始化、安装
webpack与webpack-cli、配置npm scripts,并通过npm run build验证dist产物生成。 - 能创建
webpack.config.js,使用 CommonJS 导出配置对象,正确设置entry、output.path、output.filename和clean,并通过重新打包验证入口、出口及清理旧产物生效。 - 能基于注册用户案例,在入口文件中引入用户名和密码长度校验模块,获取页面输入值并完成校验提示与
return中断流程,打包后结合 HTML 运行并验证校验结果。 - 能安装并配置
HtmlWebpackPlugin,指定public/index.html作为模板,打包验证dist中自动生成 HTML 并自动注入打包后的 JS 资源。 - 能安装并配置
css-loader与style-loader,在入口引入 CSS 文件,使用module.rules匹配.css文件并按正确 loader 顺序打包,验证样式被插入页面style标签。 - 能配置
less-loader与less处理.less文件,并使用 Webpack 5 资源模块配置图片打包,验证小于 8KB 图片转为 Base64、大于 8KB 图片输出到指定目录且页面可正常引用。
知识点
自测题1:ECMAScript 默认导出与导入
为什么需要:模块化开发要把工具函数拆成独立文件,避免变量污染全局。转写稿里封装 check.js 时,先用了命名导出 export,又补充 export default,目的就是让模块既支持按名导入,也支持默认导入。这里要先区分两套规范:CommonJS 的 module.exports / require,以及 ECMAScript 模块的 export default / import 变量名。
怎么想:题目问“ECMAScript 默认导出和导入的语法”,关键词是“默认”。默认导出写 export default,默认导入写 import 变量名 from '模块路径',变量名可自定义;命名导出则是 export { 同名变量 },导入要写 import { 同名变量 }。转写稿还提到 webpack 配置文件用 module.exports,是因为它由 Node.js 解析,Node 默认支持 CommonJS;而 src 源码由 webpack 读取转译,所以可用 import/export。
怎么做:选 C。A 把 export 和 require 混在一起;B 是 CommonJS 写法;D 是命名导出/导入,不是默认。正确语法可记为:
js
export default 变量名
import 变量名 from './模块'易错点:默认导入的变量名不必与导出名一致;命名导入必须加大括号且名字对应;不要把 export default 与 module.exports = {} 混用。
自测题2:Less 嵌套选择器
为什么需要:写样式时经常要限定“某个父级范围内的子元素”,Less 嵌套能让层级关系更清晰,减少重复写父选择器。转写稿视频6中写 .login-wrap { span { color: red; } },就是给登录区域内的 span 设红色。
怎么想:.title { span { color: red; } } 编译后是 .title span,含义是“查找 class 为 title 的元素范围内,所有 span 标签”,而不是 .title 和 span 两个并列选择器。
怎么做:选 A。保留原代码:
js
.title {
span {
color: red;
}
}这段 Less 的父子嵌套表达的是后代选择关系。
易错点:嵌套不等于并列;如果要给当前元素加伪类或拼接选择器,要注意 & 的用法;调试时看编译后的 CSS 选择器最可靠。
自测题3:map 的返回值
为什么需要:遍历数组并“按规则生成一个新数组”时,map 比手写循环更直观。转写稿本节没有覆盖 map 的调试过程,因此这里只按笔记答案核对,不编造运行记录。
怎么想:map 会对原数组每一项执行回调,并把每次返回值收集成新数组。[1,2,3,4] 每项乘 2,得到 [2,4,6,8]。
怎么做:选 B。保留原代码:
js
const arr = [1, 2, 3, 4].map(val => val * 2)
console.log(arr)输出 [2, 4, 6, 8]。
易错点:map 不会改变原数组;回调里忘记 return 会得到 undefined;不要把它和 forEach 混淆,forEach 默认不返回新数组。
自测题4:axios 配置项
为什么需要:发请求时要明确“请求哪个网址、用什么方法、参数放在查询串还是请求体”。转写稿本节没有覆盖 axios 的调试过程,因此按笔记答案核对配置项含义。
怎么想:url 是请求网址,method 是请求方法;params 通常拼到 URL 查询参数中,data 通常放请求体参数。题目中 A 把 url 说成方法、method 说成参数,错误;B 和 D 把 data 与 params 的含义说反或说错。
怎么做:选 C。保留原代码:
js
axios({
// 这里
})配置时应写 url: '请求网址'、method: 'get' 等;查询参数用 params,请求体用 data。
易错点:GET 请求常用 params,POST/PUT 常用 data;不要把 params 当成请求体;method 要写请求方法名,不是参数名。
Webpack 的定位与打包流程
为什么需要:项目里不只有 JS,还有 HTML、CSS、Less、图片等静态模块。浏览器不能直接理解所有写法,需要工具做压缩、翻译、整合。怎么想:Webpack 是静态模块打包工具,从入口文件开始逐行分析依赖,构建依赖关系图,再把与入口有直接或间接引入关系的模块打包输出。怎么做:先写源码,再准备 Webpack 环境,最后执行打包并观察 dist 产物。易错点:没有被入口直接或间接引入的文件不会被打包;不要把它和 Vite 混为一谈,当前项目仍大量基于 Webpack。
初始化项目、入口出口与自定义命令
为什么需要:前端项目要记录依赖、运行本地命令,还要指定从哪个文件开始打包、产物放哪里。怎么想:用 package.json 管理项目;Webpack 配置写在根目录 webpack.config.js,由 Node 解析,所以用 CommonJS;src 源码可写 ESM。怎么做:
bash
npm init -y
npm i webpack webpack-cli --save-devjson
{ "scripts": { "build": "webpack" } }js
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, 'src/main.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
clean: true
}
};执行 npm run build,会运行 scripts 里的 webpack。易错点:路径优先用 path.resolve 拼绝对路径;clean: true 会先清空 dist 再输出;--save-dev 表示打包工具只在开发环境使用。
插件与 loader:自动生成 HTML、处理 CSS/Less/图片
为什么需要:手写复制 HTML、手动引入打包后的 JS 很麻烦;Webpack 默认也只识别 JS/JSON。怎么想:插件扩展 Webpack 功能,loader 让 Webpack 识别更多文件类型。怎么做:用 HtmlWebpackPlugin 以 public/index.html 为模板生成 HTML 并自动引入资源;CSS 用 style-loader、css-loader;Less 再加 less-loader、less;图片用 Webpack 5 内置 asset 模块。核心配置:
js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'public/index.html') })],
module: { rules: [
{ test: /\.css$/i, use: ['style-loader', 'css-loader'] },
{ test: /\.less$/i, use: ['style-loader', 'css-loader', 'less-loader'] },
{ test: /\.(png|jpe?g|gif)$/i, type: 'asset',
generator: { filename: 'assets/[hash][ext][query]' } }
]}
};易错点:loader 从后往前执行;CSS 要先被 css-loader 解析,再由 style-loader 插入 DOM;图片在 JS 中要 import 成模块,不能直接把本地路径字符串赋给 src;asset 默认以 8KB 为界,小于转 base64,大于输出文件;[hash] 可避免同名文件覆盖。
案例:注册用户页面与长度校验
为什么需要:把前面的工具函数、页面事件和打包流程串起来。怎么想:业务代码写在 src,页面模板放 public;入口中引入校验模块,点击注册按钮时取输入值,不合格就 alert 并 return。怎么做:
js
// src/utils/check.js
export const checkUserName = name => name.length >= 8;
export const checkPassword = pwd => pwd.length >= 6;
// src/main.js
import { checkUserName, checkPassword } from './utils/check.js';
document.querySelector('.register').addEventListener('click', () => {
const name = document.querySelector('.username').value;
const pwd = document.querySelector('.password').value;
if (!checkUserName(name)) { alert('用户名长度要大于等于8位'); return; }
if (!checkPassword(pwd)) { alert('密码长度要大于等于6位'); return; }
console.log('用户名和密码长度符合要求');
});执行 npm run build 后运行 dist 中的页面,用 F12 验证提示与 return 是否阻止后续逻辑。易错点:校验失败后忘记 return 会继续执行;类名要按实际页面替换;打包后要运行 dist 产物。
开发服务器、打包模式、source map 与 @ 路径
为什么需要:反复手动打包、打开文件效率低;出错时要定位源码;深层相对路径难维护。怎么想:目录中列出这些能力,转写稿未展开细节,这里只说明配置落点,不虚构调试过程。怎么做:mode 区分开发/生产;devtool: 'source-map' 生成映射便于调试;devServer 配合 webpack-dev-server 提供开发服务;resolve.alias 配置 @ 指向 src。易错点:source map 主要用于开发调试;改别名后要重启构建;@ 只是路径别名,不是真实文件夹名。
Webpack 的作用:把静态模块整理成浏览器可用的产物
为什么需要:项目里不只有 JS,还有 HTML、CSS、Less、图片等静态资源。如果全部手动压缩、复制、引入,既繁琐又容易漏。Webpack 的核心价值是:从入口文件开始,逐行分析 import/require 等依赖关系,构建依赖图,再把与入口有直接或间接引入关系的模块进行压缩、转译、整合,输出到指定目录。转写稿里“HMLCSSGS图片”应纠正为 HTML、CSS、JS、图片等资源。
怎么想:先明确“入口”和“出口”。Webpack 默认会找 src/index.js 作为入口,打包后默认输出 dist/main.js。只有和入口产生引入关系的模块才会被打包。
怎么做:初始化项目并安装到开发环境:
bash
npm init -y
npm i webpack webpack-cli --save-dev在 package.json 中配置自定义命令:
json
{
"scripts": {
"build": "webpack"
}
}运行:
bash
npm run build易错点:webpack 和 webpack-cli 是项目内开发依赖,不是全局包;命令要通过 npm run build 运行;打包后要观察 dist 产物,而不是直接改产物文件。
npm 下载的软件包如何作用在前端项目
为什么需要:npm 包下载到项目后,需要被项目代码或命令行工具使用。像 webpack 这类包主要提供打包能力和命令,不需要在业务代码里 import。
怎么想:先看包的类型:业务依赖放 dependencies,开发工具放 devDependencies。Webpack 只在开发阶段完成打包,产物上线后浏览器运行的是打包结果,所以用 --save-dev。
怎么做:安装后,npm 会把包放入 node_modules,可执行命令通常链接到 node_modules/.bin。package.json 的 scripts 让 npm 帮你找到本地命令,因此写 "build": "webpack" 后执行 npm run build 即可。
易错点:不要以为下载了包就会自动生效;工具包要配置命令;业务代码要按模块语法引入;--save-dev 与 --save 不要混用。
开发环境和生产环境的特点与区别
为什么需要:开发环境关注“写得快、调得方便”,生产环境关注“体积小、加载快、可部署”。
怎么想:转写稿中强调,Webpack 的压缩、整合、转译主要发生在开发者本机,也就是开发环境;打包产物才部署到线上给用户看。上线后一般不再需要 Webpack 参与运行。
怎么做:开发阶段安装 webpack、webpack-cli、各类 loader/plugin 到 devDependencies;生产环境部署 dist 中的 HTML、CSS、JS、图片等产物。配置上可区分开发配置和生产配置,但本节先掌握“工具包放开发环境、产物用于生产”的基本判断。
易错点:把打包工具当成浏览器运行时依赖;把 dist 产物和 src 源码混在一起;忘记生产环境应使用打包后的资源。
Webpack 配置入口、出口与调试过程
为什么需要:默认入口和出口不一定符合项目结构,需要通过配置文件影响打包过程。
怎么想:在项目根目录新建 webpack.config.js,用 CommonJS 导出配置对象。源码在 src 中可使用 ES Module 语法,因为会被 Webpack 读取和转译;而 Webpack 配置文件由 Node.js 解析,所以用 module.exports。
怎么做:
js
const path = require('path')
module.exports = {
entry: path.resolve(__dirname, 'src/main.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
clean: true
}
}调试时先运行 npm run build,观察 dist 是否生成 app.js;加上 clean: true 后会先清空 dist 再输出最新内容。转写稿中的“entry 入口、output 出口、path 路径、filename 文件名”要按配置项理解,不要写成拼错的属性名。
易错点:路径优先用绝对路径;output.path 是目录,filename 是文件名;修改配置后要重新打包观察。
Webpack 配置解析别名
为什么需要:项目层级变深后,大量 ../../utils/check.js 这类相对路径难读、易错。别名能把常用目录映射成简短前缀,提升可维护性。
怎么想:别名属于“模块解析”配置,应放在 resolve.alias 中;本质是告诉 Webpack:遇到某个前缀时,去哪个真实目录找文件。转写稿没有展开别名演示,这里按 Webpack 配置对象说明通用做法,具体路径按项目实际目录设置。
怎么做:
js
const path = require('path')
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}配置后,原本的 import { checkUserName } from './utils/check.js' 可按项目约定写成以 @ 开头的路径。修改后重新执行 npm run build,若解析失败,先检查别名键名、真实目录和文件扩展名。
易错点:别名不是自动生成,必须和真实目录一致;不要只写相对字符串而不用 path.resolve;别名配置放在 resolve.alias,不要误放到 entry 或 output;配置改完必须重新打包验证。
一、Webpack 是什么:从入口构建依赖图
为什么需要:项目里的 JS、CSS、图片等文件越来越多,浏览器直接加载时,模块之间的引入关系容易散乱,代码也没有经过压缩、整合和转译。Webpack 就是为了把这些静态资源按依赖关系整理成可运行的产物。
怎么想:把 Webpack 想成一个“找入口 → 分析引入 → 建依赖图 → 输出打包结果”的工具。它会从入口文件开始,逐行分析代码里引入了哪些模块,再把这些有关模块打包起来。
怎么做:记住一句话:Webpack 是一个静态模块打包工具,从入口构建依赖图,打包有关的模块,最后用于展示你的内容。

易错点:不是项目里所有文件都会被打包。只有和入口有直接或间接引入关系的模块,才会进入依赖图并被处理。
二、静态模块与打包边界
为什么需要:理解“静态模块”才能判断哪些文件该交给 Webpack 处理。笔记里的静态模块指编写代码过程中的 html、css、js、图片等固定内容的文件。
怎么想:判断一个文件会不会被打包,不看它是否放在项目里,而看它有没有从入口一路引入过来。
怎么做:写代码时让入口 src/index.js 通过 import 引入工具模块;Webpack 会顺着引入关系找到 src/utils/check.js。

易错点:文件写了但没被入口直接/间接引入,通常不会成为本次打包内容。不要把“项目目录里存在”误认为“一定会打包”。
三、Webpack 的作用:压缩、整合、转译
为什么需要:前端工程化不仅要合并文件,还要处理 less/sass、ES6+ 语法和多种模块标准。转写稿里说的“压缩、这个和、转译”,应纠正为“压缩、整合、转译”。
怎么想:Webpack 的价值是把静态模块内容进行压缩、整合、转译等处理。笔记列出:把 less/sass 转成 css;把 ES6+ 降级成 ES5 等;支持多种模块文件类型和多种模块标准语法。
怎么做:本节先体验最基础的 JS 模块打包,后面再逐步加入 CSS、less、图片等处理能力。
易错点:不要把“打包”只理解成压缩。压缩只是结果之一;依赖分析、模块整合、转译都属于工程化处理。至于为何不先学 Vite:笔记明确说现在很多项目还是基于 Webpack 构建,所以仍要掌握 Webpack 的使用。
四、动手体验:封装校验函数并打包
为什么需要:只背概念不够,要用两个 JS 文件体验“入口引入工具模块,再由 Webpack 打包”的完整流程。
怎么想:先初始化包环境,再写 src 源码,最后安装 Webpack。需求是封装 utils 包,校验用户名和密码长度,在 index.js 中使用并打包。
怎么做:
- 新建项目文件夹
Webpack_study,初始化包环境:
bash
npm init -y- 新建
src/utils/check.js:
js
/**
* 目标:封装检验用户名和密码长度的函数
*/
export const checkUserName = uname => {
return uname.length >= 8
}
export const checkPassWord = pwd => {
return pwd.length >= 6
}
export default {
checkUserName,
checkPassWord
}新建 src/index.js:
js
/**
* 目标:引入工具函数使用
*/
import { checkUserName, checkPassWord } from './utils/check.js'
const unameResult = checkUserName('itheima007')
const pwdResult = checkPassWord('7654321')
console.log(unameResult, pwdResult)- 下载 webpack、webpack-cli 到项目开发依赖:
bash
npm i webpack webpack-cli --save-dev
易错点:虽然 webpack 提供命令工具,但为了保证项目之间版本独立,笔记要求下载到某个项目环境下,并通过 package.json 的 scripts 配成局部命令使用,而不是依赖全局命令。
五、运行自定义命令与观察 dist
为什么需要:局部安装后,命令要通过 npm scripts 运行,避免直接敲全局 webpack 导致版本或项目不匹配。
怎么想:npm run build 运行的是 scripts 里 build 右侧的具体命令。转写稿强调:终端里真正执行的是右侧的 webpack。
怎么做:在 package.json 的 scripts 中配置自定义命令后运行:
bash
npm run buildWebpack 会自动产生 dist 分发文件夹,里面是压缩和优化后、用于最终运行的代码。本节默认出口是 dist/main.js。

易错点:npm run 后面写的是自定义命令名,例如 build,不是直接写 webpack;不要手动改 dist 里的产物当源码,源码仍在 src。
六、默认入口出口与本节小结
为什么需要:知道默认约定,才能理解为什么没写配置也能打包,以及出错时先检查入口文件是否存在。
怎么想:Webpack 默认入口是 src/index.js,默认出口是 dist/main.js。本节体验使用默认值;修改入口出口需要额外配置文件,属于后续内容。
怎么做:按“初始化环境 → 编写代码 → 安装 Webpack 软件包 → 配置自定义命令 → 打包体验查看结果”完成。小结四问:Webpack 能压缩、转译、整合、打包静态模块;使用流程是初始化、写代码、安装、配置命令、打包;运行自定义命令用 npm run 自定义命令;默认入口和出口分别是 src/index.js 和 dist/main.js。
易错点:入口文件路径或引入路径写错会导致打包失败;dist 是分发产物目录,不是源代码目录。
本节要解决什么问题
前面我们用默认方式运行 Webpack,它会按默认约定找入口、往默认目录输出。现在要改成项目自己的入口和出口:入口指向 src/main.js,出口输出到 dist/app.js。这节的核心不是背配置,而是学会查文档、写配置文件、重新打包并观察结果。

知识点一:为什么需要 Webpack 配置文件
为什么需要: 只会在命令行里运行 webpack,打包过程就受默认约定控制;项目文件结构一变,默认入口和出口就不合适。
怎么想: 转写稿里先查 Webpack 中文文档的“概念”页,看到 entry、output 等配置项。文档说明:要影响打包过程,需要项目根目录下的 webpack.config.js 配置文件。
怎么做: 在项目根目录新建 webpack.config.js,用 module.exports 导出一个配置对象。
易错点: 配置文件名不要写错;它要放在项目根目录,和 package.json、src 等并列。配置文件由 Node.js 解析,所以这里用 CommonJS 的 module.exports,不要误以为必须和 src 里的 ES Module 写法完全一样。
知识点二:配置入口 entry
为什么需要: Webpack 要从某个入口文件开始逐行分析依赖,入口不对,打包内容就会错。
怎么想: 文档示例里用 entry 指定入口。转写稿中把入口从默认的 src/index.js 改成 src/main.js,因此对应源文件也要存在。
怎么做: 用 path.resolve(__dirname, 'src/main.js') 拼出绝对路径。__dirname 是当前配置文件所在文件夹的绝对路径。
易错点: 在 Node 环境里读文件路径,用绝对路径更稳妥;不要只写一个看似相对、实际受运行目录影响的字符串。改了入口文件名,就要检查 src/main.js 是否真的存在。
知识点三:配置出口 output
为什么需要: 默认输出是 dist/main.js,但项目可能希望输出成 dist/app.js,并控制输出目录。
怎么想: 文档里 output 是对象,常用 path 指定输出目录,filename 指定输出文件名。转写稿中把输出文件改为 app.js。
怎么做: 在配置对象里写 output.path 和 output.filename。注意 filename 是文件名,不是完整路径。
易错点: output.path 要用绝对路径;filename 不要误写成 path.resolve(...) 的完整路径。打包后要到 dist 下确认是否出现 app.js。
本节笔记里的核心配置如下:
js
const path = require('path')
module.exports = {
entry: path.resolve(__dirname, 'src/main.js'), // 入口
output: { // 出口
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
clean: true // 先清空 dist,然后再输出最新内容
}
}知识点四:clean 清空旧产物
为什么需要: 重新打包后,dist 里可能还残留上一次的旧文件。转写稿中先看到新的 app.js 生成,但旧内容还在,于是继续查配置。
怎么想: 在 output 配置对象中加入 clean: true,让 Webpack 先清空输出目录,再写入最新内容。
怎么做: 加上 clean: true 后重新运行打包命令,观察 dist 是否先被清空、再生成最新文件。
易错点: clean 放在 output 里,不要放到 entry 里;开启清空后要确认输出目录就是你想清理的 dist,避免误清其他目录。
知识点五:重新打包与调试观察
为什么需要: 配置写完不等于生效,必须通过重新打包验证入口、出口是否按预期工作。
怎么想: 转写稿中的调试过程是:保存配置 → 运行 npm run build(实际执行 webpack)→ 查看终端是否报错 → 打开 dist 看输出文件名 → 再验证 clean 效果。
怎么做: 重新打包,确认 dist/app.js 出现;再修改一次源文件或输出名,观察产物是否更新。
易错点: 如果仍输出旧名字,先检查配置文件是否在根目录、是否被正确读取;如果路径报错,优先检查 entry 和 output.path 的绝对路径拼接。
小结与自测
如何影响 Webpack 打包过程?答案是:查文档,新建配置文件,配置对应属性,然后重新打包观察。本节要掌握的是 webpack.config.js、entry、output.path、output.filename 和 clean: true 的基本用法。
目标与需求
这一节的目标不是重新讲 Webpack 的全部原理,而是通过一个很小的注册用户案例,体验“前端项目代码如何被 Webpack 打包,再被浏览器使用”。
为什么需要:前面已经写过工具函数和入口文件,但代码直接放在 src 里并不能自动变成浏览器可运行的项目产物。需要经过打包,才能观察 Webpack 如何处理入口、依赖和输出文件。
怎么想:需求是点击注册按钮,判断用户名和密码长度是否符合要求。用户名长度要大于等于 8 位,密码长度要求大于等于 6 位;不符合就 alert 提示,并用 return 阻止继续执行。
怎么做:准备网页模板,把核心 JS 写在 src/main.js,运行自定义打包命令,再把 HTML 和打包后的 JS 接起来运行。
易错点:不要直接在 src 或 public 里打开页面就以为看到了打包效果;最终要运行的是 dist 中接入打包产物后的页面。
准备网页模板
为什么需要:案例需要按钮和输入框,Webpack 只负责处理 JS 等模块,页面结构仍要先准备好。把模板放在 public/index.html,也方便查找标签,并为后期自动生成 HTML 文件做准备。
怎么想:先有页面标签,再让 src/main.js 通过类名获取按钮和输入框。模板中的类名必须和 JS 选择器一致。
怎么做:新建 public/index.html,准备用户名输入框、密码输入框和注册按钮。笔记中的模板位置如下:

易错点:public、src 要和项目根目录并列,不要放错层级;选择器类名如 .login-btn、.username、.password 要与 HTML 对应。
编写入口 JS
为什么需要:Webpack 需要一个入口文件来分析依赖并打包。本节把案例核心逻辑写在 src/main.js 中。
怎么想:点击按钮后先取值,再调用已经封装好的长度校验函数。若校验不通过,就提示并提前返回;只有都通过,才继续后面的注册逻辑。
怎么做:在入口中绑定点击事件并判断长度。笔记代码如下:
js
/**
* 目标:点击注册,检验用户名和密码长度
*/
document.querySelector('.login-btn').addEventListener('click', () => {
const username = document.querySelector('.username').value
const password = document.querySelector('.password').value
if (!checkUserName(username)) {
alert('用户名长度要大于等于8位')
return
} else if (!checkPassWord(password)) {
alert('密码长度要求大于等于6位')
return
}
console.log('用户名和密码长度符合要求')
})这里的前提是入口文件已经导入前面封装的 checkUserName、checkPassWord 函数;否则运行时会找不到函数。
易错点:校验函数不符合要求时返回 false,所以前面要取反;alert 后必须 return,否则代码还会继续往下执行。
打包与手动接入
为什么需要:写完 src/main.js 后,浏览器不能直接使用 Webpack 的模块写法,需要先打包输出。
怎么想:Webpack 会从入口 src/main.js 开始分析依赖,把相关代码压缩、整合、转译,输出到 dist。本节先体验手动接入:复制 HTML 到 dist,再手动引入打包后的 JS。
怎么做:运行项目中配置好的自定义命令,例如 npm run build,让 Webpack 打包 JS。然后手动复制 public/index.html 到 dist 下,并在 HTML 中手动引入打包后的 JS 文件,最后运行 dist/index.html 查看效果。

易错点:打包命令要运行在项目根目录;不要手动改 dist 里的打包 JS;HTML 中引入的必须是打包后的 JS 文件,而不是 src/main.js。
调试与验证
为什么需要:长度判断涉及“取值—校验—提示—阻止继续执行”多个环节,必须实际点击验证。
怎么想:分别构造三种情况:用户名不合法、密码不合法、都合法。观察 alert 是否出现,以及控制台是否打印最终结果。
怎么做:用 VS Code 的 Live Server 打开 dist/index.html,按 F12 打开控制台。先不输入用户名直接点击注册,应提示用户名长度;再输入合法用户名但不输入密码,应提示密码长度;都输入合法后再点击,控制台应输出“用户名和密码长度符合要求”。
易错点:若点击没反应,先检查按钮类名、脚本引入路径和打包是否成功;若提示后仍继续执行,检查是否漏写 return。
小结
本节的核心流程是:准备 public/index.html 模板 → 在 src/main.js 写点击校验逻辑 → 用 Webpack 打包 → 手动复制 HTML 到 dist 并引入打包后的 JS → 浏览器运行 dist/index.html。Webpack 打包后的前端代码,需要被引入到 HTML 文件中,再交给浏览器运行。
课件图示








代码示例
示例 1:webpack.config.js(入口 / 出口 / 插件 / loader)
js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 入口:从哪个文件开始构建依赖图
entry: path.resolve(__dirname, 'src/main.js'),
// 出口:打包产物输出到哪里
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
clean: true // 先清空 dist,再输出最新内容
},
// 插件列表
plugins: [
new HtmlWebpackPlugin({
// 以指定 html 文件为模板,自动生成 dist/index.html 并引入打包后的 js
template: path.resolve(__dirname, 'public/index.html')
})
],
// 加载器规则:让 webpack 认识更多类型的文件
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
},
{
test: /\.(png|jpe?g|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
]
}
}要点与易错点
webpack.config.js由 Node 环境解析,所以必须用 CommonJS(require/module.exports);而src里的源码是被 webpack 读取转译的,可以写 ESM(import/export)。- 入口、出口路径都要用绝对路径:
path.resolve(__dirname, ...),__dirname是当前配置文件所在文件夹。 - 默认入口是
src/index.js、默认出口是dist/main.js;不配置也能打包,但产物名改不了。 output.clean: true必须先清空再输出,否则旧的 dist 内容会残留。- 插件(plugins)是给 webpack 扩展功能,加载器(loader)是让 webpack 识别更多文件类型,二者别混用。
use数组的执行顺序是从后往前:less 文件先用less-loader编译成 CSS,再css-loader解析成 JS 对象,最后style-loader插入到 DOM 的<style>标签中,顺序写反会报错。- 需要安装的包:
npm i webpack webpack-cli --save-dev、npm i html-webpack-plugin css-loader style-loader less-loader less --save-dev,然后在package.json的scripts里配置"build": "webpack",运行npm run build。
示例 2:src/utils/check.js + src/main.js(注册用户长度校验)
js
/**
* src/utils/check.js
* 目标:封装检验用户名和密码长度的函数
*/
export const checkUserName = uname => {
return uname.length >= 8
}
export const checkPassWord = pwd => {
return pwd.length >= 6
}
export default {
checkUserName,
checkPassWord
}js
/**
* src/main.js
* 目标:点击注册,检验用户名和密码长度
*/
import { checkUserName, checkPassWord } from './utils/check.js'
import './css/index.css'
import './less/index.less'
import logoImg from './assets/logo.png'
// 本地图片要当作模块引入,再把数据对象赋给 src
document.querySelector('.logo').src = logoImg
document.querySelector('.login-btn').addEventListener('click', () => {
const username = document.querySelector('.username').value
const password = document.querySelector('.password').value
if (!checkUserName(username)) {
alert('用户名长度要大于等于8位')
return
} else if (!checkPassWord(password)) {
alert('密码长度要求大于等于6位')
return
}
console.log('用户名和密码长度符合要求')
})要点与易错点
check.js同时用了命名导出(export const)和默认导出(export default {}),导入时命名导出要用大括号且变量名一致:import { checkUserName } from './utils/check.js'。- 只有和入口有直接 / 间接引入关系的模块才会被打包:
index.css、index.less必须在这里import一次,否则样式不会被处理。 - 只想要副作用(让 webpack 打包进来)时,直接
import './css/index.css'即可,不用变量接收。 - 本地图片不能直接写路径字符串给
src,那样 webpack 只当普通字符串原样输出;必须import得到图片数据对象再赋值。网络图片(http 开头)才可以直接写字符串。 alert之后必须return提前结束函数,否则用户名密码不合格还会继续往下执行。- 项目代码写在
src下,最终交给 webpack 压缩、转译、整合后输出到dist,再在浏览器运行。
示例 3:public/index.html(打包模板)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>注册用户</title>
</head>
<body>
<img class="logo" src="" alt="logo" />
<form class="login-wrap">
<div>用户名:<input class="username" type="text" /></div>
<div>密码:<input class="password" type="password" /></div>
<button class="login-btn" type="button">注册</button>
</form>
</body>
</html>要点与易错点
- 这个文件放在
public下,只作为模板使用;HtmlWebpackPlugin会以它为基准生成dist/index.html,并自动在 body 底部用<script>引入打包后的app.js,不用再手动复制 html、手动写 script。 - 类名必须和
main.js里querySelector的选择器完全一致(.username、.password、.login-btn、.logo),否则拿到null会报错。 - 按钮要写
type="button",否则在 form 中默认是submit,点击会触发页面刷新。 - 最终一定要运行打包后的产物(
dist下的 html),而不是直接打开public里的模板,否则看不到打包后的效果。
常见错误
现象:执行
npm run build报webpack: not found或命令不存在。
原因:未在项目内安装webpack、webpack-cli,或package.json的scripts未配置build。
修法:项目内安装到开发依赖,并在scripts中配置"build": "webpack",统一用npm run build执行。现象:修改入口/出口后仍打包旧文件,或报找不到入口模块。
原因:entry路径与实际文件名不一致,或输出路径写成相对路径导致位置不确定。
修法:用path.resolve(__dirname, ...)配entry和output.path,改入口时同步检查源文件名。现象:打包成功但页面按钮无反应,控制台提示找不到脚本或模块。
原因:直接运行public/index.html,没有引入dist下打包后的 JS;或未通过打包产物验证。
修法:验证时运行dist内页面并正确引入打包后的 JS;更推荐用HtmlWebpackPlugin自动生成并注入。现象:CSS/LESS 样式不生效,或报
Unexpected token/ 无法解析样式文件。
原因:未安装或未配置对应 loader;样式文件未在入口形成依赖;use数组顺序写反。
修法:安装css-loader、style-loader(LESS 再加less-loader、less),在入口import样式,按“从后往前”规则配置 loader。现象:图片打包后 404,或 JS 中设置的图片地址没有输出到
dist。
原因:在 JS 里直接把本地图片路径当字符串赋给src,Webpack 不会追踪该依赖。
修法:本地图片先import成模块再赋给src;网络图片可直接用 URL;同时检查资源模块rules是否匹配图片扩展名。现象:
HtmlWebpackPlugin报找不到模板,或生成的 HTML 没有预期结构。
原因:template使用相对路径,受执行目录影响。
修法:template用path.resolve(__dirname, 'public/index.html')这类绝对路径。现象:
clean: true后误删内容,或输出目录不符合预期。
原因:output.path配错,clean清空的是该path指向的目录。
修法:确认output.path只指向dist等构建输出目录,不要指向项目根目录或源码目录。
练习
将入口改为
src/main.js,出口改为dist/app.js,并要求每次打包前清空dist。写出webpack.config.js的关键配置。
参考要点:entry、output.path、output.filename、output.clean。注册页面点击按钮无反应。请给出排查顺序:从源码依赖、打包命令、HTML 引入、浏览器控制台四方面列出检查项。
参考要点:入口是否引入并绑定事件、是否重新打包、页面是否运行dist产物、控制台是否有 404/语法错误。新增
src/less/index.less,要求其中样式最终生效。列出需要安装的包、入口文件要做什么、module.rules要匹配什么及 loader 顺序。
参考要点:less、less-loader、css-loader、style-loader;入口import;匹配.less;顺序从后往前。项目中
logo.png小于 8KB,bg.png大于 8KB。说明 Webpack 5 资源模块处理结果差异,并写出 JS 中正确使用logo.png的方式。
参考要点:小图转 Base64 进 JS,大图输出为文件;本地图片import后赋给src。使用
HtmlWebpackPlugin以public/index.html为模板自动生成dist/index.html。写出安装命令、配置文件引入方式、plugins配置要点。
参考要点:安装到开发依赖;require插件;plugins: [new HtmlWebpackPlugin({ template: ... })];模板用绝对路径。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | Webpack简介及体验 | 19:59 |
| 2 | Webpack修改入口和出口 | 11:29 |
| 3 | 案例-打包注册用户网页-判断长度 | 11:58 |
| 4 | Webpack自动生成html文件 | 09:46 |
| 5 | Webpack打包css代码 | 10:48 |
| 6 | Webpack打包less代码 | 09:19 |
| 7 | Webpack打包图片 | 18:55 |
小结
- 排错先按“三阶段”定位:源码依赖链是否完整、Webpack 配置与依赖包是否到位、最终运行的是否为打包产物。
- 入口文件决定依赖图;没有被入口直接或间接引入的资源,不要期待被打包。
- 配置文件中涉及文件系统路径时,优先使用
path.resolve(__dirname, ...),减少执行目录差异。 clean只应作用于明确的构建输出目录,输出路径配置错误会带来误删风险。- loader 负责识别/转译文件,plugin 负责扩展构建流程;构建工具与 loader/plugin 通常放开发依赖。
- 样式、图片等问题优先查三处:是否在入口形成依赖、
rules是否匹配、loader 顺序或资源模块配置是否正确。 - 页面验证必须针对打包后的运行结果;直接打开模板 HTML 容易得到错误结论。
- 团队协作中固定使用
package.json的自定义脚本作为构建入口;具体配置项以官方文档为准,按项目路径改造。