DEV Community

Cover image for PWA with Next.js
Anurag Gharat
Anurag Gharat

Posted on

PWA with Next.js

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/ 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

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

git clone -b starter https://github.com/anuraggharat/Next-PWA-Demo.git
Enter fullscreen mode Exit fullscreen mode

Installing necessary dependencies

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

npm i next-pwa
Enter fullscreen mode Exit fullscreen mode

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://manifest-gen.netlify.app/

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

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

Your manifest file should be similar to this:

{
    "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"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

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.

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;
Enter fullscreen mode Exit fullscreen mode

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.

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

module.exports = withPWA({
  pwa: {
    dest: "public",
    register: true,
    skipWaiting: true,
  },
});
Enter fullscreen mode Exit fullscreen mode

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:

npm run build
Enter fullscreen mode Exit fullscreen mode

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.

npm run start
Enter fullscreen mode Exit fullscreen mode

Head over to 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

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.

# 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
Enter fullscreen mode Exit fullscreen mode

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

const withPWA = require('next-pwa')

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

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/

PWA app

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. I post regular content on Web Development and Programming.

Top comments (5)

Collapse
 
emolr profile image
Emil Møller

Thanks for writing this article, it was really helpful.

I just want to share for the next person reading this article that next-pwa has changed a bit so the next.config.js should be:

const withPWA = require('next-pwa');

module.exports = withPWA({
  dest: 'public',
  register: true,
  skipWaiting: true,
  disable: process.env.NODE_ENV === 'development',
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
luismartinezs profile image
Luis Martinez Suarez

I think it would be more like this:

const withPWA = require('next-pwa');

const config = {
// your next config...
}

module.exports = withPWA({
  dest: 'public',
  register: true,
  skipWaiting: true,
  disable: process.env.NODE_ENV === 'development',
})(config);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
allex_ profile image
Alexei

Its working only in production but not in preview, do someone know how to fix it?
Image description

Collapse
 
leandro_nnz profile image
Leandro Nuñez

Awesome article. Thanks!!!

Collapse
 
neurologialogic profile image
Patrick Kwon

your welcome