PWA with Next.js
Tags: nextjs, pwa, beginners, react
Published: 2022-03-24 17:28:06


## What is PWA?

PWA stands for Progressive Web Apps. A PWA Web App can be installed as an Application on any device and work as a Native App on that platform. 

Earlier you had to maintain separate codebase for Web App, Android App and IOS App. But now using PWA you can turn any of your existing Web App or Website into Installable App and use it on any Platform. How cool! 

## Benefits of PWA?

1. You can use it as a Native App.
2. Super Fast and reliable.
3. Provides Offline Support.
4. Install directly from Website or Distribute as a SDK.
5. Cheaper to Build and Deploy.

## Examples of PWA

Twitter is an amazing example of PWA. Head to [https://twitter.com/](https://twitter.com/compose/tweet) and notice an icon appearing on the right on the URL box. This icon suggests that the Twitter Website is installable. Go ahead and install it. Now no matter if you are on your phone or computer you can see a twitter app on your screen. Open it. As you can see, you are getting a Native App like experience from a website. You can also use native app features like upload pictures and videos. 

## Convert your Next.js App into a PWA:

So lets start by adding PWA features to our existing Next.js App. If you are not having a ready project you can clone this Repository. This GitHub repository has two branches, make sure you clone the starter one. 

[GitHub - anuraggharat/Next-PWA-Demo at starter](https://github.com/anuraggharat/Next-PWA-Demo/tree/starter)

Or just run this command to clone the repository in the terminal.

```bash
git clone -b starter https://github.com/anuraggharat/Next-PWA-Demo.git
```

### Installing necessary dependencies

 Open the terminal inside your app and install `next-pwa`.

```bash
npm i next-pwa
```

### Generate Manifest file

A Manifest file is a JSON file which contains Meta data and icons about your application. You can write your own `manifest.json` file or you can even generate your file using an online tool. I’ll choose a tool here. Below is a list of all Online manifest generators, in this tutorial I am choosing the first one.

[https://www.simicart.com/manifest-generator.html/](https://www.simicart.com/manifest-generator.html/)

[https://manifest-gen.netlify.app/](https://manifest-gen.netlify.app/)

[https://app-manifest.firebaseapp.com/](https://app-manifest.firebaseapp.com/)

Add various details of your App like Name, Short Name, Theme Color and description. 

You can choose which type of display you want for you App. Browser makes it open in a separate browser, Standalone makes it looks like a native App. Full Screen display type makes the app open in Full screen mode and Minimal UI type is similar to Native app but some browser features are retained.


![Manifest file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fs38dpmfocfltdh1pjcq.png)

For your App to be recognized it should have icons of fixed sizes. I have downloaded a simple icon which I will use here for demo purpose. Try selecting an icon of size 512px. Once you have uploaded the icon, click on generate. This will give you a zip folder , extract all the content of the folder and copy all the contents inside the folder to your public directory inside your App. Rename manifest file to `manifest.json`. 

This is how your folder structure should look like.


![Folder Strucuture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jrxdvf6pk0hs9d46pxtb.png)

Your manifest file should be similar to this:

```bash
{
    "theme_color": "#3579f6",
    "background_color": "#ffffff",
    "display": "standalone",
    "scope": "/",
    "start_url": "/",
    "name": "Next-PWA",
    "short_name": "Next-PWA",
    "description": "A Demo for Next-PWA",
    "icons": [
        {
            "src": "/icon-192x192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "/icon-256x256.png",
            "sizes": "256x256",
            "type": "image/png"
        },
        {
            "src": "/icon-384x384.png",
            "sizes": "384x384",
            "type": "image/png"
        },
        {
            "src": "/icon-512x512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ]
}
```

### Create _document.js file

Now create a `_document.js` file in your pages directory and paste the following code. **`document.js` file is a special file in next.js just like _app.js. So if you have used Next.js you know we don’t write `<body>,<script>` and `<head>` tags by ourself. But if you go inside the inspector in browser you can see a whole bunch of script, link tags along with body and head tags. All these tags are generated by Next.js for us. `_document.js` allows us to control these tags ourself. So if you wish to add a link to external CSS or a script tag referencing a animation JS library you can create a `_document.js` file add them there. Here we are using `_document.js` file to reference our manifest files and icons. 

> `_document.js` file is loaded and run on server so don’t add event handlers here.
> 

```jsx
import Document, { Html, Head, Main, NextScript } from "next/document";

class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          <link rel="manifest" href="/manifest.json" />
          <link rel="apple-touch-icon" href="/icon.png"></link>
          <meta name="theme-color" content="#fff" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;
```

### Making Configuration in next.config.js file:

Next.js provides a default configuration file where we can set all our configurations. Open the next.config.js file and paste the following code.

```jsx
const withPWA = require("next-pwa");

module.exports = withPWA({
  pwa: {
    dest: "public",
    register: true,
    skipWaiting: true,
  },
});
```

### Make a Local build and test the PWA:

Once you have completed writing the configurations we can test the App. To test the PWA locally lets first create a new build. Stop the terminal and use this command to create a build:

```bash
npm run build
```

Once the build is created you would see a couple of files in your public folder. 

`sw.js` and `workbox-1846d813.js`

`sw.js` file is a Service Worker file. Service Worker is used in performing Caching, Background sync, Providing Native features and Offline Support. Workbox file is used to perform caching of assets.

Ok so you have created a new build now lets run this build locally. 

```bash
npm run start
```

Head over to [localhost:3000](http://localhost:3000) and in the right corner of URL box you can see a installable icon. Click on the icon. Now you can search for the App in your computer and run it. 

### Adding favicon to your website

A favicon is a small icon displayed on the left of the website title browser. This icon gives identity to your website. Currently your website has default next.js favicon lets change and ours. Head over to favicon generator website. 

[favicon-generator.org](http://favicon-generator.org/) 

[https://favicon.io/favicon-converter/](https://favicon.io/favicon-converter/)

Upload our icon which we selected earlier and convert it into a favicon. Download the zipped folder, unzip it, find the favicon.ico from the folder and replace it with the favicon from our projects public folder. Ignore all the other files from unzipped folder.

Now before we host our application lets finish some final configuration. Now the files generated by the build command aren’t necessary to be pushed on GitHub. Because these files are auto generated files and will be generated again every time we build the App. So when we deploy to a hosting platform, the platform will generate the files for us using latest configurations. So lets add these autogenerated files in `.gitignore` file. If you don’t already know `.gitignore` file tells git which files to ignore while committing a new commit.

```bash
# Auto Generated PWA files
**/public/sw.js
**/public/workbox-*.js
**/public/worker-*.js
**/public/sw.js.map
**/public/workbox-*.js.map
**/public/worker-*.js.map
```

And along with that we also with to disable PWA in development mode while we work on our App. For that we will update our next.config.js file to this

```jsx
const withPWA = require('next-pwa')

module.exports = withPWA({
  reactStrictMode: true,
  pwa:{
    dest:"public",
    register:true,
    skipWaiting:true,
    disable:process.env.NODE_ENV === 'development'
  }
});
```

We have added a disable as true if the environment is Development. And yeah that’s all you need to do to add PWA to a basic Next.js App. Now you can host your App on your favorite hosting platform and check how it works on mobile devices! 

Here’s what the final App looks in my phone!

Final Demo here. [https://next-pwa-demo-eight.vercel.app/](https://next-pwa-demo-eight.vercel.app/)


![PWA app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qg1lvxu9s4raykzshr8b.jpg)

That was how you can convert you Next.js website into a PWA App. Thanks for reading! If you love such content make sure you follow me on [twitter](https://twitter.com/anurag_gharat). I post regular content on Web Development and Programming.