Localhost环境下Chrome浏览器Web Push通知无法触发问题求助
Chrome下Web Push通知失效问题排查与修复
问题背景
用Node.js开发的网站实现了Web Push通知功能,Opera GX中可正常运行,但Chrome 109.0.5414.120版本完全无法接收通知。因项目面向学校老师,而所有老师均使用Chrome,必须解决该问题。
相关代码
app.js
const express = require("express") const webpush = require('web-push') const app = express() app.use(express.json()); const path = require("path") app.use(express.static(path.join(__dirname, 'client'))) const publicKey = "BL2QpTNn-CZARUqJhm4tDPPful3TMIjugZdyi1WNIcaps21w7KJFy4cjilMNk-NbeEIwWVA5ddCXpOStd6RTuXA" const privateKey = "dWcFCcnNS-uBYS6GISodobLXht-9KpOQmeHh1h89T7w" webpush.setVapidDetails("mailto:thdegroote18@gmail.com", publicKey, privateKey) app.post("/subscribe", async (req, res) => { try { // 客户端传来的订阅信息 const subscription = req.body; subscribers.push(subscription); // 将新订阅者保存到文件 fs.writeFileSync("./subscribers.json", JSON.stringify(subscribers)); res.status(201).send("Subscription Saved"); } catch (error) { console.error(error); } }); const subscribers = require("./subscribers.json") const fs = require("fs") async function sendPushNotificaiton() { for (let i = 0; i < subscribers.length; i++) { const subscription = subscribers[i]; // 通知负载,可包含更多信息 const payload = { title: "Push Test", body: " Push Notification Message", icon: "https://blog.mensaiah.com/assets/round_logo.png", }; // 发送通知 await webpush.sendNotification(subscription, JSON.stringify(payload)); } } // 每10分钟发送一次通知 const durationInMillisecond = 60 * 10000 setInterval(sendPushNotificaiton,durationInMillisecond); const port = 1999 app.listen(port, () => { console.log(`server started on port ${port}`) })
client.js
const publicVapidKey = "BL2QpTNn-CZARUqJhm4tDPPful3TMIjugZdyi1WNIcaps21w7KJFy4cjilMNk-NbeEIwWVA5ddCXpOStd6RTuXA"; async function subscribeToPush() { console.log("Registering service worker..."); const register = await navigator.serviceWorker.register("/worker.js", { scope: "/" }); console.log("Service Worker Registered..."); console.log("Registering Push..."); const subscription = await register.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(publicVapidKey) }); console.log("Push Registered..."); console.log("Subscribing for Push ..."); await fetch("http://localhost:1999/subscribe", { method: "POST", body: JSON.stringify(subscription), headers: { "Content-Type":"application/json" } }); } function urlBase64ToUint8Array(base64String) { const padding = "=".repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) .replace(/\-/g, "+") .replace(/_/g, "/"); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; } if ('serviceWorker' in navigator) { subscribeToPush().catch(console.log); }
worker.js
self.addEventListener("push", e => { // 来自服务端的数据 const data = e.data.json(); console.log("Push Recieved..."); self.registration.showNotification(data.title, { body: data.body, icon: data.icon, }); });
排查与修复步骤
1. 规范HTTPS访问规则
Chrome对Web Push有严格的HTTPS要求(仅localhost为例外):
- 本地测试必须使用
localhost:1999访问,禁止用IP地址或自定义域名 - 部署环境必须配置有效HTTPS证书,否则Chrome会拒绝Push API调用
2. 重新生成标准VAPID密钥对
现有密钥可能存在格式问题,执行命令生成合规密钥:
npx web-push generate-vapid-keys
替换代码中publicKey和privateKey的值,确保客户端与服务端公钥完全一致。
3. 修复订阅存储的时序错误
app.js中订阅列表引入顺序错误,会导致初始订阅为空且首次订阅可能报错,调整代码顺序:
const fs = require("fs") const subscribers = require("./subscribers.json") // 之后再定义路由 app.post("/subscribe", async (req, res) => { // 原有代码逻辑 })
4. 添加通知发送的错误捕获与处理
当前代码未处理单个订阅的发送错误,若Chrome订阅过期或无效会导致整个循环中断,修改发送函数:
async function sendPushNotificaiton() { for (let i = 0; i < subscribers.length; i++) { const subscription = subscribers[i]; const payload = { title: "Push Test", body: " Push Notification Message", icon: "https://blog.mensaiah.com/assets/round_logo.png", }; try { await webpush.sendNotification(subscription, JSON.stringify(payload)); } catch (err) { console.error(`发送通知给订阅者 ${i} 失败:`, err); // 订阅过期则移除并更新文件 if (err.statusCode === 410) { subscribers.splice(i, 1); fs.writeFileSync("./subscribers.json", JSON.stringify(subscribers)); i--; // 调整索引避免跳过元素 } } } }
5. 验证Service Worker与通知权限
在Chrome开发者工具中检查:
Application > Service Workers:确认worker.js已注册并激活- 地址栏锁图标:确认通知权限已开启
Application > Notifications:查看是否有推送记录
6. 解决跨域请求限制
若前后端域名/端口不一致,添加CORS中间件:
const cors = require('cors') app.use(cors())
安装依赖:npm install cors
验证流程
- 清空Chrome缓存与Service Worker,重启浏览器
- 重新访问页面,确认订阅流程无控制台报错
- 检查
subscribers.json是否正确保存订阅信息 - 触发通知发送,验证Chrome是否收到通知
内容的提问来源于stack exchange,提问作者Tijmi
相关产品推荐
相关产品推荐

