vite-pwa / sveltekit

Zero-config PWA Plugin for SvelteKit
https://vite-pwa-org.netlify.app/frameworks/sveltekit
MIT License
287 stars 15 forks source link

Workbox responses with cached data for network only requests #79

Open omerharuncetin opened 4 months ago

omerharuncetin commented 4 months ago

Hello,

I fetch data using a npm package. In that package it makes requests to a graphql endpoint. When I update my profile data and refetch profile information workbox responses with old response instead of the new one. I defined the url pattern in navigateFallbackDenylist and added configuration to runtimeCaching to prevent caching. What could be the problem?

Here are the details related to config and regex:

regex: /^https:\/\/api-v2-mumbai-live.lens.dev\/.*/

configuration:

 {
            urlPattern: /^https:\/\/api-v2-mumbai-live.lens.dev\/.*/,
            handler: "NetworkOnly",
            method: "POST",
            options: {
              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 () => null,
                },
              ],
            },
          }
userquin commented 4 months ago

You need to navigate to it, then close the browser and repoen it, then navigate again: the workbox cannot create the cache on first request.

To solve the problem, you need to use a custom sw and warm/create the cache on install event, then it should work: you will need to move all the logic to the custom sw.

omerharuncetin commented 4 months ago

You need to navigate to it, then close the browser and repoen it, then navigate again: the workbox cannot create the cache on first request.

To solve the problem, you need to use a custom sw and warm/create the cache on install event, then it should work: you will need to move all the logic to the custom sw.

I don't want to cache it at all. It should only return the network response. Do I need to create custom service worker still?

userquin commented 4 months ago

Oops, sorry, I was thinking about another Nuxt issue...

userquin commented 4 months ago

IIRC any request done to another origin shouldn't be intercepted by the sw, you don't need to include any runtime caching: you should handle fetch errors from the app

omerharuncetin commented 4 months ago

Oops, sorry, I was thinking about another Nuxt issue...

That's fine, being super busy can cause these kind of things 😄

omerharuncetin commented 4 months ago

IIRC any request done to another origin shouldn't be intercepted by the sw, you don't need to include any runtime caching: you should handle fetch errors from the app

Yes, I handle the errors in the app however the problem is here that it returns the cached response. I tried to add the config that I provided in topic however it still returns the old response. What could be the problem?

userquin commented 4 months ago

You can add mode: 'development' to check workbox logs in the sw (in your local if you can check against the external api), check also if the responses from the backend are cached, any api call shouldn't be cached (200 with cache headers like: no-cache no store max-age: 0...)

omerharuncetin commented 4 months ago

You can add mode: 'development' to check workbox logs in the sw (in your local if you can check against the external api), check also if the responses from the backend are cached, any api call shouldn't be cached (200 with cache headers like: no-cache no store max-age: 0...)

I checked the logs. Workbox handles the requests with NetworkOnly handle and does not cache anything actually. However, still returns the old response. Also, the api does not cache the value because I tried it on graphql api playground and it returns the response.

Another notable thing is that, It does not matter if I change browser. It still returns the old version, however when I check the profile on another app it shows the correct information.

Let me explain further, there is a graphql api and you can think that as a infrastructare for social media data. Therefore, I can check the profile information in different apps. When I change the profile's information in my app, it returns the old response and seems like nothing is changed, even if I go the user's profile I still see the old information. Yet, it changes on another application, which is frustrating tbh. I tried on different browsers, mobile, waited for a day but still the result is same.

userquin commented 4 months ago

can you show the response headers for graphql requests? maybe you've a bug in your app.

EDIT: check also if the response is cached or not (I mean, the content)

omerharuncetin commented 4 months ago

Here is the response header: image

And here is the workbox logs: image

In addition to that, when I check the Cache storage I don't see any value related to those requests.

Also for the request headers, I set Cache to no-cache

userquin commented 4 months ago

check if the browser is caching the response in network tab; where is the status (should be 200, you have Date and etag response headers, this is wrong, the browser can cache the response if match the criteria => date and etag not changed for example)?

userquin commented 4 months ago

Check also if if-modified-since present in the request headers.

omerharuncetin commented 4 months ago

first response headers: image

second response headers: image

Also here is the how network tab looks like for that request: image

No, there is no if-modified-since specified in request headers.

userquin commented 4 months ago

How about the content?

My suggestion (I use these headers): remove etag adding Cache-Control: no-cache, no-store, max-age=0, must-revalidate and Expires: 0 headers.

omerharuncetin commented 4 months ago

How about the content?

My suggestion (I use these headers): remove etag adding Cache-Control: no-cache, no-store, max-age=0, must-revalidate and Expires: 0 headers.

By content, if you mean the response data it still returns the old response.

I added headers you mentioned image

However it is still the same, also the network requests are slightly changed. There is no workbox initiator now. image

userquin commented 4 months ago

Just remove the runtime caching for external api.

If the response data is old one, you should have something wrong in your graphql backend or proxy: disabling the PWA works?

omerharuncetin commented 4 months ago

I removed the runtime caching and tried, nothing changed it still returns the old data.

I disabled the pwa, unregistered the service worker, cleared the site data and tried, nothing changed again.

I don't maintain the graphql api. So, I don't know how they implemented things there and I don't have access to change. However, we tried many things here and also I am struggling with this problem for almost 1 week. Do you think any other solution could work or should I contact with the maintainers of the backend?

userquin commented 4 months ago

if using apollo client maybe you can use these default options in the constructor:

const defaultOptions: DefaultOptions = {
      watchQuery: {
        fetchPolicy: 'no-cache',
        errorPolicy: 'ignore',
      },
      query: {
        fetchPolicy: 'no-cache',
        errorPolicy: 'all',
      },
    }
omerharuncetin commented 4 months ago

I don't use apollo client. I make the requests by using a sdk. As far as I know they don't use apollo too, only graphql and fetch. And I already set cache request header as no-cache

userquin commented 4 months ago

check if the sdk has some internal flag, check also if the new credentials are sent properly (when changing the profile)