Skip to content

Conversation

@aprici7y
Copy link
Contributor

Changes

  • Fixes CSS url() references to public assets returning 404 in dev mode when base path is configured
  • Adds rewriteCssUrls() function in packages/astro/src/core/compile/style.ts that applies URL rewriting after preprocessCSS()
  • Uses Vite's production-tested cssUrlRE regex pattern from vite/packages/vite/src/node/plugins/css.ts
  • Rewrites absolute URLs like /fonts/font.woff to /my-base/fonts/font.woff in dev mode
  • Preserves relative paths (./), external URLs (https://), data URIs, and protocol-relative URLs (//)

Root cause: Vite's preprocessCSS() API explicitly does not resolve URLs (docs). During build, Vite's CSS plugin handles URL rewriting, but
in dev mode Astro calls preprocessCSS() directly, bypassing the URL rewriting step.

Closes #14585

Testing

25 unit tests added in packages/astro/test/units/compile/css-base-path.test.js covering:

  • Absolute URL rewriting (7 tests)
  • URLs that should NOT be rewritten (6 tests)
  • Edge cases (4 tests)
  • Complex CSS scenarios (7 tests)
  • Sass/SCSS preprocessing (1 test)

Manual testing:

cd examples/minimal
echo "export default { base: '/my-base/' }" > astro.config.mjs
cat > src/pages/test.astro << 'EOF'
<!DOCTYPE html>
<html>
<head>
  <style>
    body { background: url('/test.png'); }
  </style>
</head>
<body><h1>Test</h1></body>
</html>
EOF

# Dev mode test
pnpm dev
# Open http://localhost:4321/my-base/test
# Verify: <style> tag shows url(/my-base/test.png)

# Build mode test
pnpm build
cat dist/test/index.html
# Verify: CSS contains url(/my-base/test.png)

##Docs

No documentation changes needed. This fix makes existing behavior work correctly - users already expect CSS URLs to respect the base configuration, this just fixes the dev mode bug where it wasn't working.

Fixes CSS url() references to public assets returning 404 in dev mode
when base path is configured. Applies URL rewriting after preprocessCSS()
using Vite's cssUrlRE regex pattern.

Closes withastro#14585
@changeset-bot
Copy link

changeset-bot bot commented Oct 26, 2025

🦋 Changeset detected

Latest commit: bbc1c54

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the pkg: astro Related to the core `astro` package (scope) label Oct 26, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Oct 26, 2025

CodSpeed Performance Report

Merging #14622 will not alter performance

Comparing aprici7y:fix/css-base-path-dev (bbc1c54) with main (f657183)1

Summary

✅ 6 untouched

Footnotes

  1. No successful run was found on main (420836c) during the generation of this report, so f657183 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@matthewp
Copy link
Contributor

looks good overall

@aprici7y
Copy link
Contributor Author

fixed the linting error

const css = result.css[0].code;

// URL should be rewritten to include base
assert.match(css, /url\(['"]?\/my-base\/fonts\/font\.woff2['"]?\)/);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're checking for the value that is statically known, would this perhaps read better?

Suggested change
assert.match(css, /url\(['"]?\/my-base\/fonts\/font\.woff2['"]?\)/);
assert.ok(css.includes('/my-base/fonts/font.woff2'));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first test is more explicit with regex for the full syntax, later ones use .includes() for brevity. open to changing if you prefer.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I somehow missed that, awesome! No need to change anything then

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: astro Related to the core `astro` package (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSS url is replaced to include base path during build but not during dev

3 participants