Skip to content

[build] importing from hashed chunks makes caching terribly ineffective #6773

Description

@jacekkarczmarczyk

Update

I've published a plugin that solves the issue for me: https://github.com/jacekkarczmarczyk/importmap-plugin
See #6773 (comment) 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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions