Skip to content

serve static assets from the build manifest #16565

Description

@Nic-Polumeyv

Describe the problem

The static file server re-derives at boot and request time what the build already computed, and each gap between the two surfaces as a separate bug.

sirv resolves MIME types through its own bundled mrmime. Kit's additions in utils/mime.js reach the copy dev and preview share, but not the one adapter-node bundles, which is why #13753 stayed broken there after #16234. #16564 patches it at the response layer.

sirv sets Vary: Accept-Encoding whenever gzip/brotli are on, but builder.compress only compresses a fixed extension list, so every asset outside that list gets the header without having a variant. #15182 only covered precompress: false. The upstream fix, lukeed/sirv#173, has been open since January.

sirv guesses paths from patterns, so filenames ending in + 404 in production while resolving in dev (#11766, still reproduces on 3.0.2).

It also walks the output with totalist at startup to build a lookup Kit already has, and derives its ETag from mtime rather than content.

Describe the proposed solution

Record what the build knows and serve from it.

manifest.assets already lists the files, and manifest.mimeTypes already maps extension to type through the patched lookup. What's missing is which files builder.compress actually produced .gz/.br for, and a content hash for the ETag. Both are known at adapt time and currently discarded.

Serving then becomes a lookup and a stream. The type comes from the manifest, Vary is set only for files that have a variant, exact keys remove the path-guessing class of bug, and there is no startup walk.

sirv drops out as a consequence rather than as the goal, along with totalist and @polka/url. That also removes mrmime from adapter-node's output, where it is 13.1 KB of a 26.8 KB chunk, all of it a general-purpose table answering questions the build already answered. Exporting the server from @sveltejs/kit/node keeps adapter-node on one copy, since rolldown already holds that entry external.

Alternatives considered

Upstreaming each fix. lukeed/sirv#173 was opened in January by the person who hit the Kit bug and has not been reviewed; sirv last shipped in September 2025 with 12 PRs open.

Patching per symptom, which is what #15182 and #16564 do. Each reproduces a piece of sirv's behaviour outside sirv; #16564 has to re-add the text/html charset that sirv appends itself.

Vendoring sirv's 249 lines as-is. That fixes the MIME case but keeps the runtime re-derivation, so Vary and the ETag stay as they are.

Importance

nice to have

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions