4、构建工具配置:Webpack/Vite核心配置、环境变量管理、路径别名配置、构建优化基础
说到构建工具,我这些年跟Webpack和Vite都打过不少交道。说实话,早期用Webpack的时候,光是配置就能写满一整个屏幕。后来Vite出来了,确实清爽很多。但不管用哪个,核心要解决的问题其实都一样——怎么让代码跑起来,怎么让构建更快,怎么让环境切换不出幺蛾子。
4.1 Webpack核心配置:从零搭一个能用的架子
先聊聊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: '[name].[contenthash].js',
clean: true // 每次构建前清理dist
},
// 模块处理规则
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']
}
]
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html'
})
]
};
我的小经验:contenthash这个配置一定要加上。我在项目中遇到过好几次,改了代码但用户浏览器不更新,就是因为没用hash。加上之后,文件内容变了hash就变,缓存问题迎刃而解。
4.2 Vite核心配置:快就一个字
Vite为什么快?说白了就是开发时用ES Module,不用打包。我第一次用Vite的时候,那个启动速度真的惊到我了——秒开。
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
// 开发服务器配置
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的proxy配置在开发时非常好用。我曾经有个项目,后端接口跨域问题折腾了半天,最后发现Vite的proxy一行配置就搞定了。你想想看,省了多少事。
4.3 环境变量管理:别让配置泄露到线上
环境变量这块,我踩过不少坑。最惨的一次,不小心把测试环境的API密钥提交到了代码仓库...嗯,从那以后我对环境变量管理就特别上心。
Webpack和Vite处理环境变量的方式不太一样:
| 特性 | Webpack | Vite |
|---|---|---|
| 内置支持 | 需要DefinePlugin | 默认支持import.meta.env |
| 环境文件 | .env文件 + dotenv | .env文件(内置支持) |
| 变量前缀 | 自定义 | VITE_ |
| 类型提示 | 需要额外配置 | 内置类型定义 |
// .env.development
VITE_API_BASE_URL=http://localhost:8080/api
VITE_APP_TITLE=开发环境
// .env.production
VITE_API_BASE_URL=https://api.example.com
VITE_APP_TITLE=生产环境
// 在代码中使用
const apiUrl = import.meta.env.VITE_API_BASE_URL;
避坑指南:千万不要把敏感信息(比如数据库密码、私钥)放到前端环境变量里。前端代码是公开的,这些变量最终会被打包到JS文件中。我曾经见过有人把阿里云AccessKey放进去...后果你懂的。
4.4 路径别名配置:告别../../../地狱
写过大型项目的人都知道,相对路径引用有多痛苦。我记得有个项目,一个组件引用了七层目录外的文件,那个路径长得...我每次看到都想骂人。
路径别名就是来解决这个问题的:
// Webpack配置
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
}
}
// Vite配置
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components')
}
}
// 使用方式(两者一样)
import Button from '@/components/Button';
import { formatDate } from '@utils/date';
我的习惯:我会在项目一开始就把常用的路径别名配好,比如@(src根目录)、@components、@utils、@styles。这样后面写代码的时候,引用路径清晰又简短。你想想看,import '@/components/Button' 和 import '../../../../components/Button',哪个看着舒服?
4.5 构建优化基础:让打包快一点,再快一点
构建优化这个话题,我可以聊一整天。这里先讲几个最基础、最实用的优化点:
4.5.1 代码分割
为什么要做代码分割?说白了就是不要让用户一次性下载所有代码。我见过一个项目,首屏JS包有3MB...加载了快10秒。
// 动态导入实现代码分割
const AdminPage = () => import('./pages/AdminPage');
// Webpack的splitChunks配置
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
4.5.2 Tree Shaking
Tree Shaking,说白了就是去掉没用到的代码。Webpack和Vite都支持,但有个前提——你的代码必须是ES Module格式。
关键点:使用import/export语法,不要用require/module.exports。我在项目中遇到过,明明配了Tree Shaking但体积没变化,最后发现是某个库用了CommonJS格式。
4.5.3 压缩与缓存
这两个优化点,配置起来很简单,但效果很明显:
// Webpack配置
const TerserPlugin = require('terser-webpack-plugin');
optimization: {
minimize: true,
minimizer: [new TerserPlugin({
terserOptions: {
compress: {
drop_console: true // 去掉console.log
}
}
})],
// 持久化缓存
cache: {
type: 'filesystem'
}
}
// Vite配置(默认已开启)
build: {
minify: 'terser', // 或 'esbuild'
target: 'es2015'
}
一个小技巧:开发环境不要开压缩,不然调试起来很痛苦。生产环境再开压缩和去掉console.log。我一般会在CI/CD流程里区分环境配置。
4.6 总结一下
构建工具配置这块,说白了就是三个核心:
- 基础配置:入口、出口、loader、plugin,这是骨架
- 环境管理:开发/测试/生产环境分开,变量别泄露
- 构建优化:代码分割、Tree Shaking、压缩缓存,让项目跑得快
我个人建议,刚开始接触的时候,先用Vite搭个小项目试试手。等理解了构建流程,再去研究Webpack的深度配置。毕竟,工具是为人服务的,别让配置本身成了负担。
下一章,我们会聊聊代码规范与质量保障。嗯,那又是一个能聊很多的话题。