移动端网页实现消息推送功能,核心依赖Web Push协议,HTML本身不直接处理推送逻辑,需要结合JavaScript的Push API和Notification API,配合服务端完成全流程配置。

实现移动端推送的核心前提
要实现该功能,需要满足两个基础条件:一是网页必须运行在HTTPS环境下,本地开发可使用localhost调试;二是浏览器需要支持Push API和Notification API,目前主流移动端浏览器基本都支持这两个特性。
前端HTML与JavaScript实现步骤
1. 申请推送权限
首先需要向用户申请消息推送权限,只有用户授权后才能进行后续订阅操作,相关代码如下:
// 申请通知权限
function requestNotificationPermission() {
if (!("Notification" in window)) {
console.log("当前浏览器不支持Notification API");
return;
}
// 如果已经授权,直接返回
if (Notification.permission === "granted") {
return Promise.resolve();
}
// 如果未授权,发起申请
return Notification.requestPermission().then(permission => {
if (permission !== "granted") {
throw new Error("用户拒绝了推送权限申请");
}
});
}
2. 注册Service Worker
Web Push依赖Service Worker在后台接收推送消息,需要先注册Service Worker文件,代码如下:
// 注册Service Worker
function registerServiceWorker() {
if (!("serviceWorker" in navigator)) {
throw new Error("当前浏览器不支持Service Worker");
}
return navigator.serviceWorker.register("/sw.js").then(registration => {
console.log("Service Worker注册成功", registration);
return registration;
});
}
3. 订阅推送服务
权限申请通过且Service Worker注册完成后,需要调用PushManager订阅推送,获取推送订阅信息并发送给服务端保存,代码如下:
// 订阅推送服务
function subscribePush(registration) {
// 这里替换为你的服务端公钥,需要是base64url格式
const publicKey = "你的VAPID公钥";
// 将公钥转换为Uint8Array格式
const applicationServerKey = urlBase64ToUint8Array(publicKey);
return registration.pushManager.subscribe({
userVisibleOnly: true, // 推送必须显示通知,不能静默推送
applicationServerKey: applicationServerKey
}).then(subscription => {
// 将订阅信息发送到服务端保存
return fetch("/save-subscription", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(subscription)
});
});
}
// 辅助函数:将base64url格式的公钥转换为Uint8Array
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;
}
4. Service Worker中处理推送消息
在根目录创建sw.js文件,用于接收服务端推送的消息并展示通知,代码如下:
// sw.js 文件内容
self.addEventListener("push", event => {
const data = event.data.json();
const options = {
body: data.body,
icon: "/icon.png", // 通知图标
badge: "/badge.png", // 小图标
data: {
url: data.url // 点击通知跳转的地址
}
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
// 处理通知点击事件
self.addEventListener("notificationclick", event => {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});
服务端配置说明
服务端需要完成两个核心工作:一是生成VAPID密钥对,公钥给前端使用,私钥用于推送时签名;二是保存前端的订阅信息,在需要推送时调用Web Push库向订阅地址发送消息。
以Node.js为例,使用web-push库实现推送的示例代码如下:
const webpush = require("web-push");
// 设置VAPID密钥,这里替换为你的实际密钥
const vapidKeys = {
publicKey: "你的VAPID公钥",
privateKey: "你的VAPID私钥"
};
webpush.setVapidDetails(
"mailto:admin@ipipp.com", // 联系邮箱
vapidKeys.publicKey,
vapidKeys.privateKey
);
// 推送消息的接口
app.post("/send-push", (req, res) => {
const subscription = req.body.subscription; // 从数据库获取的订阅信息
const payload = JSON.stringify({
title: "新消息提醒",
body: "你有一条新的待处理消息",
url: "https://ipipp.com/message"
});
webpush.sendNotification(subscription, payload).then(() => {
res.json({ success: true });
}).catch(err => {
console.error("推送失败", err);
res.json({ success: false });
});
});
常见问题说明
- 如果用户清除了浏览器缓存,Service Worker会被注销,需要重新引导用户完成订阅流程
- 不同浏览器的通知样式有差异,建议测试主流移动端浏览器的展示效果
- 推送内容需要符合平台规范,不能发送违规内容,否则会被浏览器拦截