Vite利用浏览器原生ES模块实现按需加载,开发服务器启动几乎零等待,生产构建基于Rollup做Tree Shaking和代码分割。相比Webpack复杂的配置与漫长的启动等待,Vite在开发体验与构建产物体积上都有明显优势。本文拆解Vite的插件机制、构建优化配置与自定义插件开发流程。
Vite开发服务器与生产构建的双引擎架构
Vite开发阶段不打包,直接利用浏览器ESM能力按需加载模块。请求一个模块时Vite拦截请求,即时编译TS或JSX,返回浏览器可执行的ES模块。这种模式的好处是项目越大启动越快——因为不需要预打包,只有被import的模块才会被编译。
生产构建切换到Rollup引擎,做完整的静态分析、Tree Shaking和代码分割。两套引擎在行为上有差异,开发阶段能跑的代码生产构建可能报错(比如路径大小写、循环依赖),需要理解这一点并做构建验证。
构建性能优化:代码分割与预加载
Vite生产构建默认按动态import做代码分割,但可以进一步优化:
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
build: {
rollupOptions: {
output: {
// 手动分包:vendor单独打包
manualChunks: {
'react-vendor': ['react', 'react-dom'],
'ui-vendor': ['antd', '@ant-design/icons'],
'utils-vendor': ['lodash-es', 'dayjs']
}
}
},
// chunk大小告警阈值
chunkSizeWarningLimit: 500,
// 启用CSS代码分割
cssCodeSplit: true,
// 压缩配置
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
}
})
手动分包把不常变化的vendor依赖独立打包,利用浏览器缓存减少重复下载。业务代码变更时只需重新下载业务chunk,vendor chunk走缓存。配合HTML中的modulepreload提示,让浏览器在空闲时预加载关键模块:
// 在入口文件预加载路由级组件
const Dashboard = defineAsyncComponent(() =>
import('./views/Dashboard.vue')
)
Vite插件机制与自定义插件开发
Vite插件API兼容Rollup插件接口,额外扩展了开发服务器钩子。一个典型的Vite插件结构:
import type { Plugin } from 'vite'
// 自定义插件:将环境变量注入HTML
function envInjector(options: { prefix: string }): Plugin {
const envVars: Record<string, string> = {}
return {
name: 'vite-plugin-env-injector',
// 构建开始时收集环境变量
configResolved(config) {
Object.keys(process.env).forEach(key => {
if (key.startsWith(options.prefix)) {
envVars[key] = process.env[key]!
}
})
},
// 转换index.html,注入环境变量
transformIndexHtml(html) {
const scriptContent = Object.entries(envVars)
.map(([k, v]) => `'${k}': '${v}'`)
.join(',')
return html.replace(
'</head>',
`<script>window.__ENV__ = {${scriptContent}}</script></head>`
)
},
// 开发服务器中间件
configureServer(server) {
server.middlewares.use('/api/env', (req, res) => {
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify(envVars))
})
}
}
}
export default envInjector
插件钩子的执行顺序:config(修改Vite配置)到configResolved(读取最终配置)到buildStart(构建开始)到transformIndexHtml(HTML转换)到transform(模块代码转换)到generateBundle(产物处理)。开发服务器额外有configureServer钩子,可以添加自定义中间件。
开发体验优化:依赖预构建与HMR
Vite启动时会对node_modules中的依赖做预构建(esbuild打包),把CJS模块转为ESM,合并小文件减少请求次数。预构建结果缓存在node_modules/.vite目录,依赖变更时自动重新预构建。如果遇到依赖更新未生效,删除.vite目录重启即可。
// 强制重新预构建特定依赖
export default defineConfig({
optimizeDeps: {
include: ['lodash-es'],
exclude: ['@my/local-pkg']
}
})
HMR(热模块替换)通过WebSocket推送更新,CSS修改即时生效不刷新页面,React组件通过@vitejs/plugin-react的Fast Refresh保持组件状态。遇到HMR不生效时检查模块是否被多层嵌套import导致更新边界丢失,尝试用import.meta.hot.accept显式声明HMR边界。对于大型项目,把vendor依赖独立预构建可以显著减少开发服务器首次加载的等待时间。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/vite-gou-jian-gong-ju-shi-zhan-cha-jian-ji-zhi-kai-fa-yu/