vite-plugin-build-version-file
v0.1.8
Published
A Vite plugin that emits version.json and injects version metadata into HTML.
Maintainers
Readme
vite-plugin-build-version-file
一个面向 Vue 3 + Vite 的构建版本插件。
它会在项目运行和构建时提供统一的版本信息:
- 构建产物中生成
version.json - 可选地向 HTML 注入
window["__VERSION__"] - 支持自定义版本号、文件名、全局变量名和额外数据
这个插件只负责产出和暴露版本信息。
它不负责这些运行时行为:
- 轮询检查版本
- 弹窗提示用户更新
- 用户取消后的重试策略
- 页面刷新时机
适合用在这些场景:
- 页面显示当前前端版本
- 检测线上是否有新版本并提示刷新
- 灰度发布时对比本地版本和服务端版本
适用范围
- 仅支持
Vite - 主要面向
Vue 3项目使用 peerDependencies要求vite >= 5- 运行环境要求
node >= 18
安装
pnpm add vite-plugin-build-version-file也可以使用:
npm install vite-plugin-build-version-file快速开始
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [vue(), buildVersionPlugin()]
})默认行为
在默认配置下,插件会执行以下行为:
- 开发态访问
/version.json时返回版本信息 - 构建后在输出目录生成
version.json - 构建后的 HTML 中注入
window["__VERSION__"] - 自动尝试读取业务项目
package.json中的name和version - 开发态默认版本号为
0 - 构建态默认版本号为当前时间戳,格式为
YYYYMMDDHHmmss
默认生成的版本文件内容如下:
{
"pkgName": "your-app-name",
"pkgVersion": "1.0.0",
"time": "20260401153045",
"env": "production"
}开发态默认返回:
{
"pkgName": "your-app-name",
"pkgVersion": "1.0.0",
"time": 0,
"env": "development"
}职责边界
这个库的职责是:
- 生成版本号
- 输出
version.json - 向页面注入版本信息
- 让业务代码能读取当前版本
这些逻辑建议写在业务项目里,而不是放进这个库里:
- 多久检查一次新版本
- 请求失败后是否重试
- 用什么 UI 提示用户
- 用户点击取消后怎么处理
- 是否立即刷新页面
如果你的项目要做“检测到新版本后提示刷新”,推荐做法是:
- 用
window["__VERSION__"]读取当前页面版本 - 请求
version.json读取服务端版本 - 在业务项目里自行决定提示方式和刷新时机
配置项
type BuildVersionContext = {
command: 'serve' | 'build'
mode: string
}
type BuildVersionPluginOptions = {
filename?: string
globalName?: string
injectToHtml?: boolean
timeZone?: string
version?: string | number | ((ctx: BuildVersionContext) => string | number)
data?: Record<string, any>
}filename
- 类型:
string - 默认值:
"version.json" - 作用:控制输出文件名
说明:
- 支持相对路径,例如
meta/version.json - 构建时会输出到
dist/meta/version.json - 开发态访问路径也会同步变成对应地址
globalName
- 类型:
string - 默认值:
"__VERSION__" - 作用:控制注入到
window上的属性名
默认注入效果:
<script>
window["__VERSION__"] = { "time": "20260401153045", "env": "production" };
</script>这里注入的是完整对象,不是单独的版本字符串。
injectToHtml
- 类型:
boolean - 默认值:
true - 作用:是否向 HTML 注入
window全局变量
当设置为 false 时:
- 仍然会生成
version.json - 不会注入
window["__VERSION__"]
version
- 类型:
string | number | ((ctx) => string | number) - 默认值:开发态为
0,构建态为当前时间戳 - 作用:自定义版本号生成逻辑
如果传入函数,函数会收到:
{
command: 'serve' | 'build',
mode: string
}timeZone
- 类型:
string - 默认值:
"Asia/Shanghai" - 作用:控制默认时间按哪个时区生成
说明:
- 只影响插件默认生成的
time - 如果构建环境是 UTC,也会按设置的时区输出
- 如果传了
version,则以你自己的version逻辑为准
data
- 类型:
Record<string, any> - 默认值:
{} - 作用:向最终生成的版本信息对象中追加自定义字段
说明:
- 插件会自动从业务项目的
package.json中读取name和version,分别写入pkgName和pkgVersion - 查找位置是从当前 Vite 项目根目录开始,向上寻找最近的
package.json - 会同时影响开发态接口返回、构建产物中的
version.json和注入到window的对象 - 如果
data里存在time或env同名字段,最终仍以插件生成的值为准 - 如果
data里存在pkgName或pkgVersion,读取到业务项目package.json时会以自动读取的值为准;读取不到时会保留data里的值
使用示例
1. 使用默认配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [vue(), buildVersionPlugin()]
})默认情况下,插件会尝试从业务项目的 package.json 中读取:
name->pkgNameversion->pkgVersion
2. 自定义全局变量名
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [
vue(),
buildVersionPlugin({
globalName: '__APP_VERSION__'
})
]
})注入后可以这样读取:
const payload = window['__APP_VERSION__']
const time = payload.time3. 只保留 version.json,不注入 window
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [
vue(),
buildVersionPlugin({
injectToHtml: false
})
]
})4. 自定义输出路径
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [
vue(),
buildVersionPlugin({
filename: 'meta/version.json'
})
]
})构建后输出:
dist/meta/version.json5. 自定义版本号生成逻辑
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [
vue(),
buildVersionPlugin({
version: ({ command, mode }) => {
if (command === 'serve') {
return 0
}
return `${mode}-20260401153045`
}
})
]
})6. 指定时区生成时间
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [
vue(),
buildVersionPlugin({
timeZone: 'Asia/Shanghai'
})
]
})7. 追加自定义数据
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import buildVersionPlugin from 'vite-plugin-build-version-file'
export default defineConfig({
plugins: [
vue(),
buildVersionPlugin({
data: {
appName: 'admin',
gitBranch: 'release/2026-04',
commitSha: 'abc1234'
}
})
]
})生成结果示例:
{
"appName": "admin",
"gitBranch": "release/2026-04",
"commitSha": "abc1234",
"time": "20260401153045",
"env": "production"
}在项目中读取版本
插件提供两种方式读取版本号,可根据场景选择:
方式一:读取注入的全局变量
const payload = window['__VERSION__']
console.log(payload.time)
console.log(payload.env)说明:
- 需要确保
injectToHtml为true(默认值) - 这里读到的是完整对象,不是单独字符串
- 如果配置了
data,这里也可以直接读取对应字段
方式二:读取 version.json
const response = await fetch('/version.json')
const payload = await response.json()
console.log(payload.time)
console.log(payload.env)如果你配置了自定义 filename,这里的请求路径也需要改成对应地址。
如果你配置了 data,返回结果中也会包含这些额外字段。
默认情况下,如果业务项目存在 package.json,返回结果中也会包含:
pkgNamepkgVersion
在项目中做版本检查
推荐把“检查新版本并提示刷新”的逻辑写在业务项目里。
通用伪代码:
const CHECK_INTERVAL = 60 * 1000
const VERSION_URL = `${import.meta.env.VITE_BASE_PATH}/version.json`
async function checkVersion() {
try {
const response = await fetch(VERSION_URL, {
cache: 'no-store'
})
const payload = await response.json()
const currentPayload = window.__VERSION__
if (currentPayload && payload.time !== currentPayload.time) {
const shouldReload = await showUpdatePrompt()
if (shouldReload) {
window.location.reload()
return
}
}
} catch (error) {
console.warn('check version failed', error)
}
scheduleNextCheck()
}
function scheduleNextCheck() {
setTimeout(checkVersion, CHECK_INTERVAL)
}
function showUpdatePrompt() {
// 这里替换成你自己的弹窗、消息组件或确认框
return Promise.resolve(window.confirm('检测到新版本,是否刷新页面?'))
}
checkVersion()建议:
- 版本比较只判断
payload.time和当前页面里的window.__VERSION__.time是否一致 - 提示方式由业务项目自己决定,可以是弹窗、消息条、通知或静默刷新
- 轮询间隔不要过短,通常用 1 分钟或更长更合适
- 请求失败后继续下一轮检查,避免一次失败后整个流程中断
上面这段逻辑故意没有放进插件里,因为不同项目通常会有不同要求:
- 轮询频率不同
- 请求路径可能不同
- 弹窗组件不同
- 刷新策略不同
- 失败重试策略不同
开发态行为说明
开发态下,插件不会往项目的 public/ 目录写文件。
它会直接通过 Vite dev server 返回版本 JSON,因此:
- 不会污染业务项目目录
- 更适合本地调试
- 修改配置后重新启动 dev server 即可看到结果
如果项目配置了 base,版本文件访问路径会自动跟随 base。
本地开发与联调
仓库中已经提供了一个专门用于调试的 Vite + Vue 3 测试项目:
- 路径:
debug/fixture-app - 引用方式:直接引用根目录
dist/index.mjs
这意味着它测试的是“打包后的真实产物”,而不是源码直连。
安装依赖
pnpm install构建插件
pnpm build启动测试项目
pnpm dev:fixture启动后可以在页面里直接看到:
window["__VERSION__"]/version.json的返回结果
构建测试项目
pnpm build:fixture这个命令会先构建插件,再构建测试项目,用来验证 dist 产物能否被正常消费。
发布到 npm
1. 登录 npm
npm login2. 构建并验证
pnpm build
pnpm build:fixture3. 发布公开包
npm publish --access public发布前检查建议
发布前建议至少确认以下几点:
dist/index.mjs、dist/index.cjs、dist/index.d.ts已生成debug/fixture-app可以正常运行或构建version.json输出正常- HTML 注入结果符合预期
package.json中的name、version、exports、publishConfig正确
如果你要进一步检查最终发布内容,可以执行:
npm pack正常情况下,发布包中应只包含:
distREADME.mdLICENSEpackage.json
License
MIT
