PWA with MERN Stack is not so hard…!(beginner guide)
What is PWA?
PWA stands for Progressive Web App. It is simply a web application but acts as a native app with almost all native app features like push notifications, offline mode, etc. It installs in all operating systems like Android, iPhone, mac, Linux, and windows.
In the present world, the download of apps per day decreases, and the use of websites increases. Because the maximum smartphone user have not much storage to install so many apps on their phone. That’s why they use websites.
That’s why almost all industries or institutes build their own website rather than native ones. But if any institute needs to develop their app, then they start to build their own app from scratch. But still, they have a website…! If only such a technology existed to convert this website into a native app, then will more efficient and profitable for business and industry.
To solve this problem PWA comes over. It is a web app with all native app features..!
Only one code run as a website and native app overall operating systems.
This is our future. So we need to learn PWA for better solutions for the future world.
Now, let’s know some more features of PWA:
- Build a website using HTML, CSS & JavaScript and run in browsers & all operating systems.
- Almost all native app features are present in PWA like push notifications.
- You can easily use this app offline and automatically refresh it and get updated data from the server when it goes online.
- It reduced installation friction.
- Full responsiveness and browser compatibility.
- Discoverability and easy installation.
How to implement PWA on a website?
To implement PWA on any website we need to work with a service worker. As service workers, we can access almost all native system features available in the hardware of a device.
What is service worker?
According to the developer.mozila: Service workers essentially act as proxy servers that sit between web applications, the browser, and the network (when available). A service worker is an event-driven worker registered against an origin and a path. It takes the form of a JavaScript file that can control the web page/site that it is associated with, intercepting and modifying navigation and resource requests, and caching resources in a very granular fashion to give you complete control over how your app behaves in certain situations (the most obvious one being when the network is not available). Read more…
Now it is time to register service-worker in our web app.
How to install service worker in react js?
In general service worker works on HTTPS for security purpose. But if you want to work with a service worker in the development mood then you need to install it from the inside react component. That’s why we need to create a file in the src folder as swDev.js. For work with service worker, a file will create in a public folder as sw.js.
Now in the swDev.js file, we check for the service worker in the browser, and if present then calls the service worker.
As we know the main service worker file is in the public folder which is sw.js. So, if our browser supports service worker then we call the sw.js file from the swDev.js file.
In this code, we see that if service worker is present then we register our app with service worker.
Now call this function inside of App.js / index.js component. I call it App.js.
In this code serviceWorkerRenderRef is nothing but to prevent 2-time render of useEffect in react 18.0 version. All of you know that in the 18 version of react useEffect automatically renders 2times with empty dependency.
Ok. Now we got the result that is
We finally register our app with service worker..!! Yeaaaa…..!!!😎
Now, let’s write some code inside the sw.js file to use the service worker in our app. 1st off all we need to store the pages of our application inside the cache. That’s why let’s create a cache for our app.
How to create a cache and how store web pages inside the cache?
1st of all, declare the cache name of our app. Suppose cacheName = “v-1”. Then we need to store all pages in the cache. That’s why we need to call the “install” event and create a cache and store all pages that you need to render in-app offline mode.
In cache.addAll method we include all pages that we want to store in the cache to load offline. 1st 4 URLs are required URLs to load any react project.
“/” is the Home page URL and other URLs are specific page URLs. I hope you understand this.
How do get those page cache offline?
First of all, we need to check the network mode. Because if we are in online mode then we want to load our updated webpage with updated data which are come from the server. If the mode is offline then we want to load the cache data so that, our web app works correctly in offline mode without any error.
That’s why we check the networking mode with the navigator.onLine method.
For that addEventListener in our app to fetch cache data of our web app.
Now check the result on the browser Network tab we see that in online mode all page load dynamically.
But in offline mode, we saw that…
We see that all pages are loaded from the sw.js file. So, we successfully make a progressive web app(PWA) with the offline mode feature.
One most important features of a PWA has pushed notification. Let’s talk about push notifications.
How do push notifications in the PWA app?🔔
To push notifications from the server we need the apps vapidPublicKey and vapidPrivateKey. To get vapidPublicKey we need to install a package web-push in the server. Then generate the vapidPublicKey and vapidPrivateKey. We need the same vapidPublicKey and vapidPrivateKey in server and client because by using that server configure the web-push configuration and push notification to the client. We should store these keys in a .env file.
Generate vapid keys in the server
Store them in the .env file, because that's sensitive data.
Now let’s build the functionality to send subscription info and browser endpoint to the server so that the server can send notifications to this specific browser.
Let’s go to swDev.js file and update the swDev() function like below,
1st off all we need to call pushManager with applicationServerKey to get subscription data and pass it to the server. How to get applicationServerKey? That we get this by using vapidPublicKey and converting this key into urlBase64ToUint8Array and that is our applicationServerKey.
This code is also found in the web-push package description. You can check there as well.
Now let’s refresh the react app, as you remember we call the swDev() function inside useEffect hook. So for 1st time render client-side automatically send a request to the server with browser endpoints and other information to send server notification to the client. So finally we get our browser information. Now you can store this data inside DB to use it at any time to send the notification. You should store this data in encrypted format as it is sensitive data.
Another reason to call swDev() function inside useEffect is if you want to store this data in DB then you can pass userId/use-email to identify the browser of a specific user. Otherwise, you also can call swDev() function below the index.js file.
How to send notifications from the server?
From the server, we can access the browser information and now we need to configure the web-push package.
1st of all, we need to set setVapidDetails in web-push. Then set options with all information of VapidDetails to check the browser to send the notification.
Code is given below,
The standard format of notification data is
- Title (title of a notification)
- Body (body text of a notification)
- Other data depend on your app requirement.
Now if you are confused about how to write this code step by step I give you full code to write step by step.
How to get notifications to clientside?
Now it’s time to work with the service worker again…!! Go to the sw.js file. Write some code to get the notification. Add an event listener whose event name is “push” and get the event into the callback function. From the event, the data will be found which send from server to client.
Data = event.data.json();
After getting data we need to register our app with showNotification event and give data.title as 1st parameter of the event and in 2nd parameter passes an object. Inside the object we should pass data.body, icon(that you want to show in the notification), data object with URL, and actions(that are the button action of a notification).
After writing this code in the sw.js file we get a notification like that
For the action array display 2 button 1. View and 2. Close. Now, let’s see how to handle the click event of those buttons.
How to handle the click event of those buttons?
In Fig-20 we see that actions array in the 2nd parameter. That is actually the buttons. Inside actions array object has a title, which is shown in the notification as button text, action is defined as button action and URL means button click to go to the specific page.
Now we need to listen to an event listener where the event type is “notificationclick” and get an event where we get all passed data in action arrays. (Fig-20)
Then check the action type and play the action when the user clicks the specific button.
The code is given below,
To do that, 1st of all get clients from self.clients. Then fire notification close event in every button action. That’s why if write without condition. If the action has any link to show a page, then at first it checks if any tab opens with the same link..? If find then just open that tab/window. Otherwise, it forces the browser to open a new tab/window to show that link page.
That’s all about basic notification. But you can customize notifications more. Learn more about notification…
So that’s all about the basic setup of PWA with the MERN stack application. I try to learn you in the simplest way. Although the blog is too big I hope it will help you…!!! I hope you all understand that and it will be useful for you if you are new to PWA.
If that blog is of any use to you, feel free to leave a Clap and your valuable feedback.