Skip to content

feat: add SSR workbox support #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

userquin
Copy link
Member

@userquin userquin commented Sep 23, 2023

This PR includes support for SSR Pages via custom runtime caching plugins using NetworkOnly or NetworkFirst handler:

  • any SSR page path will be included in the sw precache denylist entry with exact match, if includes dynamic route the plugin will include a wildcard regex instead
  • any SSR page path will include a custom handler
  • for all children in any not dynamic SSR parent route will be also included in the denylist and in the runtime caching entries
  • no dynamic pages can be cached, just enable the cache option, you can include cacheName and offlinePage

To run the playground, from root: nr dev:preview:build.

We need to:

  • handle dynamic routes like somepath-[someparam]
  • handle routeRules: vitesse-nuxt3 is using prerender and Elk is using routeRules instead prerender (traverse all pages applying the routeRules match to include/exclude them, maybe creating and using a radix3 router?)

The PR using eval to generate the runtimeCaching entry per route since we need to provide a few parameters, maybe we can use another approach.

┌───────────────────┬──────────────────┬───────────────────────────────────────────────┐
│ (iteration index) │       Key        │                    Values                     │
├───────────────────┼──────────────────┼───────────────────────────────────────────────┤
│         0         │   '/hi/:id()'    │       { exp: /^\/hi\//, dynamic: true }       │
│         1         │     '/list'      │      { exp: /^\/list$/, dynamic: false }      │
│         2         │ '/list/example2' │ { exp: /^\/list\/example2$/, dynamic: false } │
│         3         │ '/list/example'  │ { exp: /^\/list\/example$/, dynamic: false }  │
│         4         │  '/list/:id()'   │      { exp: /^\/list\//, dynamic: true }      │
└───────────────────┴──────────────────┴───────────────────────────────────────────────┘

imagen

? eval(`() => ({
urlPattern: ({ url, sameOrigin }) => sameOrigin && url.pathname.match(${regex}),
handler: 'NetworkFirst',
options: {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add purge on quota error

},
plugins: [{
handlerDidError: async () => Response.redirect(${JSON.stringify(offlinePage)}, 302),
cacheWillUpdate: async ({ response }) => response.status === 200 ? response : null
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prevent error here (response can be null/undefined when offline)?
cacheWillUpdate: async ({ response }) => response?.status === 200 ? response : null

&& options.strategies !== 'injectManifest'

const ssrPages: NuxtPage[] = []
let nitroOptions: NitroOptions | undefined
nuxt.hook('nitro:init', (nitro) => {
Copy link
Member Author

@userquin userquin Sep 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can just remove the configuration here and configure the options in vite:extendConfig hook

@userquin
Copy link
Member Author

userquin commented Sep 24, 2023

This PR is too complex to be solved automatically, the runtime caching should be included by the user, there are a lot of configuration that can be included, for example:

  • routes group set with a custom cache configuration, another routes group set with another custom cache configuration
  • custom cache with isr or swr configuration: should use StaleWhileRevalidate with proper headers?
  • custom cache with Vary header
  • custom cache with custom expiration (related to first entry)
  • complex Nuxt precache and routeRules mix: we should traverse pages with a router to check if we need to include/exclude some specific routes
  • complex dynamic routes layout/naming (somepath-[someparam] with children)
  • sort routes in a subtree to include first non dynamic ones (similar logic included in vue/unplugin router)

@userquin
Copy link
Member Author

userquin commented Mar 26, 2025

we should use https://github.com/unjs/unrouting to extract dynamic routes patterns/paths

/cc @danielroe 🙏 @BobbieGoede (sorry for the ping ❤️ )

@GreyXor
Copy link

GreyXor commented May 9, 2025

@userquin Hi, just to confirm, does this mean that offline support isn't currently available when using nuxt generate (with SSR enabled by default)? That would explain why I can't get offline support on my statically generated site

@userquin
Copy link
Member Author

userquin commented May 9, 2025

No, the problem is about SSR pages where you cannot add those routes to the sw precaching manifest, that's, a page refresh on any SSR page when offline will show the default browser offline page.

This PR will try to add a custom runtime caching for SSR pages to avoid the browser offline page; we need to store SSR pages in a new cache to allow work when offline (won't work if the user doesn't navigate to those pages previously): the runtime caching will require to "parse" SSR pages adding the corresponding "regex" to the runtime caching to allow workbox intercept and cache the SSR pages content.

@GreyXor
Copy link

GreyXor commented May 9, 2025

ok thanks for these explanations.
So my SSR static PWA app that doesn't work offline is probably something else 👍 will debug more

@userquin
Copy link
Member Author

userquin commented May 9, 2025

ok thanks for these explanations. So my SSR static PWA app that doesn't work offline is probably something else 👍 will debug more

Check if there is some error when installing the sw, if you share in a new issue/discussion your configuration and the url I can check it

@GreyXor
Copy link

GreyXor commented May 13, 2025

ok thanks for these explanations. So my SSR static PWA app that doesn't work offline is probably something else 👍 will debug more

Check if there is some error when installing the sw, if you share in a new issue/discussion your configuration and the url I can check it

Thanks, the offline feature of my app is working but only for "/" page. Not the "/foo" and "/bar". I need to first visit them online, and only after it can work in offline mode. with nuxt generate full static SPA nitro pre-rended app.

There's a way to directly make all page work in offline mode ?
my app is generated via nuxt generate. so i have SSG+SSR enabled. it's a full static site. no server behind, the server is only used during generation for all pages

  pwa: {
    registerType: 'autoUpdate',
    workbox: {
      navigateFallback: "/",
      globPatterns: ['**/*.{js,css,html,png,PNG,svg,jpg,JPG,jpeg}'],
    },

@userquin
Copy link
Member Author

userquin commented May 13, 2025

Did you remove/unregister the sw and the storage when switching between prerender and SSR app? You may have the old sw there, try using private browsing.

@GreyXor
Copy link

GreyXor commented May 13, 2025

Did you remove/unregister the sw and the storage when switching between prerender and SSR app? You may have the old sw there, try using private browsing.

Yes pre-rended pages is not availabe offline even on fresh restart, sw and storage removed

@userquin
Copy link
Member Author

userquin commented May 13, 2025

Can you share the repo or some url where I can check it? Or just provide a minimal reproduction 🙏

EDIT: check if you're going offline before the sw is ready (the sw should be green in the devtools, that's, installed and activated once sw precaching downloaded)

I'm testing settings pages with elk.zone and seems to be working, maybe we need to review Nuxt hooks, from time to time there are small breaking changes for the integration: for context check https://github.com/vite-pwa/nuxt/blob/main/src/utils/module.ts#L309-L338

offline elk.zone settings page

imagen

Can you confirm you're using the Nuxt PWA integration instead just the PWA plugin?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy