Parcel incorrectly rewrites `url()` paths in CSS during prod build resulting in asset loading failures if styles are inlined into HTML
🐛 bug report
When building for production a font loaded from within a @font-face declaration using source: url(), inlined into an HTML <style> tag is referenced via a relative path generated by parcel. As a result the font is not loaded correctly because the path is wrong. It does work when the user is at the / route in the browser but when the user is at any other route like /someroute the font does not get loaded correctly.
It seems like this is no problem in a dev mode, because there the code is referenced differently (via @import vs inlined directly ). I guess the relative path is ok when the font is loaded from a separate CSS file since the path is then relative to the CSS file.
But when inlining the CSS into HTML this won't work because then the path is relative to the current URL in the browser.
🎛 Configuration (.babelrc, package.json, cli command)
No babel or parcelrc
🤔 Expected Behavior
The font should be loaded regardless of the current path in the browser bar.
Parcel generates the following @font-face line (formatted for legibility):
<style>
@font-face {
font-family: Work Sans;
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url(WorkSans-VariableFont_wght.fe5ed19c.woff2) format("woff2"); /* relative path will only work on index / route */
unicode-range: U+??, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC,
U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
</style>
If it generated this instead everything would be fine.
<style>
@font-face {
font-family: Work Sans;
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url(/WorkSans-VariableFont_wght.fe5ed19c.woff2) format("woff2"); /* starting with a slash, now everything is fine */
unicode-range: U+??, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC,
U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
</style>
😯 Current Behavior
The font is not loaded correctly because the path is not correct.
💁 Possible Solution
Parcel currently generates a relative path for the url() function, which is relative to the CSS stylesheet. So to fix it an absolute path could be used (starting with a slash) OR the path needs to be made relative to the HTML when the styles are inlined.
🔦 Context
I ran into this after trying to optimize page load speed. First I had the @font-face declaration in a separately loaded CSS file via <link> tag. When I moved it into a <style> tag on the HTML head I ran into this issue.
💻 Code Sample
/* src/assets/css/fonts.css */
@font-face {
font-family: "Work Sans";
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url(../fonts/WorkSans/WorkSans-VariableFont_wght.woff2) format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
Font is located at src/assets/fonts/WorkSans/WorkSans-VariableFont_wght.woff2
<!-- src/index.html -->
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<title>App</title>
<!-- Loading it from a separate CSS works <link rel="stylesheet" href="./assets/css/fonts.css" /> -->
<style>
@import "./assets/css/fonts.css"; /* css gets inlined, but the path used in url() is not adjusted accordingly */
</style>
</head>
<body id="body" style="font-family: 'Work Sans'">
This text will not show up in the work sans font if the path in the browser bar is anything other than / .
</body>
</html>
🌍 Your Environment
| Software | Version(s) |
|---|---|
| Parcel | 2.8.3 |
| Node | 16.19.0 |
| npm/Yarn | npm 8.19.3 |
| Operating System | MacOS Ventura |
Same behavior with "url:*" imports in a tag. Repro here:
https://github.com/maxburs/parcel-url-import-repro
- npm start
- Open localhost:3000/test
- Incorrect url is logged in console (includes "test" in url)
<script type="module">
import testUrl from "url:./test.json";
console.log({ testUrl });
</script>
Issue still persists
Still
Issue still persists
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.
Issue still persists