通过一个超轻量化的 status.js 文件(仅控制时间逻辑),在活动开始前禁用按钮(置灰),活动开始时更新这个 JS 文件,利用 CDN 短缓存(1秒)的特性,让全网用户瞬间同步生效,无需刷新页面即可解锁按钮。
一、核心实现思路
这个方案的关键是极简的 JS 文件 + CDN 短缓存 + 前端轮询/即时加载,既保证千万级访问下的性能,又能做到秒级生效:
status.js仅暴露一个全局变量(如活动开始时间/状态),文件体积控制在几十字节内;- CDN 配置该文件缓存时间为 1 秒,保证更新后全网快速同步;
- 前端页面加载时立即请求该文件,通过判断全局变量控制按钮状态,可选轮询确保活动开始瞬间生效。
二、完整实现方案
1. 第一步:编写极简的 status.js 文件(核心控制文件)
这个文件是整个方案的核心,仅需一行代码,体积不到 50 字节,示例如下:
// 活动未开始状态(上线初期部署这个版本)
window.activityStatus = {startTime: 1740000000000, isActive: false};
// 活动开始后更新为这个版本(替换上面一行即可)
// window.activityStatus = {startTime: 1740000000000, isActive: true};
startTime:活动开始的时间戳(毫秒)(如1740000000000对应具体时间);isActive:活动是否已开始(布尔值,核心控制字段);- 注意:文件编码为 UTF-8,去除所有多余空格/注释,确保体积最小。
2. 第二步:CDN 配置(关键!确保1秒缓存+回源策略)
对 status.js 配置以下 CDN 规则(以阿里云CDN/腾讯云CDN为例):
# 核心配置(通过 CDN 控制台配置,非命令行)
1. 缓存规则:匹配文件路径 /*/status.js,设置缓存时间为 1 秒(max-age=1);
2. 回源策略:开启「缓存过期后回源」「忽略客户端缓存」;
3. 压缩:开启 Gzip/Brotli 压缩(进一步减小文件体积);
4. 预热:活动开始前无需预热,更新后 CDN 自动回源拉取最新版本。
3. 第三步:前端页面集成(控制按钮状态)
页面中加载 status.js 并控制按钮,代码极简且高性能:
<!-- 按钮元素(提前写好禁用样式) -->
<button id="activityBtn" class="btn-disabled">立即参与活动</button>
<!-- 第一步:加载 status.js(异步加载,不阻塞页面) -->
<!-- 第二步:控制按钮的核心逻辑(几十行代码) -->
// 1. 按钮样式(提前定义,避免JS频繁修改样式)
const style = document.createElement('style');
style.textContent = `
.btn-disabled {
background: #ccc;
cursor: not-allowed;
pointer-events: none;
opacity: 0.7;
}
.btn-active {
background: #f60;
cursor: pointer;
pointer-events: auto;
opacity: 1;
}
`;
document.head.appendChild(style);
// 2. 核心函数:更新按钮状态
function updateButtonStatus() {
const btn = document.getElementById('activityBtn');
if (!btn) return;
// 判断活动状态(兼容文件未加载/加载失败的情况)
const isActive = window.activityStatus?.isActive || false;
// 更新按钮样式和状态
if (isActive) {
btn.classList.remove('btn-disabled');
btn.classList.add('btn-active');
btn.disabled = false;
} else {
btn.classList.add('btn-disabled');
btn.classList.remove('btn-active');
btn.disabled = true;
}
}
// 3. 初始化+轮询(确保活动开始瞬间生效)
// 初始化:文件加载完成后立即执行
window.addEventListener('load', updateButtonStatus);
// 轮询:每1秒重新请求 status.js 并更新状态(核心!)
setInterval(() => {
// 动态创建 script 标签,强制重新请求(绕过浏览器缓存)
const script = document.createElement('script');
script.src = `https://your-cdn.com/status.js?t=${Date.now()}`; // 时间戳防缓存
script. updateButtonStatus; // 加载完成后更新按钮
script.onerror = () => console.warn('status.js 加载失败'); // 容错
document.body.appendChild(script);
// 加载后移除标签,避免DOM冗余
setTimeout(() => document.body.removeChild(script), 1000);
}, 1000); // 与CDN缓存时间一致,1秒轮询一次
4. 第四步:活动开始时的操作(全网秒级生效)
当活动开始时,你只需要:
- 将服务器上的
status.js文件内容替换为:window.activityStatus = {startTime: 1740000000000, isActive: true}; - 无需重启服务/刷新CDN,CDN会在1秒缓存过期后自动回源拉取最新文件;
- 前端页面每1秒轮询一次,拉取到最新状态后立即解锁按钮,全网用户无需刷新页面即可看到按钮变为可用状态。
三、极致优化(千万级访问场景)
-
减小轮询开销:
- 活动开始前可降低轮询频率(如10秒一次),活动开始前1分钟改为1秒一次;
- 示例代码:
let pollInterval = 10000; // 初始10秒轮询 const preStartTime = 1739999400000; // 活动开始前1分钟的时间戳 setInterval(() => { const now = Date.now(); // 活动开始前1分钟,改为1秒轮询 if (now >= preStartTime) pollInterval = 1000; }, 1000); // 动态调整轮询定时器 let timer = setInterval(() => { /* 轮询逻辑 */ }, pollInterval);
-
容错处理:
- 若
status.js加载失败,默认保持按钮禁用状态,避免误解锁; - 增加时间戳兜底判断(即使JS文件更新延迟,也能按时间解锁):
function updateButtonStatus() { const btn = document.getElementById('activityBtn'); const now = Date.now(); const startTime = window.activityStatus?.startTime || Infinity; const isActive = now >= startTime; // 时间戳兜底 if (isActive) { btn.classList.remove('btn-disabled'); btn.classList.add('btn-active'); btn.disabled = false; } else { btn.classList.add('btn-disabled'); btn.classList.remove('btn-active'); btn.disabled = true; } }
- 若
-
文件体积极致压缩: 最终的
status.js可压缩为以下形式(仅 45 字节):window.activityStatus={startTime:1740000000000,isActive:false}
总结
- 核心机制:通过极简的
status.js暴露活动状态,CDN 配置1秒缓存,前端1秒轮询拉取最新文件,实现按钮状态全网秒级同步; - 关键优化:时间戳兜底判断(防止JS文件更新延迟)、动态调整轮询频率(降低服务器压力)、容错处理(避免加载失败导致异常);
- 部署要点:活动开始前部署
isActive: false的版本,开始时替换为isActive: true,CDN 自动回源同步,无需额外操作。
注意:本文归作者所有,未经作者允许,不得转载