npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-plugin-build-version-file

v0.1.8

Published

A Vite plugin that emits version.json and injects version metadata into HTML.

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 中的 nameversion
  • 开发态默认版本号为 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 中读取 nameversion,分别写入 pkgNamepkgVersion
  • 查找位置是从当前 Vite 项目根目录开始,向上寻找最近的 package.json
  • 会同时影响开发态接口返回、构建产物中的 version.json 和注入到 window 的对象
  • 如果 data 里存在 timeenv 同名字段,最终仍以插件生成的值为准
  • 如果 data 里存在 pkgNamepkgVersion,读取到业务项目 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 -> pkgName
  • version -> 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.time

3. 只保留 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.json

5. 自定义版本号生成逻辑

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)

说明:

  • 需要确保 injectToHtmltrue(默认值)
  • 这里读到的是完整对象,不是单独字符串
  • 如果配置了 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,返回结果中也会包含:

  • pkgName
  • pkgVersion

在项目中做版本检查

推荐把“检查新版本并提示刷新”的逻辑写在业务项目里。

通用伪代码:

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 login

2. 构建并验证

pnpm build
pnpm build:fixture

3. 发布公开包

npm publish --access public

发布前检查建议

发布前建议至少确认以下几点:

  • dist/index.mjsdist/index.cjsdist/index.d.ts 已生成
  • debug/fixture-app 可以正常运行或构建
  • version.json 输出正常
  • HTML 注入结果符合预期
  • package.json 中的 nameversionexportspublishConfig 正确

如果你要进一步检查最终发布内容,可以执行:

npm pack

正常情况下,发布包中应只包含:

  • dist
  • README.md
  • LICENSE
  • package.json

License

MIT