Skip to content

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

Description

@jf-paradis

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    p2-nice-to-haveNot breaking anything but nice to have (priority)

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions