If your project already has a service worker (sw.js) in the public directory, the php artisan webpush:prepare command will not overwrite the existing file to avoid losing already implemented functionality.
In this case, you will need to manually integrate the WebPush code into your existing service worker.
First, run the preparation command normally:
php artisan webpush:prepare
You will see a message informing that the service worker already exists and was skipped:
⚠ Service worker file already exists at: /path/to/public/sw.js. Skipping copy.
ℹ See documentation for more details on how to update it.
Now you need to add the following functionality to your existing service worker:
Add this code to your public/sw.js:
self.addEventListener("push", (event) => {
if (!(self.Notification && self.Notification.permission === "granted")) {
return;
}
const payload = event.data ? event.data.json() : {};
event.waitUntil(
self.registration.showNotification(payload.title, {
body: payload.body,
icon: payload.icon,
badge: payload.badge,
actions: payload.actions || [],
data: payload.data || {},
})
);
});
Also add this code to handle notification clicks:
self.addEventListener("notificationclick", (event) => {
const notification = event.notification;
notification.close();
if (event.action === "open") {
event.waitUntil(clients.openWindow(notification.data.action_url));
} else {
event.waitUntil(
clients.openWindow(notification.data.action_url || "/app")
);
}
});
Here's an example of how your service worker might look after integration:
"use strict";
// Your existing code...
const CACHE_NAME = "my-app-cache-v1";
const OFFLINE_URL = "/offline.html";
// WebPush code - Event listener for push notifications
self.addEventListener("push", (event) => {
if (!(self.Notification && self.Notification.permission === "granted")) {
return;
}
const payload = event.data ? event.data.json() : {};
event.waitUntil(
self.registration.showNotification(payload.title, {
body: payload.body,
icon: payload.icon,
badge: payload.badge,
actions: payload.actions || [],
data: payload.data || {},
})
);
});
// WebPush code - Event listener for notification clicks
self.addEventListener("notificationclick", (event) => {
const notification = event.notification;
notification.close();
if (event.action === "open") {
event.waitUntil(clients.openWindow(notification.data.action_url));
} else {
event.waitUntil(
clients.openWindow(notification.data.action_url || "/app")
);
}
});
// Rest of your existing code...
self.addEventListener("install", (event) => {
// Your installation logic...
});
self.addEventListener("fetch", (event) => {
// Your fetch logic...
});
self.addEventListener("activate", (event) => {
// Your activation logic...
});
After integrating the code, test if notifications are working:
php artisan webpush:test {user-id}
If notifications are not working:
.env fileIf you prefer an automated approach to integrate the WebPush listeners, you can use the merge command:
php artisan webpush:merge-listeners
This command will:
public/sw.js) exists$ php artisan webpush:merge-listeners
Merging WebPush listeners into existing service worker...
✔ WebPush listeners successfully merged into your service worker.
Your service worker now supports push notifications and notification clicks.
::: warning Important This command appends code to your existing service worker. If you later update the package, you may need to manually update the listener code or remove the old listeners and run the command again. :::
If you need to consult the original package files, they are located at:
vendor/andrefelipe18/filament-webpush/stubs/sw.jsvendor/andrefelipe18/filament-webpush/stubs/webpush.jsvendor/andrefelipe18/filament-webpush/stubs/listeners-webpush.js⚠️ Warning: Always backup your service worker before making changes, especially if it already contains important logic for your application's functionality.
💡 Tip: If you're not sure how to integrate the code, consider creating a new service worker for development/testing in a separate environment first.
How can I help you explore Laravel packages today?