1、Webpack入门:Webpack是什么、为什么需要Webpack、Webpack核心概念
说实话,我第一次接触Webpack的时候,也是一脸懵。那时候前端项目还停留在「写几个HTML文件,引几个script标签」的阶段。直到我接手了一个稍微大点的项目——几十个JS文件,依赖关系乱成一锅粥,加载顺序稍微不对就报错。嗯,从那时起,我才真正意识到:前端工程化,不是锦上添花,而是刚需。
Webpack是什么?
简单来说,Webpack就是一个静态模块打包工具。它会把你的项目里所有的资源——JS、CSS、图片、字体——都当作「模块」来处理。然后根据它们之间的依赖关系,打包成几个(甚至一个)浏览器能直接识别的文件。
我习惯这么理解:你写代码时,可以随意用import、require、ES Module、CommonJS,怎么舒服怎么来。但浏览器不认这些啊。Webpack就是那个「翻译官」,帮你把这些高级语法转成浏览器能跑的东西。
核心思想:一切皆模块。Webpack把项目中的任何文件都视为模块,通过Loader转换,通过Plugin扩展功能,最终输出优化后的静态资源。
为什么需要Webpack?
你想想看,如果没有Webpack,我们面临什么问题?
- 模块化混乱:全局变量满天飞,命名冲突是家常便饭
- 加载顺序依赖:你得手动保证jQuery在插件之前加载,否则报错
- 资源无法优化:代码压缩、图片压缩、Tree Shaking,这些全靠手动?不现实
- 新语法不能用:想用ES6+、TypeScript、Sass?浏览器不买账
我在项目中遇到过最典型的场景:一个老项目,引了20多个第三方库,光script标签就写了30行。后来想升级某个库,结果牵一发而动全身,改了两天还没搞定。那时候我就想,要是早点用Webpack,哪来这些破事?
我的建议:只要项目超过3个JS文件,或者用到了npm包,就应该上Webpack。别等到代码乱成一团再重构,那成本高得多。
Webpack核心概念
Webpack有五个核心概念,我建议你死记硬背也要记住。因为后面所有的配置,都是围绕这五个东西展开的。
| 概念 | 作用 | 类比理解 |
|---|---|---|
| Entry(入口) | 告诉Webpack从哪个文件开始打包 | 就像做菜的第一步——先切哪颗菜 |
| Output(输出) | 告诉Webpack打包后的文件放哪里、叫什么名 | 菜做好了,装哪个盘子里 |
| Loader(加载器) | 让Webpack能处理非JS文件(CSS、图片、字体等) | 就像不同的厨具——炒锅炒菜,蒸锅蒸鱼 |
| Plugin(插件) | 扩展Webpack的功能,做Loader做不了的事 | 就像厨房里的烤箱、微波炉——额外功能 |
| Mode(模式) | 设置构建环境(开发/生产),自动启用优化 | 就像做菜选「家常模式」还是「宴客模式」 |
1. Entry(入口)
入口就是Webpack开始打包的起点。默认值是 ./src/index.js,但你可以改成任何文件。
// 单入口写法(最常见)
module.exports = {
entry: './src/index.js'
};
// 多入口写法(多页面应用)
module.exports = {
entry: {
home: './src/home.js',
about: './src/about.js',
contact: './src/contact.js'
}
};
我个人习惯用单入口,配合React或Vue的路由来做页面切换。多入口一般用在传统多页应用里,比如后台管理系统。
2. Output(输出)
输出告诉Webpack打包后的文件放哪。默认是 ./dist/main.js,但一般我们会自定义。
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
// 多入口时,用占位符动态命名
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js' // 比如 home.abc123.js
}
};
注意:output的path必须用绝对路径。我见过不少新手用相对路径,结果打包出来的文件不知道跑哪去了。用 path.resolve 准没错。
3. Loader(加载器)
Webpack本身只认识JS和JSON。遇到CSS、图片、TypeScript怎么办?就需要Loader来「翻译」。
Loader的执行顺序是从右到左,从下到上。这一点我曾经踩过坑——写错了顺序,结果样式死活不生效。
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'] // 先css-loader解析,再style-loader注入
},
{
test: /\.(png|jpg|gif)$/,
use: ['file-loader']
}
]
}
};
举个例子:处理CSS时,css-loader 负责解析CSS文件中的 @import 和 url(),而 style-loader 把解析后的CSS通过 <style> 标签插入到HTML中。顺序反了,Webpack会直接报错。
4. Plugin(插件)
Loader只能处理文件转换,但Plugin能做更多——比如生成HTML文件、压缩代码、提取CSS、分析打包体积等。
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 以这个HTML为模板
filename: 'index.html' // 输出到dist目录
})
]
};
我最常用的Plugin就是 HtmlWebpackPlugin,它会自动把打包后的JS文件注入到HTML中。你想想看,如果每次打包后都要手动改script标签的路径,那得多崩溃?
5. Mode(模式)
Mode是Webpack 4引入的,用来区分开发环境和生产环境。说白了,就是帮你自动开启一些优化。
| 模式 | 特点 | 适用场景 |
|---|---|---|
development |
打包速度快,保留源码注释,方便调试 | 本地开发 |
production |
代码压缩、Tree Shaking、作用域提升,体积更小 | 线上部署 |
none |
不启用任何默认优化 | 特殊场景(比如分析打包结果) |
module.exports = {
mode: 'production', // 或者 'development'
// 其他配置...
};
避坑指南:我曾经在生产环境忘了设mode为production,结果打包出来的文件有2MB,线上加载慢得不行。后来才发现,原来mode不设的话,Webpack默认是none,什么优化都不做。所以,上线前一定记得检查mode!
一个完整的入门配置
说了这么多,咱们来个完整的例子。这是我最常用的入门配置,麻雀虽小五脏俱全:
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
clean: true // 每次打包前清空dist目录
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|jpg|gif)$/,
type: 'asset/resource' // Webpack 5内置了file-loader的功能
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
mode: 'development'
};
这个配置虽然简单,但已经能覆盖大部分小项目的需求了。你只需要在 src/index.js 里写代码,在 src/index.html 里写HTML结构,然后运行 npx webpack,就能在 dist 目录看到打包结果。
嗯,到这里,Webpack的入门知识就差不多了。说白了,Entry、Output、Loader、Plugin、Mode这五个概念,就是Webpack的「五脏六腑」。后面的所有高级配置,都是在这五个基础上做文章。你先把它们吃透,后面的路就好走了。