[build] importing from hashed chunks makes caching terribly ineffective
See original GitHub issueUpdate
I’ve published a plugin that solves the issue for me: https://github.com/jacekkarczmarczyk/importmap-plugin See https://github.com/vitejs/vite/issues/6773#issuecomment-1308048405 for example usage in the issue reproduction repository
Describe the bug
Built files import other files which names contain content hash. So if the chunk A
changes its contents then the output file changes its hash (A.123.js
becomes A.234.js
). So if there’s other file that imports from A
chunk then it also changes its contents and hash because import {...} from 'A.123.js'
becomes import {...} from 'A.234.js'
.
Imagine now that I’m defining an env variable with build time. Main chunk imports this file to show the build time in App.vue
. However main chunk exports the following vue related function:
function lc (e, t, r, n, i, a, o, s) {
var f = typeof e == 'function' ? e.options : e;
t && (f.render = t, f.staticRenderFns = r, f._compiled = !0), n && (f.functional = !0), a && (f._scopeId = 'data-v-' + a);
var u;
if (o ? (u = function (d) {
d = d || this.$vnode && this.$vnode.ssrContext || this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext, !d && typeof __VUE_SSR_CONTEXT__ != 'undefined' && (d = __VUE_SSR_CONTEXT__), i && i.call(this, d), d && d._registeredComponents && d._registeredComponents.add(o);
...
that is being imported by all component chunks (note that this is just example, depending on the project there might be other user defined functions that are exported from main chunk, also in my actual project I’ve extracted vendors to separate chunks but still vue related functions were exported from main chunk).
So now when I build again env chunk will change its contents and hash/name, therefore main chunk will change it’s contents and hash/name, therefor ALL other chunks will change their names. That makes caching very innefective. Also worth to mention that that technique worked fine in vue-cli - when build time changed only single small env.hash.js chunk was changed, all others remained unchanged (EDIT: there’s also relatively small runtime chunk that also was changed)
Reproduction
https://github.com/jacekkarczmarczyk/vite-chunks-very-very-bad
Run yarn && yarn build && git add . && yarn build && git status
It behaves the same when displaying build time is moved to an async Home.vue route component, in this case hash change of main chunk is definitely unjustified
System Info
System:
OS: Windows 10 10.0.19043
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Memory: 3.34 GB / 15.87 GB
Binaries:
Node: 16.11.0 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
npm: 8.0.0 - C:\Program Files\nodejs\npm.CMD
npmPackages:
@vitejs/plugin-legacy: ^1.6.4 => 1.6.4
vite: ^2.7.2 => 2.7.13
Used Package Manager
yarn
Logs
No response
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn’t already an issue that reports the same bug to avoid creating a duplicate.
- Make sure this is a Vite issue and not a framework-specific issue. For example, if it’s a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/core instead.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
Additional notes
I believe that this more like rollup issue (or whatever is used for generating chunks) but if it’s possible to fix it by using some rollup’s settings then vite should use these settings by default. And if it’s not possible to fix it by using different settings then I think that chosing rollup was not the best choice. This page https://bundlers.tooling.report/hashing/js-import-cascade/ and this https://bundlers.tooling.report/hashing/avoid-cascade/ however suggest that this should not be an issue for rollup
Issue Analytics
- State:
- Created 2 years ago
- Reactions:9
- Comments:9
Top GitHub Comments
I had a very similar problem and came up with this hacky solution:
When adding
Cache-Control: must-revalidate, max-age=0
for /assets/index.js (my entry file) andCache-Control: public, max-age=31557600
to all other assets it seems to work fine but I had no chance to really test it yet and I’m quite new to Vite/Rollup and ESM in general so this might be a terrible idea for some reason I don’t know…Every kind of feedback is very appreciated! 😃
For anyone interested - here’s a proof of concept based on @lukastaegert’s comment in rollup repo:
https://github.com/jacekkarczmarczyk/importmap-plugin (UPDATE: now supports SystemJS)
Feel free to steal the code and create a proper vite/rollup plugin. Any comments welcome
Plugin applied to the original reproduction (https://github.com/jacekkarczmarczyk/vite-chunks-very-very-bad/tree/main-stable-hash-plugin -
yarn && yarn build && git add . && yarn build && git status
) - working as expected (only modified chunk changed the hash):