3、构建工具选型:Webpack vs Vite vs Turbopack、构建配置基础、开发服务器配置
说到模板工程的搭建,构建工具选型永远是第一道坎。
我见过太多团队,一上来就选 Webpack,结果项目跑起来要等 30 秒热更新。也见过有人跟风上 Vite,结果遇到老项目兼容性问题,折腾了两天。
说白了,没有银弹。每种工具都有自己的脾气。
3.1 三大构建工具横向对比
我们先看一张对比表,心里有个底:
| 特性 | Webpack 5 | Vite 4/5 | Turbopack (Alpha) |
|---|---|---|---|
| 启动速度 | 慢(需全量打包) | 极快(基于 ESM) | 极快(Rust 编写) |
| 热更新速度 | 中等(模块多时变慢) | 极快(按需编译) | 极快(增量编译) |
| 生态成熟度 | ★★★★★ | ★★★★☆ | ★★☆☆☆ |
| 配置复杂度 | 高 | 低 | 低 |
| 插件丰富度 | 极丰富 | 较丰富 | 有限 |
| 生产构建速度 | 中等 | 快(Rollup) | 快(Rust) |
| 适用场景 | 大型复杂项目、老项目 | 新项目、中小型项目 | Next.js 生态 |
3.2 我为什么还在用 Webpack?
说实话,现在让我选新项目,我大概率会选 Vite。但现实是,很多公司有大量存量项目,Webpack 依然是主力。
我在上一家公司接手过一个 5 年历史的后台系统,Webpack 配置写了 400 多行。你想想看,这种项目谁敢轻易换构建工具?
核心结论:
- 新项目、纯前端项目 → 优先 Vite
- 老项目、需要深度定制 → 继续 Webpack
- Next.js 项目 → 等 Turbopack 稳定后再考虑
3.3 构建配置基础(以 Webpack 为例)
不管用哪个工具,核心配置思路是相通的。我习惯把配置拆成三块:
- 入口与出口 — 告诉工具从哪里开始,打包到哪里去
- Loader 与规则 — 处理不同类型的文件
- 插件 — 做 Loader 做不了的事
一个最基础的 Webpack 配置长这样:
// 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.[contenthash].js',
clean: true
},
// 模块规则
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg)$/,
type: 'asset/resource'
}
]
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html'
})
],
// 模式
mode: 'development'
};
小技巧:contenthash 是缓存利器。文件内容变了,hash 才会变,浏览器就知道该重新下载了。我曾经见过有人没用 hash,每次发版用户都要清缓存,那叫一个痛苦。
3.4 Vite 配置 — 真香警告
Vite 的配置就清爽多了。它基于 ESM,开发时不用打包,按需编译。我第一次用的时候,项目启动速度从 15 秒降到了 2 秒,当时就愣住了。
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
build: {
outDir: 'dist',
sourcemap: false,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom']
}
}
}
}
});
看到了吗?Vite 内置了 React 插件支持,不用自己配 Babel。路径别名也直接写在 resolve 里,比 Webpack 的 resolve.alias 直观多了。
3.5 开发服务器配置 — 避坑指南
开发服务器是每天都要打交道的东西。配置不好,一天的心情都毁了。
3.5.1 代理配置
前后端分离开发时,跨域问题是躲不开的。我曾经犯过一个低级错误:把代理路径写成了 /api/(带斜杠),结果请求一直 404。后来才发现,Vite 和 Webpack 的代理路径匹配规则不一样。
// Webpack devServer 代理
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
pathRewrite: { '^/api': '' },
changeOrigin: true
}
}
}
// Vite 代理(注意!路径匹配规则不同)
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
rewrite: (path) => path.replace(/^\/api/, ''),
changeOrigin: true
}
}
}
注意:Webpack 用 pathRewrite,Vite 用 rewrite 函数。别搞混了,不然调试半天找不到原因。
3.5.2 HMR 配置
热模块替换(HMR)是开发体验的核心。Vite 默认就支持,Webpack 需要额外配置:
// Webpack 启用 HMR
const webpack = require('webpack');
module.exports = {
devServer: {
hot: true,
liveReload: false // 关闭自动刷新,只做热更新
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
嗯,这里要注意:如果 HMR 不生效,先检查 entry 文件里有没有加 module.hot.accept()。我刚开始用 Webpack 时,折腾了一下午才发现是这个问题。
3.6 如何选择?我的建议
最后给个实在的建议:
- 如果你在搭新项目模板 — 无脑选 Vite。开发体验好,配置简单,社区资源也够用。
- 如果你在维护老项目 — 别急着换工具。先把 Webpack 配置优化好,比如用
cache: { type: 'filesystem' }开启持久化缓存,能快不少。 - 如果你在用 Next.js — 可以关注 Turbopack,但目前还是 alpha 阶段,生产环境慎用。
说白了,工具是为人服务的。别为了炫技而选工具,也别因为怕麻烦而拒绝新工具。找到适合团队和项目的,就是最好的。
一句话总结:Vite 是现在,Webpack 是过去,Turbopack 是未来。但「现在」和「过去」之间,还有很长一段路要走。