You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

验证流程

  1. 清空Chrome缓存与Service Worker,重启浏览器
  2. 重新访问页面,确认订阅流程无控制台报错
  3. 检查subscribers.json是否正确保存订阅信息
  4. 触发通知发送,验证Chrome是否收到通知

内容的提问来源于stack exchange,提问作者Tijmi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:31:08