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

Circular dependencies in hash create large browser cache invalidation between code releases #10636

Open
7 tasks done
jfparadis-appomni opened this issue Oct 25, 2022 · 4 comments
Labels
p2-nice-to-have Not breaking anything but nice to have (priority)

Comments

@jfparadis-appomni
Copy link

Describe the bug

Vite bundles both the Vue library and its own helpers into the top index chunk, and because all components import Vue and use those helpers, then all JavaScript chunks import index.

The impact is that a change to one component causes a hash change to all components which cause a large browser cache invalidation between code releases.

Reproduction

https://github.com/jf-paradis/vite-circular-dependencies

Steps to reproduce

Since the top index indirectly imports all components, any change in a single component changes that component hash, then cascades up to index, then cascades back down to all components.

The impact can be seen here as follow:

  1. Checkout the code at https://github.com/jf-paradis/vite-circular-dependencies

  2. Run npm install

  3. Build the app, save the list of hash changes (lines omitted for clarity):

% npm run build

dist/assets/vue.5532db34.svg        0.48 KiB
dist/index.html                     0.44 KiB
dist/assets/HelloWorld.2a228e41.js  0.26 KiB / gzip: 0.21 KiB
dist/assets/Panel.37d1d496.js       0.19 KiB / gzip: 0.17 KiB
dist/assets/ByByeWorld.22d2d993.js  0.26 KiB / gzip: 0.22 KiB
dist/assets/index.3f6467e9.css      1.21 KiB / gzip: 0.63 KiB
dist/assets/index.7837aefd.js      52.55 KiB / gzip: 21.24 KiB
  1. Change one of the components, for example change "Hello" to "Hello!" in HelloWorld.vue, and rebuild:
% npm run build

dist/assets/vue.5532db34.svg        0.48 KiB
dist/index.html                     0.44 KiB
dist/assets/HelloWorld.85a3b193.js  0.26 KiB / gzip: 0.21 KiB
dist/assets/Panel.9626c151.js       0.19 KiB / gzip: 0.17 KiB
dist/assets/ByByeWorld.d27c7ad5.js  0.26 KiB / gzip: 0.22 KiB
dist/assets/index.3f6467e9.css      1.21 KiB / gzip: 0.63 KiB
dist/assets/index.6acde798.js       52.55 KiB / gzip: 21.25 KiB
  1. Notice that the hash of ByeByeWorld.js has changed, even if that component doesn't import HelloWorld.vue. In fact, all JavaScript files have new hashes.

This can be explained becuase all chunks import index:

% grep -rEo "/index\.\w+\.js" dist

dist/index.html:/index.6acde798.js
dist/assets/Panel.9626c151.js:/index.6acde798.js
dist/assets/ByByeWorld.d27c7ad5.js:/index.6acde798.js
dist/assets/HelloWorld.85a3b193.js:/index.6acde798.js

Workaround

  1. Uncomment the manualChunks function in vite.config.ts.

  2. Build the app

% npm run build

dist/assets/vue.5532db34.svg        0.48 KiB
dist/index.html                     0.59 KiB
dist/assets/index.caa16f9f.js       1.13 KiB / gzip: 0.58 KiB
dist/assets/vite.288ff0a5.js        1.26 KiB / gzip: 0.67 KiB
dist/assets/HelloWorld.78a2bc30.js  0.26 KiB / gzip: 0.22 KiB
dist/assets/Panel.2ce48d7b.js       0.19 KiB / gzip: 0.17 KiB
dist/assets/ByByeWorld.1350f4f8.js  0.27 KiB / gzip: 0.22 KiB
dist/assets/index.3f6467e9.css      1.21 KiB / gzip: 0.63 KiB
dist/assets/vendor.3885daba.js     50.40 KiB / gzip: 20.29 KiB
  1. Change one of the components again, for example revert "Hello!" to "Hello" in HelloWorld.vue, and rebuild:
dist/assets/vue.5532db34.svg        0.48 KiB
dist/index.html                     0.59 KiB
dist/assets/index.15a1828f.js       1.13 KiB / gzip: 0.58 KiB
dist/assets/HelloWorld.5cb36190.js  0.26 KiB / gzip: 0.22 KiB
dist/assets/vite.288ff0a5.js        1.26 KiB / gzip: 0.67 KiB
dist/assets/Panel.2ce48d7b.js       0.19 KiB / gzip: 0.17 KiB
dist/assets/ByByeWorld.1350f4f8.js  0.27 KiB / gzip: 0.22 KiB
dist/assets/index.3f6467e9.css      1.21 KiB / gzip: 0.63 KiB
dist/assets/vendor.3885daba.js     50.40 KiB / gzip: 20.29 KiB

Notice that the hash of ByeByeWorld.js has NOT changed. In fact, only HelloWorld.js and index.js have changed.

  1. This can be explained because none of the chunks are importing index:
% grep -rEo "/index\.\w+\.js" dist        

dist/index.html:/index.15a1828f.js

System Info

Binaries:
    Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v16.16.0/bin/npm
  npmPackages:
    @vitejs/plugin-vue: ^3.1.0 => 3.1.2 
    vite: ^3.1.0 => 3.1.8

Used Package Manager

npm

Logs

No response

Validations

@sapphi-red
Copy link
Member

Duplicate of #6773

@sapphi-red sapphi-red marked this as a duplicate of #6773 Oct 26, 2022
@sapphi-red sapphi-red closed this as not planned Won't fix, can't repro, duplicate, stale Oct 26, 2022
@sapphi-red sapphi-red added duplicate This issue or pull request already exists and removed pending triage labels Oct 26, 2022
@jfparadis-appomni
Copy link
Author

jfparadis-appomni commented Oct 26, 2022

@sapphi-red This is not a straight duplicate of #6773

Here's how I prevent the Vite helper functions mentioned from being added to main index chunk:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    target: 'ES2020',
    rollupOptions: {
      output: {
        // Workaround: Vite is bundling its plugins to the main index chunk, 
        // causing circular dependencies and cascading hash changes.
        manualChunks(id) {
          if (id.startsWith('vite/') || id.startsWith('\0vite/')) {
            // Put the Vite modules and virtual modules (beginning with \0) into a vite chunk.
            return 'vite';
          }
        },
      },
    },
  },
  plugins: [vue()]
});

@sapphi-red sapphi-red reopened this Oct 27, 2022
@sapphi-red sapphi-red added pending triage p2-nice-to-have Not breaking anything but nice to have (priority) and removed duplicate This issue or pull request already exists pending triage labels Oct 27, 2022
@sapphi-red
Copy link
Member

Thanks. I now understand the difference.
I guess this will be fixed in Vite 4 because we are going to update rollup to v3 that includes rollup/rollup#4543.

@jacekkarczmarczyk
Copy link

In other words, a leaf changes the trunk AND ALL LEAVES.

isn't it what my additional examples show?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p2-nice-to-have Not breaking anything but nice to have (priority)
Projects
None yet
Development

No branches or pull requests

3 participants