Gathering detailed insights and metrics for @amoursun/version-check-prompt
Gathering detailed insights and metrics for @amoursun/version-check-prompt
Gathering detailed insights and metrics for @amoursun/version-check-prompt
Gathering detailed insights and metrics for @amoursun/version-check-prompt
npm install @amoursun/version-check-prompt
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (78.68%)
JavaScript (19.33%)
Shell (1.99%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
60 Commits
1 Watchers
1 Branches
1 Contributors
Updated on Apr 23, 2025
Latest Version
1.0.3
Package Id
@amoursun/version-check-prompt@1.0.3
Unpacked Size
293.66 kB
Size
59.76 kB
File Count
35
NPM Version
9.5.1
Node Version
18.16.0
Published on
Apr 23, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
一个用于检测网页版本更新并提示用户刷新的轻量级库。
1npm install @amoursun/version-check-prompt 2 3
1import { createVersionCheckPrompt, IVersionModeEnum } from '@amoursun/version-check-prompt'; 2 3const versionCheck = createVersionCheckPrompt({ 4 mode: IVersionModeEnum.ETAG, 5 htmlUrl: 'https://example.com', // 默认使用当前页面 URL 6 onUpdate: (self) => { 7 if (confirm('发现新版本,是否更新?')) { 8 self.refresh(); 9 } 10 }, 11 onError: (error) => { 12 console.error('版本检查出错:', error); 13 }, 14 activityOption: { 15 usable: true, 16 duration: 4 * 60 * 60 * 1000, // 4小时 17 onInactivityPrompt: (self) => { 18 if (confirm('您已长时间未操作,是否刷新页面?')) { 19 self.refresh(); 20 } 21 }, 22 }, 23});
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
usable | boolean | true | 是否启用版本检查,可用于开发环境禁用 |
usePollingType | IPollingTypeEnum | 'worker' | 使用检查模式 web worker 还是直接setInterval |
mode | IVersionModeEnum | 'etag' | 版本检测模式:etag/chunk/json |
htmlUrl | string | location.href | HTML 文件 URL |
jsonUrl | string | - | JSON 文件 URL(JSON 模式需要) |
pollingTime | number | 5 * 60 * 1000 | 轮询间隔时间(毫秒) |
forbiddenPolling | boolean | false | 是否禁用轮询 |
visibilityUsable | boolean | false | 是否启用页面可见性检测 |
chunkCheckTypes | IChunkCheckTypesEnum[] | ['script_src'] | Chunk 模式下检测的文件类型 |
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
usable | boolean | false | 是否启用活跃状态检测 |
duration | number | 4 * 60 * 60 * 1000 | 检测时间间隔(毫秒) |
eventNames | string[] | ['click', 'mousemove', 'keydown', 'scroll', 'touchstart'] | 监听的事件名 |
onInactivityPrompt | function | - | 超时回调函数 |
方法 | 说明 |
---|---|
refresh() | 刷新当前页面 |
reset() | 重置检测 |
check() | 手动触发检测 |
stop() | 停止检测并忽略更新提示 |
dispose() | 销毁实例 |
方法 | 说明 |
---|---|
refresh() | 刷新当前页面 |
reset() | 重置检测 |
stop() | 停止检测并忽略更新提示 |
dispose() | 销毁实例 |
通过比较 HTML 文件的 ETag 头来检测版本更新。
HTTP ETag
作为版本标识符来判断应用是否有更新说明:每次请求
index.html`文件时,HTTP 响应头上会有一个 ETag 字段,ETag: W/"0815"
该字段的值是服务器资源的唯一标识符,通过比较前后两次请求的 Etag 字段值,可以判断资源是否发生变化,以这个为依据判断是否有更新。HTTP ETag
是由服务器生成的,前端不可控。Web Worker
API 在浏览器后台轮询请求index.html
文件,不会影响主线程运行。(或者 setInterval
直接轮询)index.html
文件,对比本地和请求响应头的 ETag 的字段值。通过检测指定的资源文件(如 JS、CSS)的更新来检测版本更新。
chunkHash
作为版本标识符来判断应用是否有更新。chunk
说明:因为前端 spa 项目都是打包后再部署,这里以 vite 为例,打包产物 index.html 文件内容中会存在一个 script 标签,格式类似<script type="module" crossorigin src="/assets/index.065a65a6.js"></script>
,/assets/index.065a65a6.js
等是否有差异新增变化, 判断以这个为依据判断是否有更新。Web Worker
API 在浏览器后台轮询请求index.html
文件,不会影响主线程运行。index.html
文件,对比当前文件和最新文件中的chunk
的值。chunk
值不一致,说明有更新,则弹出更新提示,并引导用户手动刷新页面(例如弹窗提示),完成应用更新。通过比较 JSON 文件内容来检测版本更新。
version.json
文件管理版本内容,由开发者手动控制应用版本更新。version.json
文件Web Worker
API 在浏览器后台轮询请求version.json
文件,不会影响主线程运行。version.json
文件,对比当前文件和最新文件中的 version 字段值。custom-version.js
1// 引入文件系统模块中的读取和写入功能 2const { readFileSync, writeFileSync, mkdirSync, existsSync } = require('node:fs'); 3// 解析路径模块,用于处理文件路径 4const path = require('node:path'); 5 6function getRootDir() { 7 // 优先从环境变量读取 8 if (process.env.PROJECT_ROOT) { 9 return path.resolve(process.env.PROJECT_ROOT); 10 } 11 // 动态查找 package.json 12 let currentDir = __dirname; 13 while (currentDir !== path.parse(currentDir).root) { 14 if (fs.existsSync(path.join(currentDir, 'package.json'))) { 15 return currentDir; 16 } 17 currentDir = path.dirname(currentDir); 18 } 19 throw new Error('未找到项目根目录(需存在 package.json)'); 20} 21const rootDir = getRootDir(); 22 23// [ 24// '/Users/xxx/.nvm/versions/node/v18.16.0/bin/node', 25// '/Users/xxx/Desktop/github/version-check-prompt/script/config-version.cjs', 26// // zx 执行命令 时,会传入以下参数 script/config-version.js, node 执行命令则没有 27// '-o', 28// '你要输出的目录', 29// ] 30const args = process.argv.slice(2); // 去掉前两个默认参数(node路径和脚本路径) 31let outputDir = ''; // 默认值 32 33// 解析 -o 参数, node / zx 等输出结果不同, node -o(2), zx -o(3) 34// node script/config-version.cjs -o 输出目录 => -o(2) 输出目录(3) 35// zx script/config-version.cjs -o 输出目录 => -o(3) 输出目录(4) 36const oIndex = args.indexOf('-o'); 37if (oIndex !== -1 && args[oIndex + 1]) { 38 outputDir = args[oIndex + 1]; 39} 40if (outputDir.includes('..')) { 41 throw new Error('输出目录路径不能包含上级目录引用(如 "..")'); 42} 43else if (!outputDir.trim()) { 44 throw new Error('输出目录路径不能为空'); 45} 46console.log('输出目录:', outputDir); 47 48const basePathFold = path.join(rootDir, outputDir); 49const versionFilePath = path.join(basePathFold, 'version.json'); 50 51// 确保目录存在 52if (!existsSync(basePathFold)) { 53 mkdirSync(basePathFold, { recursive: true }); 54} 55 56function formatTime(date) { 57 /** 58 * hour12: false: 强制使用24小时制, 避免输出 PM/AM 59 * replace(/\//g, '-'): 默认中文环境下日期分隔符是 /, 替换为 - 60 * replace(/,/g, ''): 移除日期和时间之间的逗号(如 2025/04/17, 19:48:03 → 2025-04-17 19:48:03) 61 * en-US: 04-17-2025 19:51:34 62 * zh-CN: 2025-04-17 19:51:34 63 */ 64 return new Intl.DateTimeFormat('zh-CN', { 65 year: 'numeric', 66 month: '2-digit', 67 day: '2-digit', 68 hour: '2-digit', 69 minute: '2-digit', 70 second: '2-digit', 71 hour12: false 72 }) 73 .format(date) 74 .replace(/\//g, '-') 75 .replace(/,/g, ''); 76} 77// // 初始化版本文件 78// if (!existsSync(versionFilePath)) { 79// writeFileSync(versionFilePath, JSON.stringify({ 80// }, 'utf-8', 4)); 81// } 82 83// 获取当前时间戳和格式化时间 84function getCurrentVersionInfo() { 85 const now = new Date(); 86 return { 87 version: now.toISOString().replace(/[-:T.]/g, '').slice(0, 14), // YYYYMMDDHHmmss 88 timestamp: now.getTime(), 89 formattedTime: formatTime(now) 90 }; 91} 92 93// 更新版本 94function updateVersion() { 95 const newInfo = getCurrentVersionInfo(); 96 97 98 writeFileSync( 99 versionFilePath, 100 JSON.stringify(newInfo, 'utf-8', 4) 101 ); 102 console.log('版本已更新:', newInfo); 103} 104 105function main() { 106 // 执行更新操作 107 updateVersion(); 108} 109 110main(); 111
1"scripts": { 2 "build:test:version": "zx scripts/custom-version.js -o dest/json", 3 "build:test:version2": "node scripts/custom-version.js -o dest/json", 4},
适用于支持原生 ES Modules 的浏览器
1chrome >= 87 2edge >= 88 3firefox >= 78 4safari >= 14
1# 安装依赖 2npm install 3 4# 运行测试 5npm test 6 7# 构建 8npm run build
1npm publish --access public --registry https://registry.npmjs.org 2npm pack --dry-run # 检查打包文件结构 3
MIT
1# 交互式测试模式 2npm test 3 4# 单次运行测试 5npm run test:run 6 7# 运行测试并生成覆盖率报告 8npm run test:coverage 9 10# 运行特定测试文件 11npx vitest src/utils/util-polling.test.ts 12 13# 运行匹配特定名称的测试 14npx vitest -t "checkUpdated" 15 16# 设置测试超时时间为 10 秒 17npx vitest --testTimeout 10000 18 19# 使用 JSON 报告格式 20npx vitest --reporter json 21 22# 想要测试 src/utils 和 src/polling 文件夹,并生成覆盖率报告 23npx vitest run --coverage src/utils src/polling 24 25# 监视模式 26npx vitest --watch 27 28# 生成覆盖率报告 29npx vitest --coverage 30 31# 测试所有 utils 文件夹下的文件 32npx vitest "src/**/utils/**/*.test.ts" 33 34# 测试所有以 .test.ts 结尾的文件 35npx vitest "**/*.test.ts"
No vulnerabilities found.
No security vulnerabilities found.