Vite And Webpack
The differences between Vite and Webpack
Vite
- Vite 采用 “约定优于配置” 的理念,默认配置已能满足大部分项目需求
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
// 1. 项目根目录(默认process.cwd())
root: process.cwd(),
// 2. 项目部署基础路径(默认'/',子路径需配置,如GitHub Pages)
base: '/',
// 3. 开发服务器配置
server: {
port: 5173, // 开发端口(默认5173)
open: true, // 自动打开浏览器
host: '0.0.0.0', // 允许局域网访问
strictPort: false, // 端口被占用时是否自动切换
proxy: {
// 跨域代理
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
hmr: {
// 热更新配置
overlay: true, // 错误浮层显示
},
},
// 4. 构建配置
build: {
outDir: 'dist', // 输出目录(默认dist)
assetsDir: 'assets', // 静态资源目录(默认assets)
assetsInlineLimit: 4096, // 小于4kb的资源内嵌为base64
sourcemap: false, // 是否生成sourcemap(默认false)
minify: 'esbuild', // 压缩工具(esbuild比terser快10-100倍)
rollupOptions: {
// Rollup打包配置(Vite底层用Rollup)
input: {
// 多入口配置
main: resolve(__dirname, 'index.html'),
admin: resolve(__dirname, 'admin.html'),
},
output: {
// 静态资源命名规则
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
},
},
},
// 5. 插件配置
plugins: [
vue(), // Vue3插件
// 其他常用插件:
// vite-plugin-html(HTML注入)
// vite-plugin-svg-icons(SVG图标)
// vite-plugin-pwa(PWA支持)
],
// 6. 解析配置
resolve: {
alias: {
// 路径别名
'@': resolve(__dirname, 'src'),
components: resolve(__dirname, 'src/components'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], // 省略后缀
},
// 7. CSS配置
css: {
modules: {
// CSS Modules配置
scopeBehaviour: 'local', // 局部作用域
generateScopedName: '[name]__[local]___[hash:base64:5]', // 类名生成规则
},
preprocessorOptions: {
// 预处理器配置(无需额外loader)
scss: {
additionalData: `@import "@/styles/variables.scss";`, // 全局注入变量
},
},
devSourcemap: true, // 开发环境CSS sourcemap
},
// 8. 依赖优化
optimizeDeps: {
include: ['lodash-es', 'axios'], // 强制预构建的依赖
exclude: ['vue-demi'], // 排除预构建的依赖
},
// 9. 环境变量配置
envDir: '.env', // 环境变量文件目录(默认项目根目录)
envPrefix: 'VITE_', // 环境变量前缀(默认VITE_,如VITE_API_URL)
})
Webpack
- Webpack 是 “配置驱动” 的打包工具,几乎所有功能都需要手动配置
// webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpack = require('webpack')
module.exports = {
// 1. 入口配置
entry: {
main: './src/main.js', // 主入口
vendor: ['lodash-es', 'axios'], // 第三方依赖入口(拆分用)
},
// 2. 输出配置
output: {
filename: 'assets/js/[name].[contenthash].js', // 入口文件命名(contenthash缓存)
chunkFilename: 'assets/js/[name].[contenthash].chunk.js', // chunk文件命名
path: path.resolve(__dirname, 'dist'), // 输出目录
publicPath: '/', // 静态资源基础路径
assetModuleFilename: 'assets/[ext]/[name].[hash].[ext]', // 静态资源命名(Webpack5+)
},
// 3. 模块解析配置
resolve: {
alias: {
// 路径别名
'@': path.resolve(__dirname, 'src'),
components: path.resolve(__dirname, 'src/components'),
},
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue', '.json'], // 省略后缀
modules: [path.resolve(__dirname, 'src'), 'node_modules'], // 模块查找路径
},
// 4. 模块规则配置(核心:处理不同类型文件)
module: {
rules: [
// 4.1 JavaScript/TypeScript处理(Babel转译)
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/, // 排除node_modules
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env', // ES6+转ES5
'@babel/preset-react', // React转译
'@babel/preset-typescript', // TypeScript转译
],
plugins: [
'@babel/plugin-proposal-class-properties', // 类属性支持
'@babel/plugin-transform-runtime', // 避免重复代码
],
},
},
},
// 4.2 CSS处理
{
test: /\.css$/,
use: [
process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader, // 开发环境内嵌,生产环境提取
'css-loader', // 解析CSS
'postcss-loader', // 自动前缀、CSS优化(需配合postcss.config.js)
],
},
// 4.3 预处理器(SCSS/Sass)
{
test: /\.(scss|sass)$/,
use: [
process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader', // 解析SCSS
],
},
// 4.4 静态资源处理(Webpack5+ Asset Module)
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: 'asset', // 自动判断:小于8kb内嵌base64,否则输出文件
parser: {
dataUrlCondition: {
maxSize: 8 * 1024, // 8kb阈值
},
},
},
// 4.5 字体文件处理
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource', // 直接输出文件
},
// 4.6 Vue文件处理
{
test: /\.vue$/,
loader: 'vue-loader', // Vue2/Vue3通用
options: {
compilerOptions: {
preserveWhitespace: false, // 去除空格
},
},
},
],
},
// 5. 插件配置
plugins: [
new CleanWebpackPlugin(), // 清理dist目录(Webpack5+可省略,用output.clean)
new HtmlWebpackPlugin({
// 生成HTML文件
template: './public/index.html', // 模板文件
filename: 'index.html', // 输出文件名
chunks: ['main', 'vendor'], // 引入的chunk
minify: {
// 压缩配置
removeComments: true, // 移除注释
collapseWhitespace: true, // 折叠空格
},
}),
new MiniCssExtractPlugin({
// 提取CSS为单独文件(生产环境)
filename: 'assets/css/[name].[contenthash].css',
chunkFilename: 'assets/css/[name].[contenthash].chunk.css',
}),
new webpack.DefinePlugin({
// 注入环境变量
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify('http://localhost:3000'),
}),
new webpack.HotModuleReplacementPlugin(), // 热更新插件(开发环境)
],
// 6. 开发工具配置
devtool: process.env.NODE_ENV === 'development' ? 'eval-cheap-module-source-map' : false,
// 7. 开发服务器配置(webpack-dev-server)
devServer: {
port: 8080, // 开发端口
open: true, // 自动打开浏览器
host: '0.0.0.0', // 局域网访问
hot: true, // 启用热更新
compress: true, // 启用gzip压缩
proxy: {
// 跨域代理
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
pathRewrite: { '^/api': '' },
},
},
historyApiFallback: true, // 支持SPA路由(Vue/React Router)
},
// 8. 优化配置(Webpack5+)
optimization: {
minimize: process.env.NODE_ENV === 'production', // 生产环境压缩
minimizer: [
// 压缩工具
new TerserPlugin({
// JS压缩
parallel: true, // 并行处理
terserOptions: {
compress: { drop_console: true }, // 移除console
},
}),
new CssMinimizerPlugin(), // CSS压缩
],
splitChunks: {
// 代码分割(拆分第三方依赖和公共代码)
chunks: 'all', // 对所有chunk生效
cacheGroups: {
vendor: {
// 第三方依赖
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
priority: 10, // 优先级
reuseExistingChunk: true, // 复用已存在的chunk
},
common: {
// 公共代码
name: 'common',
minChunks: 2, // 至少被2个模块引用
priority: 5,
reuseExistingChunk: true,
},
},
},
runtimeChunk: 'single', // 单独提取运行时代码(避免缓存失效)
},
// 9. 模式配置(development/production)
mode: process.env.NODE_ENV || 'development',
}
Vite vs Webpack
| 对比维度 | Vite | Webpack |
|---|---|---|
| 核心原理 | 开发环境用 ES Module 原生加载(无需打包),生产环境用 Rollup 打包 | 全程 依赖图打包(递归解析所有模块,生成 chunk) |
| 开发启动速度 | 极快(毫秒级),无需等待打包 | 较慢(大型项目需几十秒),需打包所有模块 |
| 热更新(HMR) | 原生 ES Module HMR,速度快 | 需 HMR 插件,依赖打包重建,速度较慢 |
| 配置复杂度 | 低(约定优于配置,默认支持多数场景) | 高(需手动配置 loader、plugin、优化规则) |
| 打包工具 | 生产环境用 Rollup(比 Webpack 轻量) | 自带打包引擎(功能强但笨重) |
| 静态资源处理 | 原生支持(无需配置 loader) | 需配置 Asset Module 或 file-loader/url-loader |
| CSS 处理 | 原生支持 CSS/SCSS/LESS(无需 loader) | 需配置 style-loader/css-loader/sass-loader |
| 兼容性 | 仅支持 现代浏览器(ES6+) | 支持旧浏览器(需 Babel 转译 ES5) |
| 生态插件 | 生态较小,但兼容 Rollup 插件 | 生态庞大,插件丰富(覆盖所有场景) |
| 适用场景 | 现代前端项目(Vue/React/TS)、中小型项目 | 复杂项目(多入口、SSR、微前端)、需兼容旧浏览器 |
| 默认优化 | 预构建第三方依赖(esbuild)、缓存 | 需手动配置 splitChunks、runtimeChunk 等 |
| 错误提示 | 清晰(原生 ES Module 错误定位) | 较模糊(需 devtool 配置优化) |
总结
- Vite 是下一代构建工具,主打 “快” 和 “简洁”,适合现代浏览器环境的项目,尤其 Vue/React 单页应用。
- Webpack 是成熟的构建工具,主打 “灵活” 和 “全能”,适合复杂场景或需要兼容旧浏览器的项目