本文目录导读:

在 Laravel 中实现浏览器推送通知,强烈推荐使用 WebPush 协议,Laravel 生态中最常用的包是 laravel-notification-channels/webpush,它基于 W3C 的 Push API 和 Service Workers 实现标准化的浏览器推送。
为什么选择 WebPush?
核心优势
- 标准协议:基于 W3C Push API + Service Workers
- 跨平台兼容:支持 Chrome、Firefox、Edge、Safari 16.4+
- 无需 App Key:使用 VAPID(Voluntary Application Server Identification)认证
- 后台推送:即使浏览器关闭也能收到通知(依赖系统通知服务)
与替代方案对比
| 方案 | 适用场景 | 缺点 |
|---|---|---|
| WebPush | 标准浏览器推送 | 需要 Service Worker |
| Pusher Channels | 实时WebSocket通信 | 非推送通知,需页面打开 |
| Firebase Cloud Messaging (FCM) | 原生App + Web | Google服务依赖,国内受限 |
| SSE (Server-Sent Events) | 单向实时推送 | 非浏览器推送API |
在 Laravel 中实现 WebPush
安装包
composer require laravel-notification-channels/webpush
生成 VAPID 密钥
php artisan webpush:vapid
这会配置 .env 文件:
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:your-email@example.com
创建数据迁移
php artisan make:migration create_push_subscriptions_table
Schema::create('push_subscriptions', function (Blueprint $table) {
$table->id();
$table->morphs('subscribable');
$table->string('endpoint', 500)->unique();
$table->string('public_key', 100)->nullable();
$table->string('auth_token', 100)->nullable();
$table->string('content_encoding', 20)->nullable();
$table->timestamps();
});
前端实现(JavaScript + Service Worker)
注册 Service Worker:
// resources/js/app.js
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered', reg))
.catch(err => console.error('SW registration failed', err));
}
// 订阅推送
async function subscribeUser() {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('{{ $vapidPublicKey }}')
});
// 保存到服务器
await fetch('/api/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(subscription)
});
}
Service Worker (public/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();
if (event.notification.data.url) {
clients.openWindow(event.notification.data.url);
}
});
创建通知类
php artisan make:notification PushNotification
use NotificationChannels\WebPush\WebPushChannel;
use NotificationChannels\WebPush\WebPushMessage;
class PushNotification extends Notification
{
public function via($notifiable)
{
return [WebPushChannel::class];
}
public function toWebPush($notifiable, $notification)
{
return (new WebPushMessage)
->title('新消息通知')
->body('您有一条新消息')
->action('查看详情', 'view')
->data(['url' => route('messages.show', 1)]);
}
}
添加 Notifiable Trait 到 User 模型
use NotificationChannels\WebPush\HasPushSubscriptions;
class User extends Authenticatable
{
use HasPushSubscriptions;
}
发送通知
$user->notify(new PushNotification()); // 或批量发送 Notification::send($users, new PushNotification());
高级配置
自定义 Service Worker 路径
// config/webpush.php 'service_worker' => '/custom-sw.js',
设置通知超时
'guzzle' => [
'timeout' => 5,
'connect_timeout' => 5,
],
处理过期订阅
// 在订阅更新方法中
use NotificationChannels\WebPush\WebPushChannel;
public function updateSubscription(Request $request)
{
$user = $request->user();
$user->deletePushSubscriptions();
$user->updatePushSubscription($request->input('endpoint'), [
'public_key' => $request->input('keys.p256dh'),
'auth_token' => $request->input('keys.auth'),
]);
return response()->json(['success' => true]);
}
注意事项
HTTPS 要求
浏览器推送必须通过 HTTPS 或 localhost 使用
用户权限
- 用户必须主动授权通知权限
- 不支持静默推送
浏览器兼容性
- Chrome 50+ ✅
- Firefox 44+ ✅
- Edge 79+ ✅
- Safari 16.4+ ✅ (需要 macOS Ventura 13.3+)
国内特殊考虑
- 如果使用自建 Push Service,确保网络可访问
- 某些浏览器(如部分国产浏览器)可能不完全支持
是否推荐使用 WebPush?
强烈推荐,尤其是在以下场景:
- ✅ 需要离线推送通知(浏览器关闭也能收到)
- ✅ 标准 Web 应用,不需要原生 App 支持
- ✅ 跨平台兼容性要求高
- ✅ 预算有限,不希望依赖第三方推送服务
可能不适合的场景:
- ❌ 需要即时双向通信(用 WebSocket 更合适)
- ❌ 需要原生 App 推送(考虑 FCM/APNs)
- ❌ 用户群体主要使用旧版浏览器(< 2018 年版本)
对于标准的浏览器推送通知需求,WebPush 是 Laravel 生态中的最佳实践选择,它提供了完整的订阅管理、通知格式化和可靠送达机制,并且与 Laravel 的 Notification 系统完美集成。