shadowwalker / next-pwa

Zero config PWA plugin for Next.js, with workbox 🧰
MIT License
3.84k stars 320 forks source link

Address bar showing up when installing as PWA #278

Open churichard opened 2 years ago

churichard commented 2 years ago

Summary

I have the scope set to /app in my next.config.js, and my start_url in my manifest is /app/. However, I'm having an issue where the address bar is showing up in my PWA, even though I have display set to standalone in my manifest.

My manifest:

{
  "name": "...",
  "short_name": "...",
  "icons": [
    {
      "src": "/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    },
    {
      "src": "/maskable-icon.png",
      "sizes": "1024x1024",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ],
  "theme_color": "#FFFFFF",
  "background_color": "#FFFFFF",
  "start_url": "/app/",
  "display": "standalone",
  "orientation": "portrait"
}

My next.config.js properties for next-pwa:

pwa: {
  dest: 'public',
  scope: '/app',
  disable: process.env.NODE_ENV === 'development',
  dynamicStartUrlRedirect: '/login',
  reloadOnOnline: false,
},

Versions

How To Reproduce

Steps to reproduce the behavior:

  1. Set up Next.js with next-pwa and the properties above
  2. Go to the app on Android and click the "Add to Home Screen" banner that shows up at the bottom
  3. Once the app is installed, open it up and observe that the address bar shows up at the top

Expected Behaviors

I would expect the address bar to not show up.

Screenshots

Additional Context

I noticed that if I don't set the scope in my next.config.js, then it works fine and there is no address bar. However, this doesn't work for me because I don't want to cache my marketing pages.

According to this Stack Overflow answer, this issue could be occurring because my app is navigating outside of the scope.

I looked at the codebase for next-pwa and saw that a / is being added to the scope: https://github.com/shadowwalker/next-pwa/blob/1daeb9a192a98e807b206adb760ab05b880b1786/index.js#L71

So this could be occurring because the the user is starting at /app, but /app is not technically inside of /app/.

Is the / at the end necessary? If not, maybe we could remove it, or at least expose an option to remove it.

churichard commented 2 years ago

If I add trailingSlash: true to my next.config.js, then the address bar disappears, so I can confirm that the trailing slash is indeed the problem here.

It's also a decent workaround, but I would prefer it if my URLs didn't all require trailing slashes.

The strange thing is that I tried forking next-pwa and simply removing the extra / that's being appended at the end, but it actually made it so that the app was no longer being recognized as a PWA.

I found this issue which seems to be related: https://github.com/w3c/ServiceWorker/issues/1272

MaxKoldun commented 1 year ago

I had a similar issue, the problem was that basePath (next.config.js) I used and start_url (manifest.json) were different. Maybe you need to change your start_url /app/ -> /app and make it the same as the scope value

SergeySych commented 1 year ago

it is because next-pwa automatically set the closing hash to scope PWA - scope: /app/ even if your basePath: "/app". Pwa scope begine form /app/* . Browser think that page /app is not on scope and not using SW for this page, so this page is not trusted for pwa. There is two way for to resolve it(that i know):

  1. add trailingSlash: true in next.config.js , and your all routes will slash ending (/app/ , /app/about/) https://nextjs.org/docs/api-reference/next.config.js/trailing-slash ;
  2. set custom next response header to SW file, which will allow to use root scope for SW https://medium.com/dev-channel/two-http-headers-related-to-service-workers-you-never-may-have-heard-of-c8862f76cc60 in next.config.js:
    `{
    basePath: "/app",
    headers: async () => [
        {
            source: '/sw.js',
            headers: [
                {
                    key: "Service-Worker-Allowed",
                    value: "/",
                },
            ],
        },
    ],
    }`
nktnet1 commented 1 week ago

@SergeySych thank you! Can confirm the second method with adding:

  headers: async () => [
    {
      source: '/sw.js',
      headers: [
        {
          key: 'Service-Worker-Allowed',
          value: '/',
        },
      ],
    },
  ],

to next.config.mjs worked.

The other things I had to do to get the prefix/basePath working for Next 14 (App Router) was adding this link tag to the root layout

<link rel="manifest" href={`${basePath}/manifest.webmanifest`} />

assuming we are using app/manifest.ts. Otherwise change the href as necessary, e.g. to manifest.json instead of manifest.webmanifest.