@gitlon/version
v0.1.4
Published
Vite 构建版本插件:生成 version.json、注入版本信息并提供客户端缓存刷新能力
Maintainers
Readme
@gitlon/version
Vite 构建版本插件。开发态提供版本接口,构建态输出 version.json,并可把同一份版本信息注入 HTML 和 Vite define。
安装
pnpm add -D @gitlon/version要求 Node.js >= 18、Vite >= 5。
Vite
import { defineConfig } from 'vite'
import buildVersionPlugin from '@gitlon/version'
export default defineConfig({
plugins: [buildVersionPlugin()],
})默认行为:
- 开发态通过
/version.json返回版本信息; - 构建态生成
dist/version.json; - 构建态生成
dist/refresh.html刷新页,开发态同路径响应; - 向 HTML 注入
window["__VERSION__"]、window.refreshCache()和window.checkVersion(); - 通过 Vite
define注入__VERSION__; - 读取项目最近的
package.json,写入pkgName、pkgVersion; - 开发态
time为0; - 构建态
time为Asia/Shanghai时区的YYYYMMDDHHmmss。
{
"pkgName": "your-app",
"pkgVersion": "1.0.0",
"time": "20260917153045",
"env": "production"
}VitePress
必须复用同一个插件实例:
import { defineConfig } from 'vitepress'
import buildVersionPlugin from '@gitlon/version'
const buildVersion = buildVersionPlugin()
export default defineConfig({
vite: {
plugins: [buildVersion],
},
transformHtml: buildVersion.transformHtml,
})Nuxt
Nuxt HTML 不经过 Vite transformIndexHtml,需把 headScript() 接入 render:html:
import buildVersionPlugin from '@gitlon/version'
const buildVersion = buildVersionPlugin()
export default defineNuxtConfig({
vite: {
plugins: [buildVersion],
},
hooks: {
'render:html'(html) {
html.head.push(buildVersion.headScript())
},
},
})插件自动识别 Nuxt 构建资产目录。默认静态文件路径通常为 /_nuxt/version.json。
配置
interface BuildVersionContext {
command: 'serve' | 'build'
mode: string
}
interface BuildVersionPluginOptions {
filename?: string
globalName?: string
defineName?: string | false
injectToHtml?: boolean
refreshHtml?: boolean | string
refreshKey?: string
checkKey?: string
timeZone?: string
version?: string | number | ((context: BuildVersionContext) => string | number)
data?: Record<string, any>
log?: (content: any) => string
payload?: (json: any) => any
}filename
版本文件路径,默认 version.json。自动跟随 Vite base:
buildVersionPlugin({ filename: 'meta/version.json' })globalName
HTML 注入的 window 属性名,默认 __VERSION__:
buildVersionPlugin({ globalName: '__APP_VERSION__' })defineName
Vite 编译期常量名,默认 __VERSION__。传 false 关闭:
buildVersionPlugin({ defineName: false })injectToHtml
是否注入 HTML,默认 true。关闭后仍提供和生成版本 JSON。
refreshHtml
独立刷新页的文件名,默认 refresh.html。传 false 不生成,同时不注入 refreshKey 方法:
buildVersionPlugin({ refreshHtml: 'clear.html' })
buildVersionPlugin({ refreshHtml: false })refreshKey
跳转到刷新页的全局方法名,默认 refreshCache,注入为 window.refreshCache():
buildVersionPlugin({ refreshKey: 'goRefresh' })checkKey
检查是否有新版本的全局方法名,默认 checkVersion,注入为 window.checkVersion():
buildVersionPlugin({ checkKey: 'getVersionStatus' })该方法的注入只受 injectToHtml 控制,refreshHtml: false 不影响它。
timeZone
默认版本时间所用时区,默认 Asia/Shanghai。
version
固定版本值或版本生成函数:
buildVersionPlugin({
version: ({ command, mode }) => (command === 'serve' ? 0 : `${mode}-20260917`),
})data
追加字段。覆盖顺序为 data、项目包信息、time/env、payload:
buildVersionPlugin({
data: {
appName: 'admin',
commitSha: 'abc1234',
},
})payload
最终改写 payload:
buildVersionPlugin({
payload: (json) => ({
version: json.time,
environment: json.env,
}),
})log
自定义构建完成日志:
buildVersionPlugin({
log: (payload) => `build version: ${payload.time}`,
})读取版本
运行时:
console.log(window.__VERSION__)编译期:
console.log(__VERSION__)远程检查:
const latest = await fetch('/version.json', { cache: 'no-store' }).then((response) =>
response.json(),
)
if (latest.time !== window.__VERSION__?.time) {
window.location.reload()
}或直接调用注入的全局方法,一次拿到本地与线上信息:
const { local, server, update } = await window.checkVersion()
console.log(local) // 注入的 __VERSION__
console.log(server) // 线上 version.json
if (update) window.refreshCache()返回结构为 { local, server, update }:update 由 server.time !== local.time 判定。请求失败或响应非 2xx 时不抛错,返回 server: null、update: false。请求走 no-store 并在 URL 上附加时间戳参数二次防缓存,URL 已按 Vite base 计算。
刷新项目缓存
import { clearUrlCache } from '@gitlon/version/client'
await clearUrlCache({
urls: ['/vue-app/', '/vue-app/index.html'],
redirectUrl: '/vue-app/',
time: 5,
onBeforeRedirect: async () => {
await reportUpdate()
},
})time 单位为秒,默认 5。调用时显示全屏倒计时;依次使用无缓存请求、reload 请求和隐藏 iframe 刷新各 URL,完成或超时后携带随机参数跳转。
onBeforeRedirect 在跳转前调用并被 await,适合收尾工作(存状态、埋点、清理登录态)。回调抛错或刷新超时都不影响跳转。
无参数时处理当前页面路径及其 index.html:
await clearUrlCache()hash 路由会保留,随机参数写在 # 前。该方法仅支持同源 URL;浏览器无法直接删除全部 HTTP 缓存,此方法只尽可能刷新目标项目缓存。
刷新页
插件在 dist 中生成 refresh.html,作为不依赖应用构建产物的稳定入口:
/refresh.html?url=/vue-app/ → 清理 /vue-app/ 缓存后跳转到 /vue-app/流程为:显示 loading → 对 url 及其 index.html 变体依次发送无缓存请求并加载隐藏 iframe → 完成或 5 秒超时后跳转到 url。url 支持相对路径,相对 refresh.html 所在位置解析;跳转不附加随机参数。
不带 url 参数时跳转到当前目录的 index.html:
/refresh.html → /index.html
/app/refresh.html → /app/index.html业务代码触发刷新(同事在任意位置调用):
window.refreshCache()等价于 location.replace('<刷新页路径>?_=' + Date.now() + '&url=' + encodeURIComponent(location.href)),携带当前完整 URL 并透传 hash,刷新页请求本身也带时间戳防缓存;用 replace 而非 href=,刷新页不会进入历史栈,避免用户后退时被反复弹回。路径已按 Vite base 计算。
该页脚本由插件内联生成,不 import 任何带 hash 的构建产物,所以旧版本页面也能通过它清理缓存后进入新版本。dev server 同样响应该路径。
类型导出
主入口导出:
buildVersionPluginBuildVersionContextBuildVersionPayloadBuildVersionPluginOptionsBuildVersionPlugin
客户端入口导出:
clearUrlCacheClearUrlCacheOptions
