sveltejs / kit

web development, streamlined
https://svelte.dev/docs/kit
MIT License
18.76k stars 1.95k forks source link

svelte.config.js version changes cause most client chunks to generate a new hash despite no other changes #12260

Open rory-orennia opened 6 months ago

rory-orennia commented 6 months ago

Updated bug report

Changing the version in svelte.config.js and rebuilding the exact same code results in most client chunks also being updated with a new hash. The cause seems to be the version check code being updated to look for a new version, and then most client chunks directly or indirectly importing that change.

Initial bug report

Describe the bug

If you build the same project twice, you get different files out even though nothing has changed.

I was trying to break my project up using manualChunks to create a vendor.js file with the hope that while we're deploying multiple times a day, our dependencies rarely change so clients would reuse many of the same js files they'd already have cached from previous visits. In practice this doesn't work because some base level thing that many pieces inherit from is constantly changing so you never get the same vendor.js file out between builds.

The issue seems to be around a randomly generated key in the output like globalThis.__sveltekit_zp1tl where that hash changes every build. That shows up as the main difference in entry.{hash}.js which many other files then import. image image

I thought this should work since Richard Harris actually raised this bug with Vite: https://github.com/vitejs/vite/issues/11911

Reproduction

  1. pnpm create svelte@latest deterministic-build
  2. press enter a bunch. none of these settings matter. Same issue appears in Typescript vs JS, adding eslint, etc, or even doing it in npm instead of pnpm
  3. cd deterministic-build
  4. pnpm i
  5. pnpm build. copy output
  6. pnpm build. copy output
  7. compare outputs. Notice some files change

Logs

> deterministic-build@0.0.1 build
> vite build

vite v5.2.11 building SSR bundle for production...
"confetti" is imported from external module "@neoconfetti/svelte" but never used in "src/routes/sverdle/+page.svelte".
✓ 109 modules transformed.
vite v5.2.11 building for production...
✓ 92 modules transformed.
.svelte-kit/output/client/_app/version.json                                                         0.03 kB │ gzip:  0.05 kB
.svelte-kit/output/client/.vite/manifest.json                                                       7.12 kB │ gzip:  0.99 kB
.svelte-kit/output/client/_app/immutable/assets/fira-mono-greek-ext-400-normal.CsqI23CO.woff2       7.51 kB
.svelte-kit/output/client/_app/immutable/assets/fira-mono-cyrillic-400-normal.36-45Uyg.woff2        9.10 kB
.svelte-kit/output/client/_app/immutable/assets/fira-mono-greek-400-normal.C3zng6O6.woff2          10.52 kB
.svelte-kit/output/client/_app/immutable/assets/fira-mono-latin-ext-400-normal.D6XfiR-_.woff2      11.36 kB
.svelte-kit/output/client/_app/immutable/assets/fira-mono-cyrillic-ext-400-normal.B04YIrm4.woff2   15.77 kB
.svelte-kit/output/client/_app/immutable/assets/fira-mono-latin-400-normal.DKjLVgQi.woff2          16.28 kB
.svelte-kit/output/client/_app/immutable/assets/fira-mono-all-400-normal.B2mvLtSD.woff             77.36 kB
.svelte-kit/output/client/_app/immutable/assets/svelte-welcome.0pIiHnVF.webp                      115.47 kB
.svelte-kit/output/client/_app/immutable/assets/svelte-welcome.VNiyy3gC.png                       360.81 kB
.svelte-kit/output/client/_app/immutable/assets/5.CU6psp88.css                                      0.80 kB │ gzip:  0.35 kB
.svelte-kit/output/client/_app/immutable/assets/2.Cs8KR-Bb.css                                      1.47 kB │ gzip:  0.53 kB
.svelte-kit/output/client/_app/immutable/assets/4.DOkkq0IA.css                                      3.78 kB │ gzip:  1.06 kB
.svelte-kit/output/client/_app/immutable/assets/0.CT0x_Q5c.css                                      5.15 kB │ gzip:  1.66 kB
.svelte-kit/output/client/_app/immutable/chunks/index.R8ovVqwX.js                                   0.03 kB │ gzip:  0.05 kB
.svelte-kit/output/client/_app/immutable/entry/start.kuqVoxG5.js                                    0.07 kB │ gzip:  0.08 kB
.svelte-kit/output/client/_app/immutable/chunks/stores.CyV73Wv9.js                                  0.23 kB │ gzip:  0.17 kB
.svelte-kit/output/client/_app/immutable/chunks/index.Ice1EKvx.js                                   0.51 kB │ gzip:  0.34 kB
.svelte-kit/output/client/_app/immutable/nodes/1.DgAi-rhN.js                                        0.84 kB │ gzip:  0.52 kB
.svelte-kit/output/client/_app/immutable/nodes/3.BqQOub2U.js                                        1.57 kB │ gzip:  0.96 kB
.svelte-kit/output/client/_app/immutable/chunks/scheduler.Dk-snqIU.js                               2.25 kB │ gzip:  1.05 kB
.svelte-kit/output/client/_app/immutable/nodes/5.CwxmUzn6.js                                        2.35 kB │ gzip:  1.11 kB
.svelte-kit/output/client/_app/immutable/nodes/2.BMQFqo-e.js                                        5.48 kB │ gzip:  2.60 kB
.svelte-kit/output/client/_app/immutable/chunks/index.DDRweiI9.js                                   6.09 kB │ gzip:  2.57 kB
.svelte-kit/output/client/_app/immutable/entry/app.D6zuvAPi.js                                      6.64 kB │ gzip:  2.65 kB
.svelte-kit/output/client/_app/immutable/nodes/0.qacZO6So.js                                        8.77 kB │ gzip:  3.57 kB
.svelte-kit/output/client/_app/immutable/nodes/4.D_o_hs5U.js                                       17.08 kB │ gzip:  7.07 kB
.svelte-kit/output/client/_app/immutable/chunks/entry.DI0Mx0P3.js                                  27.97 kB │ gzip: 10.97 kB
✓ built in 248ms
.svelte-kit/output/server/.vite/manifest.json                                                       7.17 kB
.svelte-kit/output/server/_app/immutable/assets/fira-mono-greek-ext-400-normal.CsqI23CO.woff2       7.51 kB
.svelte-kit/output/server/_app/immutable/assets/fira-mono-cyrillic-400-normal.36-45Uyg.woff2        9.10 kB
.svelte-kit/output/server/_app/immutable/assets/fira-mono-greek-400-normal.C3zng6O6.woff2          10.52 kB
.svelte-kit/output/server/_app/immutable/assets/fira-mono-latin-ext-400-normal.D6XfiR-_.woff2      11.36 kB
.svelte-kit/output/server/_app/immutable/assets/fira-mono-cyrillic-ext-400-normal.B04YIrm4.woff2   15.77 kB
.svelte-kit/output/server/_app/immutable/assets/fira-mono-latin-400-normal.DKjLVgQi.woff2          16.28 kB
.svelte-kit/output/server/_app/immutable/assets/fira-mono-all-400-normal.B2mvLtSD.woff             77.36 kB
.svelte-kit/output/server/_app/immutable/assets/svelte-welcome.0pIiHnVF.webp                      115.47 kB
.svelte-kit/output/server/_app/immutable/assets/svelte-welcome.VNiyy3gC.png                       360.81 kB
.svelte-kit/output/server/_app/immutable/assets/_page.CU6psp88.css                                  0.80 kB
.svelte-kit/output/server/_app/immutable/assets/_page.BBloWWo2.css                                  1.45 kB
.svelte-kit/output/server/_app/immutable/assets/_page.DOkkq0IA.css                                  3.78 kB
.svelte-kit/output/server/_app/immutable/assets/_layout.c5uvFHuT.css                                5.40 kB
.svelte-kit/output/server/chunks/prod-ssr.js                                                        0.04 kB
.svelte-kit/output/server/entries/pages/_page.ts.js                                                 0.05 kB
.svelte-kit/output/server/chunks/index3.js                                                          0.08 kB
.svelte-kit/output/server/entries/pages/about/_page.ts.js                                           0.13 kB
.svelte-kit/output/server/entries/pages/sverdle/how-to-play/_page.ts.js                             0.13 kB
.svelte-kit/output/server/chunks/client.js                                                          0.28 kB
.svelte-kit/output/server/internal.js                                                               0.31 kB
.svelte-kit/output/server/entries/fallbacks/error.svelte.js                                         0.47 kB
.svelte-kit/output/server/chunks/stores.js                                                          0.54 kB
.svelte-kit/output/server/entries/pages/about/_page.svelte.js                                       1.07 kB
.svelte-kit/output/server/chunks/index2.js                                                          1.33 kB
.svelte-kit/output/server/chunks/index.js                                                           2.10 kB
.svelte-kit/output/server/chunks/ssr.js                                                             4.00 kB
.svelte-kit/output/server/chunks/exports.js                                                         5.96 kB
.svelte-kit/output/server/chunks/internal.js                                                        6.03 kB
.svelte-kit/output/server/entries/pages/sverdle/how-to-play/_page.svelte.js                         6.47 kB
.svelte-kit/output/server/entries/pages/_page.svelte.js                                            13.48 kB
.svelte-kit/output/server/entries/pages/_layout.svelte.js                                          14.67 kB
.svelte-kit/output/server/entries/pages/sverdle/_page.svelte.js                                    23.42 kB
.svelte-kit/output/server/index.js                                                                 90.30 kB
.svelte-kit/output/server/entries/pages/sverdle/_page.server.ts.js                                146.12 kB
✓ built in 1.01s

Run npm run preview to preview your production build locally.

> Using @sveltejs/adapter-auto
  Could not detect a supported production environment. See https://kit.svelte.dev/docs/adapters to learn how to configure your app to run on the platform of your choosing
  ✔ done

System Info

System:
    OS: macOS 14.4.1
    CPU: (16) arm64 Apple M3 Max
    Memory: 2.59 GB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 21.6.0 - /usr/local/bin/node
    npm: 10.3.0 - /usr/local/bin/npm
    pnpm: 9.1.0 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 125.0.6422.78
    Safari: 17.4.1
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.2.1
    @sveltejs/kit: ^2.0.0 => 2.5.10
    @sveltejs/vite-plugin-svelte: ^3.0.0 => 3.1.0
    svelte: ^4.2.7 => 4.2.17
    vite: ^5.0.3 => 5.2.11

Severity

serious, but I can work around it

Additional Information

No response

Conduitry commented 6 months ago

You need to set https://kit.svelte.dev/docs/configuration#version to something consistent; otherwise, it uses the current timestamp, which changes every build, affecting the hashes.

rory-orennia commented 6 months ago

@Conduitry Ohh thank you! That was definitely it. I guess now my concern is, how is this supposed to work in the case of making a vendor.js file? Unless I hardcode the version to something and then ignore the svelte version handling, I'm still going to get a different vendor.js file every time I do a new commit (assuming you tie version to git like is suggested). I think even if I manually pulled this version check out into another chunk, it would be referenced by most other client chunks in the app and thus they would also change their hash.

rory-orennia commented 6 months ago

Here's me changing the svelte.config.js -> version -> name from 1 to 2 and it basically changing every client chunk image

mquandalle commented 6 months ago

If two compiled files across two distincts app versions are exactly the same, why not keep the same file name to avoid unnecessary cache invalidation on the client?

rory-orennia commented 6 months ago

If two compiled files across two distincts app versions are exactly the same, why not keep the same file name to avoid unnecessary cache invalidation on the client?

That's the problem. They aren't exactly the same because some base level sveltekit code gets changed, and then most client code chunks import that change, which causes them to change because the hash they reference (eg. import somebasefile.constantlychanginghash.js) has changed.

If the cause of all of this is the version check code, I think we need to find a way to make that code not bleed into every client chunk

rory-orennia commented 6 months ago

@eltigerchino @Conduitry Do you want me to close this ticket and open a new one that is the new problem? (Version changes cause most client chunks to generate a new hash despite no other changes). Or do you want me to rename this one instead?

eltigerchino commented 6 months ago

@eltigerchino @Conduitry Do you want me to close this ticket and open a new one that is the new problem? (Version changes cause most client chunks to generate a new hash despite no other changes). Or do you want me to rename this one instead?

Yes, renaming this one would be great. Thanks!

matindow commented 5 months ago

Are there any proposals/thoughts for how to address this?

How much worse would it be if the content in version.json were replaced with something like a junction map of component names => file paths that all of the chunks referenced dynamically? I am assuming there are a lot of really great/important benefits to being able to hardcode a static file import into all of the chunks that make this a non starter?

I'm trying to think through other ways of doing this version check, and everything seems to come back to the same frictions.

I do agree that incrementing the version number should intuitively not cascade into a new hash for unchanged files in your project, though. Seems not great even aside from the terrible caching issues.