Skip to content

fix(css): keep deprecated name/originalFileName in synthetic assetFileNames call#22439

Merged
sapphi-red merged 2 commits into
vitejs:mainfrom
ChrisJr404:fix-css-url-relative-base-subfolder
May 14, 2026
Merged

fix(css): keep deprecated name/originalFileName in synthetic assetFileNames call#22439
sapphi-red merged 2 commits into
vitejs:mainfrom
ChrisJr404:fix-css-url-relative-base-subfolder

Conversation

@ChrisJr404
Copy link
Copy Markdown
Contributor

Description

getCssAssetDirname calls the user's assetFileNames once with a fake PreRenderedAsset to find out which directory the emitted CSS will land in. The rolldown migration in 47a4d50 dropped the deprecated name and originalFileName (singular) fields from that synthetic call.

Both fields are flagged @deprecated on rolldown's PreRenderedAsset type, but rolldown still populates them when it really emits the asset. User-provided assetFileNames callbacks routinely branch on chunkInfo.name, including the one in the reproduction for #22434:

assetFileNames(chunkInfo) {
  const name = chunkInfo.name ?? ''
  if (name.endsWith('.css')) return 'css/[name]-[hash].[ext]'
  if (name.match(/\.(png|jpe?g|gif|svg|webp)$/)) return 'img/[name]-[hash].[ext]'
  return '[name]-[hash].[ext]'
}

During the real emit chunkInfo.name is main.css and the CSS lands in css/. During the synthetic call from getCssAssetDirname name is undefined, the css branch is skipped, the fallback [name]-[hash].[ext] is returned, path.dirname of that is ., and so url() rewriting computes paths relative to the build root rather than relative to css/. The CSS ends up containing url(./img/foo-*.png) when it should be url(../img/foo-*.png).

This restores name and originalFileName on the synthetic call so it matches what user code sees during the real emit. The string and undefined (no callback) branches were already correct since they derive the dirname from the pattern itself.

Verification

Reproduced against https://github.com/karlvr/vite-relative-base-bug with vite 8.0.12: emits url(./img/foo-*.png). With this patch the same build emits url(../img/foo-*.png), matching vite 7.

Added a regression test in build.spec.ts that runs a build() programmatically with base: './' and a function assetFileNames that splits CSS into css/ and images into img/. The test asserts the emitted CSS contains url(../img/foo-*.png).

  • pnpm test-unit in packages/vite (747 passed, 4 skipped).
  • VITE_TEST_BUILD=1 pnpm exec vitest run playground/assets/__tests__/relative-base/ (34 passed).
  • VITE_TEST_BUILD=1 pnpm exec vitest run playground/css/__tests__/ (107 passed, 3 skipped).

What is the purpose of this pull request?

  • Documentation update
  • Bug fix
  • New Feature
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the Pull Request Guidelines.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

Closes #22434

…`assetFileNames` call

`getCssAssetDirname` invokes the user's `assetFileNames` callback to
figure out which directory the CSS file ends up in, so url() rewrites
can compute a correct relative path. The rolldown migration dropped
`name` and `originalFileName` (singular) from that synthetic call.

Both fields are marked deprecated in rolldown's `PreRenderedAsset` type
but are still populated for the real asset emit. User callbacks
commonly branch on `chunkInfo.name` (the karlvr/vite-relative-base-bug
repro does), so the synthetic call now misses the css branch and falls
through to the default pattern. The dirname then comes out as `.`
instead of e.g. `css`, and `url(../img/foo.png)` regresses to
`url(./img/foo.png)`.

Restore the two deprecated fields in the synthetic call so it matches
what user code sees during the real emit.

fix vitejs#22434

Signed-off-by: ChrisJr404 <chris@hacknow.com>
@sapphi-red sapphi-red added p2-edge-case Bug, but has workaround or limited in scope (priority) feat: css labels May 14, 2026
@sapphi-red sapphi-red merged commit 8e59c97 into vitejs:main May 14, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat: css p2-edge-case Bug, but has workaround or limited in scope (priority)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSS url() regression in Vite 8 when base is set to ./

2 participants