Convert an existing website to a PWA
To convert an existing website to a PWA, first, you need to make your website responsive. Once you have done this, you only need two things: a “manifest.json” and a service worker. Let’s see what they are!
STEP 01: The Web App Manifest
A “manifest.json” file is a key component of a Progressive Web App (PWA). It provides important information about your web app to the browser, allowing it to be installed and launched like a native app on a user’s device. Here are some of the key attributes that can be included in a “manifest.json” file, along with a brief explanation of each one:
"name"
: This attribute specifies the name of your web app."short_name"
: This attribute specifies a shorter name for your app, which may be used in places where space is limited (such as on a user’s home screen)."start_url"
: This attribute specifies the URL where your app should start when launched."display"
: This attribute specifies how your app should be displayed to the user (e.g., “fullscreen,” “standalone,” or “minimal-ui”)."icons"
: This attribute specifies a list of icons to be used for your app, at different sizes and resolutions."theme_color"
: This attribute specifies the primary color of your app, which may be used in the browser’s UI when your app is launched."background_color"
: This attribute specifies the background color of your app."description"
: This attribute provides a brief description of your app, which may be used in places like app stores or search results."orientation"
: restrictions (it is unwise to change this from “any” without a hard technical limit)"scope"
: This specifies the set of URLs where the website will be active or interact with.
Where to add “manifest.json” file in your project?
For General Projects:
Place the “manifest.json” file in the root directory of your web app.
For React Projects:
Place the “manifest.json” file in the public folder of your project. The file will then be automatically included in the build when you run the npm run build
.
{ "name": "To Do List Application", "short_name": "TODO LIST", "theme_color": "#ffcbe4", "background_color": "#fa99ca", "display": "standalone", "scope": "/", "start_url": "/index.html", "description": "To do list for my tasks.", "orientation": "any", "icons": [ { "src": "/assets/images/logo-72x72.png", "type": "image/png", "sizes": "72x72" }, { "src": "/assets/images/logo-96x96.png", "type": "image/png", "sizes": "96x96" }, { "src": "/assets/images/logo-128x128.png", "type": "image/png", "sizes": "128x128" }, { "src": "/assets/images/logo-144x144.png", "type": "image/png", "sizes": "144x144" }, { "src": "/assets/images/logo-152x152.png", "type": "image/png", "sizes": "152x152" }, { "src": "/assets/images/logo-192x192.png", "type": "image/png", "sizes": "192x192" }, { "src": "/assets/images/logo-384x384.png", "type": "image/png", "sizes": "384x384" }, { "src": "/assets/images/logo-512x512.png", "type": "image/png", "sizes": "512x512" } ] }
If you noticed the /assets/images/logo-72x72.png
, that is the icon for the app. You can create your own using any tool of your choice or check out a generator like RealFaviconGenerator, which generates the tags and favicons that you need for your site.
Now, coming to generating icons. I strongly suggest using the App Manifest Generator, which works like a charm; it generates both “manifest.json” and icons.
IMPORTANT NOTE: Adding icons is a must; otherwise, the PWA standard will not work properly. Please remember that the icons should be in eight different sizes ranging from 72×72 to 512×512 to cater to various devices. Note that the icon sizes shown above are just an example.
Link “manifest.json” file with the “index.html” of your project
<link rel="manifest" href="/manifest.json"/>
Also, add a theme-color meta tag for improved PWA performance:
<meta name="theme-color" content="#FFE1C4"/>
|In your “index.html” file of the project, link the “manifest.json” file in the head tag.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></pre> <pre><link rel="manifest" href="manifest.json"> <meta name="theme-color" content="#FFE1C4"></pre> <pre></head></pre> <pre><body> <h1> Hi This is Muhib here </h1> </body> </html>
STEP 02: The Service Worker
After creating the “manifest.json” file, check whether the browser supports the service worker or not.
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('service worker registered')) .catch(err => console.log('service worker not registered', err)); }
You can do this by adding this script into your “app.js” file (your default running script) or you can also add it to the “index.html” of your general or React project with the <script>
tag like this.
The Service Worker is essentially a JavaScript file that runs separately from the main browser thread. With a Service Worker, you can cache or retrieve resources from the cache, deliver push messages, provide offline support, and enable background sync.
What does the “service_worker.js” file actually do?
Imagine a helper who works quietly behind the scenes to make your web app more powerful. This helper is the service worker, and it has three important stages: registration, installation, and activation. In the first stage, you let the web browser know where to find the helper, and it starts installing in the background. During the second stage, you can give the helper some tasks to do while it’s being installed. Once the helper is installed, it waits patiently in the third stage until there are no more pages using the old helper. Then, it wakes up and gets to work! This stage can also include additional tasks for the helper to perform. Overall, the service worker is crucial for adding cool features like offline functionality to your Progressive Web App.
We will add the “service_worker.js” file in the root folder of our directory.
Now, create the “service_worker.js” file.
const cacheName = 'to-do-list-v1'; const staticAssets = [ "/", '/index.html', '/manifest.json', '/Images/img.webp' ]; //INSTALL_EVENT self.addEventListener("install", async (e) => { const cache = await caches.open(cacheName); await cache.addAll(staticAssets); return self.skipWaiting(); }); //ACTIVATE_EVENT self.addEventListener("activate", async (evt) => { const cacheKeys = await caches.keys(); await Promise.all( cacheKeys .filter((key) => key !== cacheName) .map((key) => caches.delete(key)) ); }); //FETCH_EVENT self.addEventListener("fetch", async (e) => { const req = e.request; const url = new URL(req.url); if (url.origin === location.origin) { e.respondWith(cacheFirst(req)); } else { e.respondWith(networkAndCache(req)); } }); async function cacheFirst(req) { const cache = await caches.open(cacheName); const cached = await cache.match(req); return cached || fetch(req); } async function networkAndCache(req) { const cache = await caches.open(cacheName); try { const fresh = await fetch(req); await cache.put(req, fresh.clone()); return fresh; } catch (e) { const cached = await cache.match(req); return cached; } }
Install event
This event is fired when the service worker is first installed. During this event, the static assets that need to be cached are added to the cache, and the service worker is set to skip waiting so that it can be activated immediately.
Activate event
This event is fired when the service worker is activated. During this event, all the caches except the current one (in this case, “to-do-list-v1” cache) are deleted so that only the latest version of the cache is retained.
Fetch event
This event is fired whenever the application makes a network request. During this event, the service worker checks if the requested resource is available in the cache. If it is, the cached resource is returned. If it isn’t, the resource is fetched from the network and then cached so that it can be returned from the cache the next time it’s requested.
Congratulations, you were able to convert an existing website to a PWA. You can check it by going to the Lighthouse part of your website developer tools. Analyze it and check the PWA part.
BONUS POINTS:
To automatically generate the “service-worker.js” file, we will be using an NPM package called sw-precache
.
In the terminal:
npm install -g sw-precache
Once it is installed, run the below command, making sure you are in the same path as your project root directory:
sw-precache
For more information on Progressive Web Apps (PWAs), you can refer to these articles on devfum.com: