Skip to content
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

Cached files does not load pages except "/" (base path) in sveltekit #665

Closed
omerharuncetin opened this issue Feb 16, 2024 · 29 comments
Closed

Comments

@omerharuncetin
Copy link

omerharuncetin commented Feb 16, 2024

My problem is related to the cached files. If I route to the main page, which is / everything works fine. However, if I want to route another page, such as

  • /explore
  • /posts/x
  • /users/y

These page assets are loading from the current path not from the base path. Therefore, non of the files be able to uploaded and the page doesn't respond correctly.

Some project information may be helpful for finding solution.

  • I have defined scope and base as / both in manifest and SvelteKitPWA config.
  • I use generateSW strategy with autoUpdate register type
  • I don't have custom service worker.

If you need any further information, please let me know.

Also, here is the a part of error in browser console. If I do hard refresh on page, everything works fine.

image

@userquin
Copy link
Member

try setting paths.relative to false in kit config file: https://kit.svelte.dev/docs/configuration#paths

@omerharuncetin
Copy link
Author

omerharuncetin commented Feb 16, 2024

try setting paths.relative to false in kit config file: https://kit.svelte.dev/docs/configuration#paths

I tried it, now page loads but it does not load the related page. It loads the main page instead.

Current behaviour:

I route to /profile/x

Website url is /profile/x but shows the main page contents.

@userquin
Copy link
Member

userquin commented Feb 16, 2024

Any SSR page or api call must be excluded from sw interception, check vite-pwa/sveltekit#65

NOTE: any page not being prerendered will not have the corresponding html page in the dist folder, on page refresh the entry will not be in the sw precache manifest and the sw will redirect/forward to fallback page, you need to exclude SSR pages from sw interception including them in the navigateFallbackDenylist and then add a custom handler to avoid browser offline error page redirecting to the offline page

@omerharuncetin
Copy link
Author

omerharuncetin commented Feb 16, 2024

Any SSR page or api call must be excluded from sw interception, check vite-pwa/sveltekit#65

NOTE: any page not being prerendered will not have the corresponding html page in the dist folder, on page refresh the entry will not be in the sw precache manifest and the sw will redirect/forward to fallback page, you need to exclude SSR pages from sw interception including them in the navigateFallbackDenylist and then add a custom handler to avoid browser offline error page redirecting to the offline page

Unfortunately still opens the home page when I try to route dynamic ssr pages. Here are what I added to the config regarding to the issue that you suggested to look at.

I defined navigateFallbackDenyList for my routes as following:

const navigateFallbackDenyList = [
  // prettier-ignore
  new RegExp("/^\/[^\/]+\/?$/") /* eslint-disable-line */,
  // prettier-ignore
  new RegExp("/^\/[^\/]+\/posts\/[^\/]+\/?$/") /* eslint-disable-line */,
  // prettier-ignore
  new RegExp("/^\/profile\/[^\/]+\/?$/") /* eslint-disable-line */,
  // prettier-ignore
  new RegExp("/^\/posts\/[^\/]+\/?$/") /* eslint-disable-line */,
  // prettier-ignore
  new RegExp("/^\/topics\/[^\/]+\/?$/") /* eslint-disable-line */,
];

Also defined runtimeCaching for every rule. Here is the one example:

{
            urlPattern: ({ url, sameOrigin }) =>
              // prettier-ignore
              sameOrigin && url.pathname.match("/^\/[^\/]+\/?$/") /* eslint-disable-line */,
            handler: "NetworkFirst",
            options: {
              cacheName: "ssr-pages-cache",
              /* cache only 200 responses */
              cacheableResponse: {
                statuses: [200],
              },
              /* check the options in the workbox-build docs*/
              matchOptions: {
                ignoreVary: true,
                ignoreSearch: true,
              },
              plugins: [
                {
                  /* this callback will be called when the fetch call fails */
                  handlerDidError: async () =>
                    Response.redirect("/error?offline", 302),
                  /* this callback will prevent caching the response */
                  cacheWillUpdate: async ({ response }) =>
                    response.status === 200 ? response : null,
                },
              ],
            },
          },

EDIT: Here is the related part in sw.js

e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/"),{
        denylist: [/\/^\/[^/]+\/?$\//, /\/^\/[^/]+\/posts\/[^/]+\/?$\//, /\/^\/profile\/[^/]+\/?$\//, /\/^\/posts\/[^/]+\/?$\//, /\/^\/topics\/[^/]+\/?$\//]
    })),
    e.registerRoute((({url: e, sameOrigin: i})=>i && e.pathname.match("/^/[^/]+/?$/")), new e.NetworkFirst({
        cacheName: "ssr-pages-cache",
        matchOptions: {
            ignoreVary: !0,
            ignoreSearch: !0
        },
        plugins: [new e.CacheableResponsePlugin({
            statuses: [200]
        }), {
            handlerDidError: async()=>Response.redirect("/error?offline", 302),
            cacheWillUpdate: async({response: e})=>200 === e.status ? e : null
        }]
    }), "GET"),
    e.registerRoute((({url: e, sameOrigin: i})=>i && e.pathname.match("/^/[^/]+/posts/[^/]+/?$/")), new e.NetworkFirst({
        cacheName: "ssr-pages-cache",
        matchOptions: {
            ignoreVary: !0,
            ignoreSearch: !0
        },
        plugins: [new e.CacheableResponsePlugin({
            statuses: [200]
        }), {
            handlerDidError: async()=>Response.redirect("/error?offline", 302),
            cacheWillUpdate: async({response: e})=>200 === e.status ? e : null
        }]
    }), "GET"),
    e.registerRoute((({url: e, sameOrigin: i})=>i && e.pathname.match("/^/profile/[^/]+/?$/")), new e.NetworkFirst({
        cacheName: "ssr-pages-cache",
        matchOptions: {
            ignoreVary: !0,
            ignoreSearch: !0
        },
        plugins: [new e.CacheableResponsePlugin({
            statuses: [200]
        }), {
            handlerDidError: async()=>Response.redirect("/error?offline", 302),
            cacheWillUpdate: async({response: e})=>200 === e.status ? e : null
        }]
    }), "GET"),
    e.registerRoute((({url: e, sameOrigin: i})=>i && e.pathname.match("/^/posts/[^/]+/?$/")), new e.NetworkFirst({
        cacheName: "ssr-pages-cache",
        matchOptions: {
            ignoreVary: !0,
            ignoreSearch: !0
        },
        plugins: [new e.CacheableResponsePlugin({
            statuses: [200]
        }), {
            handlerDidError: async()=>Response.redirect("/error?offline", 302),
            cacheWillUpdate: async({response: e})=>200 === e.status ? e : null
        }]
    }), "GET"),
    e.registerRoute((({url: e, sameOrigin: i})=>i && e.pathname.match("/^/topics/[^/]+/?$/")), new e.NetworkFirst({
        cacheName: "ssr-pages-cache",
        matchOptions: {
            ignoreVary: !0,
            ignoreSearch: !0
        },
        plugins: [new e.CacheableResponsePlugin({
            statuses: [200]
        }), {
            handlerDidError: async()=>Response.redirect("/error?offline", 302),
            cacheWillUpdate: async({response: e})=>200 === e.status ? e : null
        }]
    }), "GET")

@userquin
Copy link
Member

can you share the repo?

@omerharuncetin
Copy link
Author

can you share the repo?

Here is minimal reproduction that has the same vite, svelte and pwa config and node modules
https://github.com/omerharuncetin/pwa-reproduction

also here is the deployed version of the repository:

https://pwa-reprod.netlify.app/

you can try these urls:

https://pwa-reprod.netlify.app/
https://pwa-reprod.netlify.app/test
https://pwa-reprod.netlify.app/test/posts/postid
https://pwa-reprod.netlify.app/explore

@omerharuncetin
Copy link
Author

hi @userquin is there any update on this issue?

@userquin
Copy link
Member

userquin commented Feb 19, 2024

You cannot redirect to error page since it is not being prerendered, the error.html page isn't in the sw precache, so you can prerender it or replace handlerDidError redirection with / instead using /error (you will get an infinite redirection).

Add workbox.globPatterns to include html, css, js and png assets (pwa icons not being precached): workbox.globPatterns: ['client/**/*.{js,css,png}'] (don't include html here, the plugin will do it for you)

Change cache names on each router or use only one with all the logic: move the logic to only 1 urlPattern handler.

If you refresh the page you will see the caches (right button on caches and refresh caches): the cache cannot be created if missing when intercepting the request.

@userquin
Copy link
Member

userquin commented Feb 19, 2024

Add mode: 'development' to pwa options to show the workbox messages in Netlify...

@omerharuncetin
Copy link
Author

Thank you for your response. I added the globPattern values and set mode as development then updated the repository and netlify. Could you please briefly explain the following statement, because I couldn't understand it

Change cache names on each router or use only one with all the logic: move the logic to only 1 urlPattern handler.

You cannot redirect to error page since it is not being prerendered, the error.html page isn't in the sw precache, so you can prerender it or replace handlerDidError redirection with / instead using /error (you will get an infinite redirection).

Add workbox.globPatterns to include html, css, js and png assets (pwa icons not being precached): workbox.globPatterns: ['client/**/*.{js,css,png}'] (don't include html here, the plugin will do it for you)

Change cache names on each router or use only one with all the logic: move the logic to only 1 urlPattern handler.

If you refresh the page you will see the caches (right button on caches and refresh caches): the cache cannot be created if missing when intercepting the request.

@userquin
Copy link
Member

imagen

@userquin
Copy link
Member

you're caching all resources on each cache: navigate between routes in this comment #665 (comment) with a page refresh and refresh Cache storage entries in dev tools (right button + refresh caches)

@userquin
Copy link
Member

Cache entries will be there (repeat the process with a few more pages)

@userquin
Copy link
Member

@userquin
Copy link
Member

maybe the problem is previous handler

@omerharuncetin
Copy link
Author

omerharuncetin commented Feb 19, 2024

what's the purpose of this handler https://github.com/omerharuncetin/pwa-reproduction/blob/main/vite.config.ts#L76?

That handler should catch the profile url's in production. Such as /userquin or /omerharuncetin.

@userquin
Copy link
Member

You cannot use prerenderedPages outside the handler, include it inside the handler as a regex array, your sw with errors...

@omerharuncetin
Copy link
Author

You cannot use prerenderedPages outside the handler, include it inside the handler as a regex array, your sw with errors...

just fixed it 😅

@userquin
Copy link
Member

userquin commented Feb 19, 2024

add pwa icons inside static folder, since you don't have web manifest icons the sw will have weird behavior, use @vite-pwa/assets-generator via CLI (or just copy paste them from the pwa kit repo to test the sw in your local)

EDIT: once web manifest icons added the sw scope will take effect and so only 1 cache added to the browser when navigating between pages + page refresh

@omerharuncetin
Copy link
Author

omerharuncetin commented Feb 19, 2024

add pwa icons inside static folder, since you don't have web manifest icons the sw will have weird behavior, use @vite-pwa/assets-generator via CLI (or just copy paste them from the pwa kit repo to test the sw in your local)

EDIT: once web manifest icons added the sw scope will take effect and so only 1 cache added to the browser when navigating between pages + page refresh

PWA icons are already in the static folder. However, it's not included in precache and does not show up in deployed netlify directory too.

image

@userquin
Copy link
Member

pwa icons missing in the server ? just try requesting one of them or check the web manifest in dev tools

@userquin
Copy link
Member

uhmm, static folder should be on root not inside src folder

@omerharuncetin
Copy link
Author

uhmm, static folder should be on root not inside src folder

Oh good catch, thank you! Probably there was a mistake when I was moving the folder from my original repo to minimal. Just updated and I guess you are right. The regex that I use to catch profile url doesn't work properly tbh and idk why. Do you have any opinion on that, that would help me a lot tbh. Because that regex works when I try it on different regex test websites.

@userquin
Copy link
Member

I'll try using another approach later, using kit sw: we've access to routes there https://kit.svelte.dev/docs/service-workers#inside-the-service-worker

@userquin
Copy link
Member

userquin commented Feb 19, 2024

it seems the sw precaching is there but it shouldn't (using kit sw we can warm the ssr cache when installing the sw), I guess it is the redirection since I get the home page (that's fine to avoid browser offline page), but not stored in the ssr-pages cache:

imagen

@userquin
Copy link
Member

userquin commented Feb 19, 2024

it seems your pages not working properly, this is an example that's working (just visit the page and then refresh it):

imagen

imagen

@omerharuncetin
Copy link
Author

it seems your pages not working properly, this is an example that's working (just visit the page and then refresh it):

imagen

imagen

Thank you. and I wonder why /slug/posts/postId works but /slug does not work. Probably it would be better if I search for the routing in sveltekit.

@omerharuncetin
Copy link
Author

I found out that the issue was related to regex as we discussed before. The regex was wrong and I had to use same regex for workbox.navigateFallbackDenylist and workbox.runtimeCaching. Thank you for your support @userquin 🙌

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

No branches or pull requests

2 participants