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

[🐞] service-worker.js contains appBundles that triggers reinstall of SW when app update and vanishes cached contents generated at client side. #7231

Open
genki opened this issue Jan 7, 2025 · 3 comments
Labels
STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working

Comments

@genki
Copy link
Contributor

genki commented Jan 7, 2025

Which component is affected?

Qwik Rollup / Vite plugin

Describe the bug

I am writing a somewhat larger app that has about 30k LOC with Qwik.
The app uses cache storage for caching generated blobs at the client side.
When I updated the app, I found the all cached contents triggers 404 not found even if they had been cached previously.
Many of browsers tend to delete the caches have "Response type = default" (it means generated in client side) when the SW is re-installed.

The reason this happen is the SW consists of import directives of app bundles at the beginning of its code like this:

/* Qwik Service Worker */
const appBundles=[["../service-worker.js",[]],["q--KEW2DbK.js",[340],["xQFD5FVcBRQ"]],["q--_4w9D7L.js",[503],["OBeSkLDDqJo"]],["q--qFCc4IF.js",[62],["l201lnGtjHc"]],["q-06YRlKI6.js",[263],["G0S2erIT0Fw"]],["q-0gyC57cm.js",[376],["RJ2O1gsqYM8"]],...

The hashes of app bundles are changed even if one of them has been modified, so thus we experience the reinstall of the SW for every app updates.

Expected behaviour is the SW is not re-installed when the app is updated, except the SW itself has been modified.
The reinstall expires the cached content that is cached by previous era of the SW.

I think the appBundles can be fetched dynamically instead of being embedded.

Reproduction

couldn't be supplied

Steps to reproduce

No response

System Info

System:
    OS: macOS 14.6.1
    CPU: (8) arm64 Apple M2
    Memory: 42.20 MB / 24.00 GB
    Shell: 3.6.1 - /opt/homebrew/bin/fish
  Binaries:
    Node: 20.18.1 - /opt/homebrew/opt/node@20/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.9.4 - ~/project/jotter/node_modules/.bin/npm
    pnpm: 9.11.0 - /opt/homebrew/bin/pnpm
    bun: 1.1.26 - ~/.bun/bin/bun
  Browsers:
    Chrome: 131.0.6778.205
    Safari: 17.6
  npmPackages:
    @builder.io/qwik: file:../clone/qwik/packages/qwik => 1.12.0 
    @builder.io/qwik-city: file:../clone/qwik/packages/qwik-city => 1.12.0 
    typescript: ^5.4.5 => 5.4.5 
    undici: ^5.28.4 => 5.28.4 
    vite: ^5.4.11 => 5.4.11

Additional Information

No response

@genki genki added STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working labels Jan 7, 2025
@gioboa
Copy link
Member

gioboa commented Jan 7, 2025

Hi @genki I see

The hashes of app bundles are changed even if one of them has been modified, so thus we experience the reinstall of the SW for every app updates.

Is it related to this issue ?

@genki
Copy link
Contributor Author

genki commented Jan 7, 2025

@gioboa
To say this is too about the fragile hash problem, it is a bit related to, but I think this is separated issue because this is happen even if the most of the hashes are expectedly stable.
This is about the design of the life time of the service-worker.

@genki
Copy link
Contributor Author

genki commented Jan 7, 2025

To keep stable the SW, it should have no varying entities in it.
So the appBundles and so on, should be taken like this

let lastUpdate = 0;
self.addEventListener('message', async (event) => {
  if (event.data.action === 'updateBundles') {
    if (event.data.buildTime <= lastUpdate) return;
    lastUpdate = event.data.buildTime; 
    const res = await fetch("/q-bundles.json?_=" + event.data.buildTime);
    const {appBundles, libraryBundleIds, linkBundles} = await res.json();
    ...
  }
});

This makes the SW's lifetime longer and let it be possible to handle/keep caches over the generations of updated app versions even for the Response type = default.
This /q-bundles.json's lifetime is same to single app version. It would be invalidated per each update including changes of the app.
And the <ServiceWorkerRegister/> component should post the message to the SW with the build time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants