Skip to content

Use import maps for better caching #4482

Open
@Rich-Harris

Description

@Rich-Harris

Describe the problem

Suppose you have three pages, /one, /two and /three, that each depend on Widget.svelte. Because that component is used by multiple pages, Vite will create a chunk for it with a hashed name: chunks/Widget-abc123.js.

Since routes are also code-split, the pages will have their own chunks — pages/one-def234.js, pages/two-ghi345.js and pages/three-jkl456.js. Each will have an import declaration like this:

import Widget from '../chunks/Widget-abc123.js';

The hashing allows us to treat these assets as immutable, which means that repeat visitors won't have to redownload those chunks as long as they don't change.

But.

One day we change Widget.svelte without changing /one, /two or /three. Because the hashes are based on content, chunks/Widget-abc123.js is now chunks/Widget-mno567.js. That's fine — we want users to redownload that chunk — but it means that the import declaration now looks like this...

import Widget from '../chunks/Widget-mno567.js';

...which means that the page chunk hashes must also change, even though they're otherwise identical. Suddenly, the user must redownload four chunks (more, in fact, since the main entry point containing the route manifest is also tainted) even though only one module changed.

Obviously this problem isn't unique to SvelteKit, but it's a problem we're well-placed to solve.

Describe the proposed solution

Import maps solve this problem. By mapping stable identifiers to the hashed assets...

<script type="importmap">
{
  "imports": {
    "chunks/Widget": "/_app/chunks/Widget-abc123.js",
    "pages/one": "/_app/pages/one-def234.js",
    ...
  }
}
</script>

...we can import chunks like so:

import Widget from 'chunks/Widget';

Now, changes to Widget.svelte won't taint its consumers — all we need to do is update the import map.

Wrinkles:

  • Import maps aren't yet supported in all browsers. Happily, there's a production-ready solution: https://github.com/guybedford/es-module-shims
  • Generating import declarations with stable identifiers while still generating hashed assets might be tricky — I'm not sure how to do that with Vite. I'm confident we could figure it out though
  • The import map could conceivably grow quite large, perhaps even to the point where the trade-off isn't worth it

Alternatives considered

No response

Importance

nice to have

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions