My MPA Journey...
Step 4 - Make the "Hello Gopher" a PWA
Progressive Web App
A PWA is still just a website, but with a few extra files it can behave like an installed desktop or mobile app. It launches in its own window, has an icon, and feels more “native” while still being 100% web based.
This section shows how to prepare your MPA for PWA. It builds directly on Step 3, adding only a few small refinements. Note that this is a minimal setup and it can be further enhanced.
1. Folder Structure for PWA
The structure is almost the same as Step 3. Except for a new folder "pwa" and one extra
javascript file. The Go init.go is already prepared for this by serving some file from the
root.
── go/
└── hello3/
└── main/
├── assets/
│ ├── css/
│ │ ├── base.css
│ │ └── fonts.css
│ ├── favicons/
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon-96x96.png
│ │ ├── favicon-192x192.png
│ │ ├── favicon.ico
│ │ └── favicon.svg
│ ├── fonts/
│ │ ├── source-sans-pro-v14-latin-300.woff
│ │ ├── source-sans-pro-v14-latin-300.woff2
│ │ ├── source-sans-pro-v14-latin-600.woff
│ │ ├── source-sans-pro-v14-latin-600.woff2
│ │ ├── source-sans-pro-v14-latin-regular.woff
│ │ └── source-sans-pro-v14-latin-regular.woff2
│ ├── img/
│ │ ├── gopher.jpg
│ │ └── gvp.jpg
│ ├── js/
│ │ ├── pwa.jpg <-- new pwa functions
│ │ └── init.js
│ ├── pwa/ <-- new folder
│ │ ├── service-worker.js <-- new js
│ │ ├── site.manifest <-- new manifest document
│ │ ├── manifest-192x192.png <-- new pwa icon 1
│ │ └── manifest-512x512.png <-- new pwa icon 2
│ ├── seo/
│ │ ├── robots.txt
│ │ └── sitemap.xml
│ └── tmpl/
│ ├── components/
│ │ ├── httphead.html
│ │ └── httpend.html
│ └── pages/
│ ├── home.html
│ └── gvp.html
│
├── go.mod
├── main
├── main.go
└── init.go
2. Create the manifest file
The web application manifest defines the app's name, icons, colors, start URL and scope. It is essentially the “instruction file” for your PWA.
{
"id": "/",
"name": "mpa.go4webdev",
"short_name": "GoMPA",
"icons": [
{
"src": "/pwa/manifest-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/pwa/manifest-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"start_url": "./",
"display": "standalone",
"display_override": ["standalone", "minimal-ui"],
"scope": "/"
}
3. Create the service-worker
A minimal service worker that activates immediately and takes control of all pages.
// activate immediately after installation
self.addEventListener('install', event => {
self.skipWaiting();
});
// take control of all pages immediately
self.addEventListener('activate', event => {
clients.claim();
});
4. Register the service-worker
This small JavaScript snippet enables PWA features.
/let deferred_prompt = null;
// init pwa service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js');
}
// Listen for the beforeinstallprompt event
window.addEventListener('beforeinstallprompt', (event) => {
event.preventDefault();
deferred_prompt = event;
});
// action triggered after click on a button
function install_app() {
if (!deferred_prompt) return;
deferred_prompt.prompt();
deferred_prompt = null;
}
5. Supported browsers
Most Chromium based browsers support full installation on desktop (Chrome, Edge, Brave etc). Opera, however does not support PWA as standalone apps. Safari supports installation on macOS and iOS, but uses its own UI instead of the standard install prompt. Firefox does not support installation on desktop.
In practice, this still covers the vast majority of users, and everyone else simply uses the site in a browser as usual.
6. Install the PWA
The PWA should not install automatically. Instead, offer it as a friendly option. Create a button that triggers the install_app() function in pwa.js.