Make a web app installable in a breeze
Anwar
Posted on November 13, 2023
Welcome to this tutorial on making your web app installable in a few simple steps.
Summary
- What is a progressive web app?
- Defining a web app manifest
- Registering a service worker
- Show an install button
- Conclusion
What is a progressive web app?
For a web app to be considered installable, a Progressive Web App (PWA), it must adhere to several criteria:
- It must define a manifest describing how the app behaves and interacts with the UI.
- It should register a Service Worker to enable offline browsing.
- It needs to have a responsive design suitable for small devices.
Other secondary criteria exist, but we'll focus on the essential information here.
Defining a web manifest
Start by adding a "manifest.json" file to your project's root:
{
"name": "Dev.to",
"short_name": "DEV",
"start_url": "/",
"display": "standalone",
"icons": [
{
"src": "images/touch/homescreen48.png",
"sizes": "48x48",
"type": "image/png"
}
}
- The "start_url" determines the URL shown when launching the app.
- The "display" specifies how the browser renders the UI when launching the app.
Refer to the manifest MDN documentation for a comprehensive list of configuration options..
Include the manifest file in your HTML:
<!DOCTYPE html>
<html>
<head>
<!-- ... !-->
<link rel="manifest" href="manifest.json" />
</head>
<body>
<!-- ... -->
</body>
</html>
Registering a service worker
Service Workers introduce powerful caching patterns for fine-grained control over how the browser handles requests. Let's implement the simple Network First pattern using Workbox.js.
This pattern tells the browser:
If you encounter a resource, wether it be an image, an HTML document, or anything, if the connectivity is on, grab the content of the resource from the server and store it in the cache.
If the network is off, and the resource is present in the cache, grab it from there, else behave like usual.
You can learn more on all the various caching strategies on the Workbox.js documentation about caching strategies.
Install the library:
npm install workbox-core workbox-routing workbox-strategies
Create a "service-worker.js" file:
const { clientsClaim } = require("workbox-core");
const { registerRoute } = require("workbox-routing");
const { NetworkFirst } = require("workbox-strategies");
clientsClaim();
registerRoute(
/.*/u,
new NetworkFirst({
cacheName: "nf-v1",
})
);
Update the "app.js" entry point to start the service worker:
if (navigator.serviceWorker instanceof ServiceWorkerContainer) {
navigator.serviceWorker.register("/service-worker.js", { scope: "/" });
}
Include the script in your HTML:
<!DOCTYPE html>
<html>
<head>
<!-- ... !-->
<link rel="manifest" href="manifest.json" />
</head>
<body>
<!-- ... -->
<script type="text/javascript" src="app.js"></script>
</body>
</html>
Show an install button
To make your web app more discoverable, register it on Store.app. This platform can increase your app's visibility, and they provide a convenient install modal.
Install the NPM package:
npm install @storedotapp/pwa-install-dialog
Import the code in your main entry javascript file:
require("@storedotapp/pwa-install-dialog");
if (navigator.serviceWorker instanceof ServiceWorkerContainer) {
navigator.serviceWorker.register("/service-worker.js", { scope: "/" });
}
Add a button to your HTML for users to install the app:
<!DOCTYPE html>
<html>
<head>
<!-- ... !-->
<link rel="manifest" href="manifest.json" />
</head>
<body>
<button id="install-button">Install the app</button>
<pwa-install-dialog id="install-dialog" app="fitness-app" theme="dark"></pwa-install-dialog>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
Register an "onClick" listener to show the modal when clicking the button:
require("@storedotapp/pwa-install-dialog");
if (navigator.serviceWorker instanceof ServiceWorkerContainer) {
navigator.serviceWorker.register("/service-worker.js", { scope: "/" });
}
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById("install-button");
if (button instanceof HTMLButtonElement) {
button.addEventListener("click", () => {
const dialog = document.getElementById("install-dialog");
if (dialog instanceof HTMLElement) {
dialog.show();
}
});
}
});
Conclusion
In just a few lines of code, we've transformed a website or web app into an installable web app. The evolution of the web into a platform with capabilities rivaling native apps is truly fascinating.
Installable web apps are shaping the future for a seamless, unified experience across all devices, offering lightweight, capable, and rich applications.
One limitation with the actual setup is that our app will still display the "install the app" button even if the app is installed (e.g. displayed as a standalone app).
Let us improve it by hiding the button if the app is already installed.
Create an "app.css" file with the following code:
@media all and (display-mode: standalone) {
#install-button {
display: none;
}
}
Now, only users who haven't installed your app will see the install button.
You can see this in action as I implemented it on Predzo.
I hope this tutorial has helped you understand PWAs better and demonstrated how easy it is to create an outstanding offline-ready installable web experience.
Happy web building!
Cover image by Roberto Nickson from Pexels.
Posted on November 13, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.