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

version-polling

v1.3.3

Published

A JavaScript library for web application updates

Downloads

1,009

Readme

version-polling

一个用于实时检测 web 应用更新的 JavaScript 库

前言

以下内容是通过 GitHub Copilot 生成的 😊

在现代 web 应用开发中,前端代码的更新频率较高,尤其是单页应用(SPA)。当应用发布新版本时,如何及时通知用户并引导其刷新页面以加载最新资源,成为了一个亟待解决的问题。version-polling 库应运而生,旨在提供一种简单高效的方式来检测前端应用的版本更新,并提示用户进行页面刷新。

适用场景

用户在浏览器中打开某 web 应用(通常是后台管理系统)很长时间且未刷新页面时,如果应用有新功能添加或问题修复,用户可能无法及时知道有新版发布。这样会导致用户继续使用旧版,影响用户体验和数据准确性,甚至出现程序报错。

功能特性

  • 针对前端 web 单页应用(SPA)而设计

  • 纯前端技术实现,使用简单无需后端支持

  • 提供三种版本控制方式

    1.使用HTTP ETag作为版本标识符
    2.使用chunkHash作为版本标识符 v1.3.0
    3.使用version.json 文件管理版本号 v1.3.0

  • 支持 TypeScript

实现原理

使用HTTP ETag作为版本标识符

使用HTTP ETag作为版本标识符来判断应用是否有更新。
HTTP ETag说明:每次请求index.html文件时,HTTP 响应头上会有一个 ETag 字段, 格式类似ETag: W/"0815"该字段的值是服务器资源的唯一标识符,通过比较前后两次请求的 Etag 字段值,可以判断资源是否发生变化,以这个为依据判断是否有更新。
缺点是HTTP ETag是由服务器生成的,前端不可控。

  1. 使用Web WorkerAPI 在浏览器后台轮询请求index.html文件,不会影响主线程运行。
  2. 请求index.html文件,对比本地和请求响应头的 ETag 的字段值。
  3. 如果 ETag 字段值不一致,说明有更新,则弹出更新提示,并引导用户手动刷新页面(例如弹窗提示),完成应用更新。
  4. 当页面不可见时(例如切换标签页或最小化窗口),停止实时检测任务;再次可见时(例如切换回标签页或还原窗口),恢复实时检测任务。
  5. 支持添加其他前端事件(例如页面导航或自定义事件)触发检测,由开发者自行决定检测时机。

使用chunkHash作为版本标识符

使用chunkHash作为版本标识符来判断应用是否有更新。
chunkHash说明:因为前端 spa 项目都是打包后再部署,这里以 vite 为例,打包产物 index.html 文件内容中会存在一个 script 标签,格式类似<script type="module" crossorigin src="/assets/index.065a65a6.js"></script>,其中index是 chunk 名称,后面的065a65a6是 chunk 哈希值,每次项目代码有改动再打包这里的chunkHash哈希值都会发生变化,以这个为依据判断是否有更新。

  1. 使用Web WorkerAPI 在浏览器后台轮询请求index.html文件,不会影响主线程运行。
  2. 请求index.html文件,对比当前文件和最新文件中的chunkHash的哈希值。
  3. 如果chunkHash哈希值不一致,说明有更新,则弹出更新提示,并引导用户手动刷新页面(例如弹窗提示),完成应用更新。
  4. 其他逻辑和方式一保持一致。

使用version.json 文件管理版本号

使用 version.json 文件管理版本内容,由开发者手动控制应用版本更新。 缺点是需要开发者手动维护 version.json 文件

  1. 使用Web WorkerAPI 在浏览器后台轮询请求version.json文件,不会影响主线程运行。
  2. 请求version.json文件,对比当前文件和最新文件中的 version 字段值。
  3. 版本号比较遵循 Semver 语义化版本规范,如果有高版本则弹出更新提示,并引导用户手动刷新页面(例如弹窗提示),完成应用更新。
  4. 其他逻辑和方式一保持一致。

浏览器兼容性

适用于支持原生 ES Modules 的浏览器

chrome >= 87
edge >= 88
firefox >= 78
safari >= 14

安装

  • 通过 npm 引入,并通过构建工具进行打包
# 本地项目安装
npm install version-polling --save
  • 通过 CDN 方式引入,直接插入到 HTML

无侵入用法,接入成本最低

<script src="https://unpkg.com/version-polling/dist/version-polling.min.js"></script>

使用参考前端静态 HTML 页面自动检测更新示例

使用示例

基础用法

当检测到有新版本时,会触发onUpdate回调函数,弹出提示用户有更新,点击确定刷新页面。

// 在应用入口文件中使用: 如 main.js, app.jsx
import { createVersionPolling } from 'version-polling';

createVersionPolling({
  silent: process.env.NODE_ENV === 'development', // 开发环境下不检测
  onUpdate: (self) => {
    const result = confirm('页面有更新,点击确定刷新页面!');
    if (result) {
      self.onRefresh();
    } else {
      self.onCancel();
    }
  },
});

使用第三方组件提示更新

import { createVersionPolling } from 'version-polling';
import { MessageBox } from 'element-ui';

createVersionPolling({
  silent: process.env.NODE_ENV === 'development', // 开发环境下不检测
  onUpdate: (self) => {
    MessageBox.confirm('检测到网页有更新, 是否刷新页面加载最新版本?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
    })
      .then(() => {
        self.onRefresh();
      })
      .catch(() => {
        self.onCancel();
      });
  },
});

使用轮询,并且设置轮询间隔

如果觉得前端轮询请求太频繁,可以设置轮询间隔为半小时。

import { createVersionPolling } from 'version-polling';

createVersionPolling({
  pollingInterval: 30 * 60 * 1000, // 每 30 分钟检测一次
  silent: process.env.NODE_ENV === 'development', // 开发环境下不检测
  onUpdate: (self) => {
    const result = confirm('页面有更新,点击确定刷新页面!');
    if (result) {
      self.onRefresh();
    } else {
      self.onCancel();
    }
  },
});

不使用轮询,仅通过前端事件触发检测

在浏览器页面导航跳转时、页面显示切换时,触发检测任务。

Window上触发的事件。

import { createVersionPolling } from 'version-polling';

createVersionPolling({
  eventTriggerList: ['popstate'],
  silent: process.env.NODE_ENV === 'development', // 开发环境下不检测
  silentPollingInterval: true,
  onUpdate: (self) => {
    const result = confirm('页面有更新,点击确定刷新页面!');
    if (result) {
      self.onRefresh();
    } else {
      self.onCancel();
    }
  },
});

通过前端自定义事件触发检测

由开发者自行决定触发检测的时机。

import { createVersionPolling } from 'version-polling';

createVersionPolling({
  eventTriggerList: ['myEvent'],
  silent: process.env.NODE_ENV === 'development', // 开发环境下不检测
  onUpdate: (self) => {
    const result = confirm('页面有更新,点击确定刷新页面!');
    if (result) {
      self.onRefresh();
    } else {
      self.onCancel();
    }
  },
});

通过dispatchEvent触发版本检测。

dispatchEvent(new CustomEvent('myEvent'));

还可以在路由跳转时触发,以Vue Router为例,借助导航守卫来触发版本检测。

router.afterEach((to, from) => {
  dispatchEvent(new CustomEvent('myEvent'));
});

设置版本控制方式为chunkHash

使用chunkHash作为版本标识符,控制应用版本更新。以打包构建工具 vite 为例。

import { createVersionPolling } from 'version-polling';

createVersionPolling({
  vcType: 'chunkHash',
  chunkName: 'index',
  silent: import.meta.env.MODE === 'development', // 开发环境下不检测
  onUpdate: (self) => {
    const result = confirm('页面有更新,点击确定刷新页面!');
    if (result) {
      self.onRefresh();
    } else {
      self.onCancel();
    }
  },
});

chunkName 也可能是其他值,例如 Vue CLI 是app,查看打包产物里index.html文件内容来确定。

设置版本控制方式为versionJson

使用version.json 文件管理版本号,控制应用版本更新。

import { createVersionPolling } from 'version-polling';

createVersionPolling({
  vcType: 'versionJson',
  silent: import.meta.env.MODE === 'development', // 开发环境下不检测
  onUpdate: (self) => {
    const result = confirm('页面有更新,点击确定刷新页面!');
    if (result) {
      self.onRefresh();
    } else {
      self.onCancel();
    }
  },
});

修改version.json文件,配置version字段值

{
  "version": "2.1.0",
  "versionContent": "更新内容: 修复已知存在的问题"
}

version.json文件跟index.html文件放在同一个服务器目录下。

API

options

| 参数 | 说明 | 类型 | 默认值 | | --------------------- | -------------------------------------------------------- | ---------------- | ---------------------------------------------------- | | vcType | 版本控制方式,可选值有etagchunkHashversionJson | string | etag | | htmlFileUrl | index.html文件地址 | string | ${location.origin}${location.pathname} | | chunkName | chunk 名称 | string | index | | versionFileUrl | version.json文件地址 | string | ${location.origin}${location.pathname}version.json | | eventTriggerList | 触发版本检测的事件名称列表 | string[] | - | | pollingInterval | 轮询间隔,单位为毫秒,默认为 5 分钟 | number | 5 * 60 * 1000 | | silent | 为true时,不进行版本检测 | boolean | false | | silentPollingInterval | 为true时,不做轮询版本检测 | boolean | false | | silentPageVisibility | 为true时,visibilitychange事件不会触发版本检测 | boolean | false | | onUpdate | 检测到版本更新触发的回调函数 | (self) => void | - |

deprecated

  • v1.3.0移除appETagKeyforceUpdate配置项,移除原因使用鸡肋

开源协议

MIT