@qq1766141548/web-version-refresh
v0.1.0
Published
Framework-independent browser resource version refresh with Vite integration.
Maintainers
Readme
@qq1766141548/web-version-refresh
Framework-independent browser resource version checking with a Vite build plugin.
Install
npm install @qq1766141548/web-version-refreshConfigure Vite
import { defineConfig } from 'vite'
import { webVersionPlugin } from '@qq1766141548/web-version-refresh/vite'
export default defineConfig({
plugins: [
webVersionPlugin({
version: process.env.BUILD_VERSION || '1.0.0',
}),
],
})The plugin injects the build version into the generated HTML and JavaScript bundle, emits app-version.json, and serves the manifest during Vite development.
For production builds, the plugin also injects a small script before other resources. It immediately checks the deployed version and listens for entry script, stylesheet, module preload, and Vite dynamic chunk failures. A stale page or failed asset load is retried once with ?__app_version__=<version>, without depending on the application bundle being able to start.
CI/CD
Pass a stable, unique application version into the Vite build. A Git commit SHA, release number, or CI pipeline ID is recommended:
BUILD_VERSION="$CI_COMMIT_SHA" npm run buildGitHub Actions example:
- name: Build web application
run: npm run build
env:
BUILD_VERSION: ${{ github.sha }}The value is read by the Vite configuration shown above. During the same build, the plugin injects that value into the generated HTML and JavaScript bundle and writes it to dist/app-version.json, so no separate manifest-generation command is required.
Deploy the complete output directory from that build as one release. Do not reuse an app-version.json from another build or change it after the bundle has been built. When a platform cannot deploy atomically, upload hashed static assets first and publish the HTML and app-version.json only after those assets are available.
BUILD_VERSION identifies the deployed web application, not the npm package version of @qq1766141548/web-version-refresh. Keep it unchanged when retrying deployment of the same artifact, and change it whenever a new frontend artifact is released.
Vite Application Usage
No application entry-point call is required. Registering webVersionPlugin() is sufficient because the generated HTML performs the asynchronous check.
The HTML check can be configured or disabled:
webVersionPlugin({
version: process.env.BUILD_VERSION || '1.0.0',
htmlCheck: {
requestTimeout: 3000,
versionQueryKey: '__app_version__',
},
})Use manifestUrl when the version is returned by a backend endpoint or hosted outside the Vite base path:
webVersionPlugin({
version: process.env.BUILD_VERSION || '1.0.0',
manifestUrl: '/api/web/version',
})The endpoint must return a top-level, non-empty version:
{
"version": "20260813-a1b2c3d"
}For a relative Vite base, the generated relative manifest path is resolved from the current document URL. Override manifestUrl when history-mode routing and the deployment layout require a fixed manifest location.
The injected script is inline. A strict Content Security Policy must allow it through an appropriate nonce or hash. Set htmlCheck: false when the deployment cannot allow inline scripts; in that mode, use the runtime API after the application starts.
Manual Runtime API
checkWebVersion() remains available for non-Vite integrations or builds with htmlCheck: false:
import { checkWebVersion } from '@qq1766141548/web-version-refresh'
void checkWebVersion()Avoid calling the runtime API again during initial startup when the default HTML check is enabled; that would duplicate the same request. It remains useful at later business nodes such as route changes, visibility restoration, or before a critical workflow.
Set autoRefresh: false to show an application prompt before refreshing:
const result = await checkWebVersion({ autoRefresh: false })
if (result.status === 'outdated') {
const confirmed = window.confirm('A new version is available. Refresh now?')
if (confirmed) result.refresh()
}The result status is current, outdated, refreshing, or error. An outdated result provides refresh(), which reloads the current route with the target version while preserving its other query parameters and hash. The package does not depend on Vue, React, or another UI framework.
