I just added pwa functionality to an older project at work. Although I haven't tested thoroughly and although my project wasn't an Angular project, this has worked so far:
Add a service worker. You'll need one that defines a fetch event listener. The one I use I found online. It looks like this:
// sw.js//Install stage sets up the offline page in the cache and opens a new cacheself.addEventListener('install', function(event){
var offlinePage = new Request('offline.html');
event.waitUntil(
fetch(offlinePage).then(function(response){
return caches.open('mesquite').then(function(cache){
console.log('[PWA Builder] Cached offline page during Install' + response.url);
return cache.put(offlinePage, response);
});
}));
});
//If any fetch fails, it will show the offline page.//Maybe this should be limited to HTML documents?self.addEventListener('fetch', function(event){
event.respondWith(
fetch(event.request).catch(function(error){
console.error('[PWA Builder] Network request Failed. Serving offline page ' + error);
return caches.open('mesquite').then(function(cache){
return cache.match('offline.html');
});
}));
});
Register the service worker:
// this javascript code runs on the the layout markup of a MVC NET app. if ("serviceWorker"in navigator) {
if (navigator.serviceWorker.controller) {
console.log("[PWA Builder] active service worker found, no need to register");
} else {
// Register the service worker
navigator.serviceWorker
.register("/sw.js", {
scope: "./"
})
.then(function (reg) {
console.log("[PWA Builder] Service worker has been registered for scope: " + reg.scope);
});
}
}
Instead of prompting the user to install the app, I show a download button so that the user can download it if they want to/when they want to. That logic looks like this:
const a2hsButton = document.querySelector('#a2hs');
if (a2hsButton) {
let deferredPrompt;
//a2hsButton.style.display = 'none';window.addEventListener('beforeinstallprompt', function (e) {
console.log("beforeinstall");
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
// Update UI to notify the user they can add to home screen
a2hsButton.style.display = 'block';
a2hsButton.addEventListener('click', function (e) {
// hide our user interface that shows our A2HS button// Show the prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
a2hsButton.style.display = 'none';
console.log('User accepted the A2HS prompt');
} else {
console.log('User dismissed the A2HS prompt');
}
deferredPrompt = null;
});
});
})
Hopefully it helps some. Checking out PWABuilder will help too.
Diego Bernal
Front-End Engineer
I just added pwa functionality to an older project at work. Although I haven't tested thoroughly and although my project wasn't an Angular project, this has worked so far:
fetchevent listener. The one I use I found online. It looks like this:// sw.js //Install stage sets up the offline page in the cache and opens a new cache self.addEventListener('install', function (event) { var offlinePage = new Request('offline.html'); event.waitUntil( fetch(offlinePage).then(function (response) { return caches.open('mesquite').then(function (cache) { console.log('[PWA Builder] Cached offline page during Install' + response.url); return cache.put(offlinePage, response); }); })); }); //If any fetch fails, it will show the offline page. //Maybe this should be limited to HTML documents? self.addEventListener('fetch', function (event) { event.respondWith( fetch(event.request).catch(function (error) { console.error('[PWA Builder] Network request Failed. Serving offline page ' + error); return caches.open('mesquite').then(function (cache) { return cache.match('offline.html'); }); })); });// this javascript code runs on the the layout markup of a MVC NET app. if ("serviceWorker" in navigator) { if (navigator.serviceWorker.controller) { console.log("[PWA Builder] active service worker found, no need to register"); } else { // Register the service worker navigator.serviceWorker .register("/sw.js", { scope: "./" }) .then(function (reg) { console.log("[PWA Builder] Service worker has been registered for scope: " + reg.scope); }); } }{ "name": "ProjectName", "short_name": "ProjectShortName", "description": "Description", "theme_color": "#00BCD4", "background_color": "#fafafa", "display": "standalone", "start_url": "/", "scope": "/", "prefer_related_applications": false, "icons": [ { "src": "Images/Logos/logo-sm.png", "sizes": "192x192", "type": "image/png" }, { "src": "Images/Logos/logo-lg.png", "sizes": "512x512", "type": "image/png" } ] }Reference manifest.json
// layout.html <link rel="manifest" href="/manifest.json">Instead of prompting the user to install the app, I show a download button so that the user can download it if they want to/when they want to. That logic looks like this:
const a2hsButton = document.querySelector('#a2hs'); if (a2hsButton) { let deferredPrompt; //a2hsButton.style.display = 'none'; window.addEventListener('beforeinstallprompt', function (e) { console.log("beforeinstall"); // Prevent Chrome 67 and earlier from automatically showing the prompt e.preventDefault(); // Stash the event so it can be triggered later. deferredPrompt = e; // Update UI to notify the user they can add to home screen a2hsButton.style.display = 'block'; a2hsButton.addEventListener('click', function (e) { // hide our user interface that shows our A2HS button // Show the prompt deferredPrompt.prompt(); // Wait for the user to respond to the prompt deferredPrompt.userChoice.then((choiceResult) => { if (choiceResult.outcome === 'accepted') { a2hsButton.style.display = 'none'; console.log('User accepted the A2HS prompt'); } else { console.log('User dismissed the A2HS prompt'); } deferredPrompt = null; }); }); })Hopefully it helps some. Checking out PWABuilder will help too.