Vite构建优化与实践

时游大约 2 分钟

Vite 构建优化与实践

构建配置

export default defineConfig({
	build: {
		outDir: "dist",
		assetsDir: "assets",           // 静态资源子目录
		sourcemap: false,              // 生产不输出 sourcemap
		chunkSizeWarningLimit: 1000,   // chunk 大小告警阈值(kb)
		cssCodeSplit: true,            // css 按需分包
		reportCompressedSize: false,   // 关闭 gzip 大小计算,加快构建
		rollupOptions: {
			output: {
				// 按使用方分包:node_modules 的第三方拆出来
				manualChunks(id) {
					if (id.includes("node_modules")) {
						return "vendor";
					}
				},
				// 静态资源文件名加 hash
				assetFileNames: "assets/[name].[hash:8].[ext]"
			}
		}
	}
});

体积分析与优化手段

npm i rollup-plugin-visualizer -D
import { visualizer } from "rollup-plugin-visualizer";

plugins: [visualizer({ open: true })]   # build 后自动打开 stats.html

常见优化:

  1. 按需引入组件库:element-plus 配合 unplugin-vue-components,或 babel-plugin-import(legacy)
  2. 大库替换:moment → dayjs、lodash → lodash-es(esbuild 支持摇树)
  3. 手动分包:echarts、编辑器等大体积库单独拆 chunk,利用浏览器缓存
  4. gzip:nginx 开 gzip_static on;,配合 vite-plugin-compression 产出 .gz 文件
  5. 图片压缩:vite-plugin-imagemin 或上 CDN/oss

HMR 原理简述

  1. vite dev server 与浏览器建立 WebSocket 长连接
  2. 文件变动 → server 端沿模块依赖图找到受影响的模块边界(如 vue 组件边界)
  3. 通过 WebSocket 通知浏览器 fetch 新模块代码并替换执行
  4. Vue 组件自带 HMR 处理,状态不丢失;无 HMR 处理的模块则整页刷新

与 Webpack 对比

维度Vite(dev)Webpack
启动按需编译,秒级全量打包,随项目变慢
热更新精准模块级,毫秒级重新打包受影响 chunk
配置开箱即用,配置量少loader/plugin 配置繁琐
生态沿用 rollup 插件体系最成熟
生产构建Rollup自身
浏览器需支持原生 ESM(现代型)全兼容

实战:完整的 vite.config.ts demo

import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import { fileURLToPath, URL } from "node:url";

export default defineConfig(({ mode }) => {
	const env = loadEnv(mode, process.cwd());

	return {
		plugins: [
			vue(),
			AutoImport({ resolvers: [ElementPlusResolver()] }),
			Components({ resolvers: [ElementPlusResolver()] })
		],
		resolve: {
			alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) }
		},
		server: {
			port: 20777,
			proxy: {
				"/api": { target: env.VITE_API_URL, changeOrigin: true }
			}
		},
		build: {
			rollupOptions: {
				output: {
					manualChunks: {
						vendor: ["vue", "vue-router", "pinia"],
						echarts: ["echarts"]
					}
				}
			}
		}
	};
});
Loading...