Gatsby: [gatsby-plugin-offline] Default behavior serves stale data

Created on 17 Feb 2019  路  30Comments  路  Source: gatsbyjs/gatsby

Summary

Default configuration for gatsby-plugin-offline serves stale data to users even when network is available.

Relevant information

Imagine a user who visits a website once a week. If the website has default gatsby-plugin-offline configuration, the user will always see 1 week old version of the website on their first pageload. Gatsby-plugin-offline is configured in such a way that it first serves stale content from its cache and then updates the cache in the background (so subsequent pageloads get a fresher version).

I've been trying for hours but I can't seem to change this behavior. I tried changing staleWhileRevalidate to networkFirst after reading this and this. It seems I got the syntax wrong somehow, since the behavior is still the same. I can't find a complete working example anywhere.

I don't think it's ever reasonable for a user to see a version that may be several days old. So I guess my question is twofold,
1) Should the default configuration be changed?
2) Can someone provide a complete working example of a reasonable configuration for gatsby-plugin-offline? I think a reasonable behavior would be to use network when it's available, but use cache in case of timeout/fail. And of course assets in /static and *.js etc. should be always served from cache.

help wanted PWA

Most helpful comment

It'd be nice to support network first as an option. It's still be faster than without a SW and offer the nice guarantee that pages will always be fresh.

It could even be the default in the future actually as it's less surprising for folks.

All 30 comments

@baobabKoodaa
I use this function in gatsby-browser.js to notify user about new version

export const onServiceWorkerUpdateFound = () => {
  if (isBrowser) {
    const answer = window.confirm(
      `This application has been updated. ` +
      `Reload to display the latest version?`
    )

    if (answer === true) {
      window.location.reload()
    }
  }
}

but I do not like the behavior. It is often shows a lot of errors in browser console from the cache after page reload.

11842

@baobabKoodaa it's not as easy as it seems. The default that we use is cache-first as we can do a lot of optimisations for you.

These are all approaches that are available:

  • Cache only
  • Network only
  • Cache first, falling back to network (current approach)
  • Network first falling back to cache

Cache first approach is the fastest. You probably can create your own gatsby-plugin-offline with another approach. I'm unsure we want to take this on in the default plugin. Perhaps we could look into opt-out scenarios. Another idea could be to look in to background fetch (not supported everywhere yet) to update these pages from time to time.

It'd be nice to support network first as an option. It's still be faster than without a SW and offer the nice guarantee that pages will always be fresh.

It could even be the default in the future actually as it's less surprising for folks.

I have to admit, its a bit awkward to have to tell management to reset their cache to see the new feature 4x a week. Offline first isn't understood by most people. I love the speed, but for smaller sites that are iterating on rapidly changing designs, the positives don't outweigh the negatives.

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 馃挭馃挏

not stale lol

+1 for network first

Any word on this? No one is going to understand what I'm talking about if I pop a dialog telling them to upgrade to the new version of a website.

  • 1 for network first

Add the option to gatsby-plugin-offline to enable network first approach.

We love if someone would take this on! 馃挭

I was surprised by the current behavior as well, and would love to give this a shot 馃檪

@stfnsr that's awesome! If you need any assistance just let us know. A pair programming session might work or join us in our weekly meeting.

My guess is to make https://github.com/gatsbyjs/gatsby/blob/b4e370f9baec397d1958d73315ef1c8aa5eb2d52/packages/gatsby-plugin-offline/src/gatsby-node.js#L91 configurable with an option where we can easily switch it to networkFirst.

You should be able to test this without changing the offline plugin.

// gatsby-config.js
{
  plugins: [
    {
      resolve: `gatsby-plugin-offline`,
      options: {
        runtimeCaching: [
          {
            // Use cacheFirst since these don't need to be revalidated (same RegExp
            // and same reason as above)
            urlPattern: /(\.js$|\.css$|static\/)/,
            handler: `networkFirst`,
          },
          {
            // Add runtime caching of various other page resources
            urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
            handler: `staleWhileRevalidate`,
          },
          {
            // Google Fonts CSS (doesn't end in .css so we need to specify it)
            urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
            handler: `staleWhileRevalidate`,
          },
        ],
      },
    }
  ]
}

I'm no offline-plugin expert so i'll cc @davidbailey00 which is 馃槃.

@wardpeet thanks for pointing me in this direction - would be great if this approach would be sufficient, i was expecting to have to delve into the depths of serviceworkers ^^
Where can i find more info about the weekly meeting? The link on the community page seems to be dead?
The pair programming session sounds great - will definitely consider this at a later point :)

Regarding the offline plugin:
Is the snippet you posted an alternative syntax for plugin configuration? I was only aware of { resolve: 'gatsby-plugin-offline', options: { ... }}

I tried to switch the workbox strategy to networkFirst (and even to networkOnly) (which worked, according to workbox' console logs), but the behaviour was still not what i would expect - it took 2 to 3 reloads until changes were visible.
Will have to poke around further 馃

馃槷 https://gatsby.dev/core-maintainers thanks for pointing out 馃槃 I'll let you know when it's fixed.

I tried to switch the workbox strategy to networkFirst (and even to networkOnly) (which worked, according to workbox' console logs), but the behaviour was still not what i would expect - it took 2 to 3 reloads until changes were visible.

Could you try to remove the service worker or update on reload. I think the sw isn't updating but I might be wrong.
image

Ah, i didn't know that option. I tried to fully deregister the service worker though (with gatsby-plugin-remove-serviceworker), and tried it in a freshly cloned default starter project as well.
From what I'm seeing in the Application tab, after i change something in the (specifically, the "Hi people" headline), build the site and reload the browser, the content is still the old one, but a new/updated serviceworker is registered. With the next reload, the new content is there.

Is the snippet you posted an alternative syntax for plugin configuration? I was only aware of { resolve: 'gatsby-plugin-offline', options: { ... }}

It's just me being bad at giving advice 馃槃 I've been to deep on babel configs lately which uses that syntax. I've edited the above comment with correct syntax

Let me know if the config above works then we can add an option to the offline plugin. We recently shipped a new way of getting page data #14359 so this might help as well with stale data.

Let me know if the config above works then we can add an option to the offline plugin. We recently shipped a new way of getting page data #14359 so this might help as well with stale data.

Ah sorry, i might have been unclear here:

From what I'm seeing in the Application tab, after i change something in the (specifically, the "Hi people" headline), build the site and reload the browser, the content is still the old one, but a new/updated serviceworker is registered. With the next reload, the new content is there

This was referring to the situation after trying the config above, even when starting from a completely fresh project that has never been run with offline-first.
So, did not work.
I'd like to use this as an opportunity to dig deeper into serviceworkers, my suspicion right now is that it could have something to do with the routes being precached?

I would love to see the option for network then cache too. For now I will have to disable this because there are too many inquiries with my team on why we are showing stale pages. I would really love to keep using this long term though 馃

I also definitely would love network, then cache. Meanwhile we silently reload the page after update.

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 馃挭馃挏

not stale

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 馃挭馃挏

not stale!

not stale

@wardpeet any updates on this?

after a week of developmet there were 2gb of cache data i saw in 'clear storage' tab. Some pages didn't work and were displayed as white screen untill i cleared storage. If i remove this plugin from project i will see 'static query(loading...)' after replacing old build with new one. The page on my mobile phone were also like empty white-screen. I've tried everything to force chrome through nignx headers to download fresh data but nothing works, it uses cache first anyway.

I thought the problem was fixed after reading some articles (links below) and creating the following configuration:

    {
      resolve: `gatsby-plugin-offline`,
      options: {
        workboxConfig: {
          runtimeCaching: [
            // no need for revalidation (unique uris with static content)
            {
              urlPattern: /(\.js$|\.css$|static\/)/,
              handler: `CacheFirst`,
            },
            // *data.json and static query results are not content hashed
            {
              urlPattern: /^https?:.*\/page-data\/.*\.json/,
              handler: `NetworkFirst`,
              options: {
                networkTimeoutSeconds: 3,
              },
            },
            // add runtime caching for resources that change less often
            {
              urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
              handler: `StaleWhileRevalidate`,
            },
            // Google Fonts CSS (doesn't end in .css so we must specify it)
            {
              urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
              handler: `StaleWhileRevalidate`,
            },
            // serve up-to-date content and fallback to cache when posible
            {
              urlPattern: /\/$/,
              handler: `NetworkFirst`,
              options: {
                networkTimeoutSeconds: 3,
              },
            },
          ],
        },
      },
    },

But, ultimately, the website had all sorts of new strange behaviour. So, in the end, I just replaced this plugin with gatsby-plugin-remove-serviceworker.

Well, thinking about it now, maybe I should have first removed the old workers, and then created the new configuration, I don't know.

Links:

after a week of developmet there were 2gb of cache data i saw in 'clear storage' tab. Some pages didn't work and were displayed as white screen untill i cleared storage. If i remove this plugin from project i will see 'static query(loading...)' after replacing old build with new one. The page on my mobile phone were also like empty white-screen. I've tried everything to force chrome through nignx headers to download fresh data but nothing works, it uses cache first anyway.

@vsolanogo Make sure you installed gatsby-plugin-remove-serviceworker, this is required when removing gatsby-plugin-offline.

export const onServiceWorkerUpdateFound = () => {
if (isBrowser) {
const answer = window.confirm(
This application has been updated. +
Reload to display the latest version?
)

if (answer === true) {
  window.location.reload()
}

}
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dustinhorton picture dustinhorton  路  3Comments

timbrandin picture timbrandin  路  3Comments

andykais picture andykais  路  3Comments

rossPatton picture rossPatton  路  3Comments

Oppenheimer1 picture Oppenheimer1  路  3Comments