next-offline icon indicating copy to clipboard operation
next-offline copied to clipboard

Service Worker aggressive caching makes web app slower

Open urkopineda opened this issue 5 years ago • 5 comments

Time-to-Interactive / First CPU Idle / First Input Delay result decrease adding next-offline service worker to a web app. As can be seen in the screenshots, seems that the service worker is too aggressive caching JS chunks of the web app and makes this results worse.

  • Issue and steps to reproduce: Add to a next.js web app next-offline using the getting started gide.

  • Versions.

    • next.js: 9.2.2
    • next-offline: 5.0.0
  • Screenshots.

    • Lighthouse without SW. Lighthouse - without SW
    • Network without SW. Network without SW
    • Lighthouse with SW (15 points of drop! T-t-I from 6.4 to 9.1 seconds, FCI from 5.7 to 7.7 seconds and FID from 580 to 840 ms) Lighthouse - with SW
    • Network with SW part 1 (we can see the start of all JS of the web app downloading) Network with SW (1)
    • Network with SW part 2. Network with SW (2)
  • Expected: Same or even better Time-to-Interactive result.

  • Actual: Worse Time-to-Interactive result.

  • Link to your project: https://tentu.eus

  • Browser name and version: Chrome 80

urkopineda avatar Feb 21 '20 09:02 urkopineda

Interesting, this issue might be better suited for the library next-offline is using under the hood

https://github.com/GoogleChrome/workbox

They're really receptive, we can keep this open and you can link the new issue to this one if you'd like

hanford avatar Feb 24 '20 17:02 hanford

I have being digging a little more and when a build is generated there is a list of *.js assets that seems to precache when entering the page (I'm checking .next/service-worker.js after generating a build)

The list looks like this one:

[
    // BASE FILES START
    {
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/_buildManifest.js",
        revision: "da7188f9e1f939567016a2317720dc51"
    },{
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/pages/_app.js",
        revision: "f8b6d0a28a7d558551eb6391a89e4a23"
    }, {
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/pages/_error.js",
        revision: "f37e0a171bb16b16040c90df34522d96"
    }, {
        url: "_next/static/chunks/framework.b347b462804689eaf927.js",
        revision: "6deca90db3f45a916770bb0e41b13c47"
    }, {
        url: "_next/static/runtime/main-e7b4cabd257a4cc3b967.js",
        revision: "890b84d502df85433e36acdf3cf74224"
    }, {
        url: "_next/static/runtime/polyfills-f916fbf10dc4121ae9cd.js",
        revision: "d9323c6914d005baba12d60770880583"
    }, {
        url: "_next/static/runtime/webpack-e103235a3ab9d95a6af4.js",
        revision: "8bcbba6f506d61d82d4064c4b346a8aa"
    },
    // BASE FILES END
    // PAGE FILES START
    {
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/pages/index.js",
        revision: "6ba52db6a6bb884b8fafebfa4cf546e8"
    }, {
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/pages/latest-news.js",
        revision: "25cd2877186c0b93bef4deeeb8b3cb7c"
    }, {
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/pages/next-events.js",
        revision: "2ef7b0df9ce3fccdd3bae4e86f5173b9"
    }, {
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/pages/profile.js",
        revision: "89527553568411baf5e7c6b805f00e62"
    }, {
        url: "_next/static/MqWv-Y9HiB2_KCflF20PP/pages/signin.js",
        revision: "01883f6cc3a11498246bcc7882c70c4c"
    },
    ...
   // PAGE FILES END
   // CHUNK FILES START
    {
        url: "_next/static/chunks/596ac167622d5d88a275aa870b98bfe10a2d1a1c.aada1b70c5e59113cfa0.js",
        revision: "1f845cd5bf11ae86bd19e00f50a94785"
    }, {
        url: "_next/static/chunks/8ab5f57d4e90de3a37b5e6b66aec8a1d67553e8e.829705e26d6c76bf7ca5.js",
        revision: "15a269bcc53e9ea86fa833192b2b5aa0"
    }, {
        url: "_next/static/chunks/c2fc468355bab5579cbc197ee84c663065a62816.17832137b27cd0ba4068.js",
        revision: "117596cdf7a332d8c46cec972085667f"
    }, 
   ...
    // CHUNK FILES END
]

So, in this example if I'm accessing / which is the page index.js, is there a way (a cache strategy for example) to only download and cache that page, the chunks needed and the base JS files; and not the whole pages of the web app (in this example: latest-news.js, next-events.js, profile.js, signin.js...)?

urkopineda avatar Feb 25 '20 08:02 urkopineda

I'm not 100% certain, I'd check the workbox docs.

hanford avatar Feb 29 '20 21:02 hanford

The same problem. Should be able to disable precache bundles!

MaxSvargal avatar Mar 04 '20 11:03 MaxSvargal

Same issue so I use this options to prevent it.

workboxOpts: {
  // Do not precache images
  exclude: [/\.(?:png|jpg|jpeg|svg)$/],
  // Ignore all URL parameters.
  ignoreURLParametersMatching: [/.*/],
  dontCacheBustURLsMatching: /.*/,
  runtimeCaching: [
	{
		urlPattern: /\.(?:png|jpg|jpeg|svg)/,
		handler: 'CacheFirst',
	},
	{
		urlPattern: /^https?.*/,
		handler: 'NetworkFirst',
		options: {
			cacheName: 'offlineCache',
			expiration: {
				maxEntries: 200
			}
		}
	}
]},

geun avatar Apr 10 '20 10:04 geun