Adding PWA To Next.js App Simple Guide(part2)

Progressive Web Applications (PWAs) are apps built with web technologies that we probably all know and love, like HTML, CSS, and JavaScript. But they have the feel and functionality of an actual nativ...

#Next.js #PWA #dev #javascript #Android #ISO

In this article, we will show how to add PWA to Next.js App.

What is next-pwa?

next-pwa is a plugin for Next.js that allows you to create a progressive web app with it.

With it, building a PWA is simply painless, just drop withPWA into your next.config.js and you are already good to go!

It is also really configurable as it uses Workbox under the hood to build the service worker.

Install next-pwa

npm i @ducanh2912/next-pwa && npm i -D webpack

Step 1: Wrap your Next config with withPWA:

Update or create your next.config.js with

const withPWA = require("@ducanh2912/next-pwa").default({
  dest: "public",

module.exports = withPWA({
  // Your Next.js config

If your deployment platform requires your production image's size to not exceed a certain limit, you can also install @ducanh2912/next-pwa as one of your devDependencies and do this:

const {
} = require("next/constants");

/** @type {import("next").NextConfig} */
const nextConfig = {
  reactStrictMode: true,

module.exports = (phase) => {
    const withPWA = require("@ducanh2912/next-pwa").default({
      dest: "public",
    return withPWA(nextConfig);
  return nextConfig;

After running next build, this will generate two files in your public directory: workbox-*.js and sw.js, which will automatically be served statically.

Step 1.5: Next.js < 9

If you are using Next.js >= 9, then skip the section below.

Otherwise, you'll need to pick one of the two options below before continuing.

Option 1: Hosting static files

Copy files to your static file hosting server, so that they are accessible from the following paths: and*.js.

An example is using Firebase hosting service to host those files statically. You can automate the copying step with scripts in your deployment workflow.

Option 2: Using a custom server:

example server:

const { createServer } = require("http");
const { join } = require("path");
const { parse } = require("url");
const next = require("next");

const dev = process.env.NODE_ENV !== "production";
const hostname = "localhost";
const port = 3000;

const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  createServer((req, res) => {
    const parsedUrl = parse(req.url, true);
    const { pathname } = parsedUrl;
    if (
      pathname === "/sw.js" ||
    ) {
      const filePath = join(__dirname, ".next", pathname);
      app.serveStatic(req, res, filePath);
    } else {
      handle(req, res, parsedUrl);
  }).listen(port, () => {
    console.log(`> Ready on http://${hostname}:${port}`);

Step 2: Add a manifest.json file:

Create a manifest.json file in your public folder:

  "name": "My awesome PWA app",
  "short_name": "PWA App",
  "icons": [
      "src": "/icons/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
      "src": "/icons/android-chrome-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
  "theme_color": "#FFFFFF",
  "background_color": "#FFFFFF",
  "start_url": "/",
  "display": "standalone",
  "orientation": "portrait"

Step 3: Add <meta /> and <link /> tags to your <head />

import type { Metadata, Viewport } from "next";

const APP_NAME = "PWA App";
const APP_DEFAULT_TITLE = "My Awesome PWA App";
const APP_TITLE_TEMPLATE = "%s - PWA App";
const APP_DESCRIPTION = "Best PWA app in the world!";

export const metadata: Metadata = {
  applicationName: APP_NAME,
  title: {
    default: APP_DEFAULT_TITLE,
    template: APP_TITLE_TEMPLATE,
  description: APP_DESCRIPTION,
  manifest: "/manifest.json",
  appleWebApp: {
    capable: true,
    statusBarStyle: "default",
    // startUpImage: [],
  formatDetection: {
    telephone: false,
  openGraph: {
    type: "website",
    siteName: APP_NAME,
    title: {
      default: APP_DEFAULT_TITLE,
      template: APP_TITLE_TEMPLATE,
    description: APP_DESCRIPTION,
  twitter: {
    card: "summary",
    title: {
      default: APP_DEFAULT_TITLE,
      template: APP_TITLE_TEMPLATE,
    description: APP_DESCRIPTION,

export const viewport: Viewport = {
  themeColor: "#FFFFFF",

finally if was useful add comments and share

This website uses cookies to enhance your browsing experience, analyze site traffic, and serve better user experiences. By continuing to use this site, you consent to our use of cookies. Learn more in our cookie policy

Explore the latest insights, articles,free components, and expert advice on programming and software development

© Copyright 2024 MED DAKIR. All rights reserved./privacy policy