-
-
Save m5lil/a928ac03ab063eb73b8431a8f5818488 to your computer and use it in GitHub Desktop.
Simple Laravel + Vue + Laravel Mix + Firebase Notification (PWA, Offline)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FILE PATH: /resources/js/app.js | |
require('./bootstrap'); | |
// Import Service Worker Registry | |
require('./extensions/sw-registry'); | |
import Vue from 'vue'; | |
... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FILE PATH: /resources/js/firebase.js | |
import * as firebase from 'firebase/app'; | |
require('firebase/messaging'); | |
const initializedFirebaseApp = firebase.initializeApp({ | |
messagingSenderId: '#####' | |
}); | |
let messaging = null; | |
if (firebase.messaging.isSupported()) { | |
messaging = initializedFirebaseApp.messaging(); | |
messaging.usePublicVapidKey( | |
'#####' | |
); | |
messaging.onMessage((payload) => { | |
const notificationTitle = payload.notification.title; | |
const notificationOptions = { | |
body: payload.notification.body, | |
icon: '/android-chrome-144x144.png', | |
}; | |
if (!('Notification' in window)) { | |
console.log('This browser does not support system notifications'); | |
} else if (Notification.permission === 'granted') { | |
let notification = new Notification(notificationTitle,notificationOptions); | |
notification.onclick = function(event) { | |
event.preventDefault(); | |
window.open(payload.notification.click_action , '_blank'); | |
notification.close(); | |
}; | |
} | |
}); | |
} | |
export { messaging }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FILE PATH: /resources/js/service-worker.js | |
importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'); | |
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-app.js'); | |
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-messaging.js'); | |
firebase.initializeApp({ | |
'messagingSenderId': '######' | |
}); | |
const messaging = firebase.messaging(); | |
messaging.setBackgroundMessageHandler(function(payload) { | |
const notification = JSON.parse(payload.data.data); | |
const notificationTitle = notification.title; | |
const notificationOptions = { | |
body: notification.body, | |
icon: '/android-chrome-144x144.png', | |
}; | |
return self.registration.showNotification(notificationTitle, | |
notificationOptions); | |
}); | |
if (workbox) { | |
// injected assets by Workbox CLI | |
workbox.precaching.precacheAndRoute([]); | |
// js/css files | |
workbox.routing.registerRoute( | |
/\.(?:js|css)$/, | |
new workbox.strategies.StaleWhileRevalidate({ | |
cacheName: 'static-resources', | |
}) | |
); | |
// // images | |
workbox.routing.registerRoute( | |
// Cache image files. | |
/\.(?:png|jpg|jpeg|svg|gif)$/, | |
// Use the cache if it's available. | |
new workbox.strategies.CacheFirst({ | |
// Use a custom cache name. | |
cacheName: 'image-cache', | |
plugins: [ | |
new workbox.expiration.Plugin({ | |
// Cache upto 50 images. | |
maxEntries: 50, | |
// Cache for a maximum of a week. | |
maxAgeSeconds: 7 * 24 * 60 * 60, | |
}), | |
new workbox.cacheableResponse.Plugin({ | |
statuses: [200] | |
}) | |
], | |
}) | |
); | |
const networkFirstHandler = new workbox.strategies.NetworkFirst({ | |
cacheName: 'dynamic', | |
plugins: [ | |
new workbox.expiration.Plugin({ | |
maxEntries: 10 | |
}), | |
new workbox.cacheableResponse.Plugin({ | |
statuses: [200] | |
}) | |
] | |
}); | |
const FALLBACK_URL = workbox.precaching.getCacheKeyForURL('/offline.html'); | |
const matcher = ({ event }) => event.request.mode === 'navigate'; | |
const handler = args => | |
networkFirstHandler | |
.handle(args) | |
.then(response => response || caches.match(FALLBACK_URL)) | |
.catch(() => caches.match(FALLBACK_URL)); | |
workbox.routing.registerRoute(matcher, handler); | |
self.addEventListener('message', function (event) { | |
console.log('user request for update... (' + event.data.action + ')'); | |
if (event.data.action === 'skipWaiting') { | |
self.skipWaiting(); | |
} | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FILE PATH: /resources/js/sw-registry.js | |
// (optional) If you using firebase notification | |
import { messaging } from 'firebase'; | |
let newWorker; | |
// Notify user if service worker file has changed.. and need to update | |
// in your blade file create this snippet for notification for example | |
// | |
// <div id="sw-snackbar">A new version of this app is available. Click <a id="reload">here</a> to update.</div> | |
// | |
function showUpdateBar() { | |
let snackbar = document.getElementById('sw-snackbar'); | |
snackbar.className = 'show'; | |
} | |
document.getElementById('reload').addEventListener('click', function(){ | |
newWorker.postMessage({ action: 'skipWaiting' }); | |
}); | |
if ('serviceWorker' in navigator) { | |
window.addEventListener('load', () => { | |
navigator.serviceWorker.register('/offline.js').then(reg => { | |
reg.addEventListener('updatefound', () => { | |
newWorker = reg.installing; | |
newWorker.addEventListener('statechange', () => { | |
switch (newWorker.state) { | |
case 'installed': | |
if (navigator.serviceWorker.controller) { | |
// Show update bar | |
showUpdateBar(); | |
} | |
break; | |
} | |
}); | |
}); | |
}).catch((err) => { | |
console.log('ServiceWorker registration failed: ', err); | |
}); | |
let refreshing; | |
navigator.serviceWorker.addEventListener('controllerchange', function () { | |
if (refreshing) return; | |
window.location.reload(); | |
refreshing = true; | |
}); | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const mix = require('laravel-mix'); | |
const WebpackShellPlugin = require('webpack-shell-plugin'); | |
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') | |
.BundleAnalyzerPlugin; | |
mix.setPublicPath('public'); | |
mix.sass('./resources/sass/app.scss', '/css/app.css'); | |
mix.js('./resources/js/app.js', '/js/webapp.js') | |
.extract(['axios', 'vue', 'accounting', 'vuex', 'vuex-router-sync', 'vue-router', 'vue-lazyload', 'vue-i18n', 'vue-events', 'vee-validate']) | |
.webpackConfig({ | |
output: { | |
chunkFilename: 'js/chunks/[name].js' | |
} | |
}); | |
if (mix.inProduction()) { | |
mix.webpackConfig({ | |
plugins: [new BundleAnalyzerPlugin()] | |
}); | |
mix.version(); | |
mix.disableNotifications(); | |
} | |
/** | |
* Publishing the assets | |
*/ | |
mix.webpackConfig({ | |
plugins: [ | |
new WebpackShellPlugin({ | |
onBuildEnd: [ | |
'npx workbox injectManifest workbox-config.js' | |
] | |
}) | |
] | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
// Path to be offline cache | |
'globDirectory': 'public/', | |
'globPatterns': [ | |
'/**/*.{css,ico,ttf,woff,svg,png,jpg,php,js,xml,webmanifest,json,txt,gif,md,html,scss,eot,woff2,swf,otf}', | |
'offline.html', | |
'mix-manifest.json', | |
], | |
'swDest': 'public/offline.js', | |
'globIgnores': [], | |
'swSrc': 'resources/js/service-worker.js' | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment