Closed goldmerc closed 1 month ago
The problem occurs because the CSS is being loaded from the Vite dev server during development (e.g. http://127.0.0.1:5173/resources/css/app.css). When the browser sees the absolute path in the CSS (i.e. /fonts/AvenirLTStd-Roman.woff
), it loads from the same host as the CSS.
One option is to load the CSS via the JavaScript entrypoint instead of having it as a dedicated entrypoint. E.g:
// app.js
import '../css/app.css';
import './bootstrap';
(Don't forget to remove the CSS entrypoint from the Vite config and @vite
helper)
This will cause Vite to inject the CSS into the page instead of linking to it during development, and so the browser will load the absolute path via the Laravel host instead. This can lead to a "flash of unstyled content" (FOUC) during development if your page is server-rendered (rather than client-rendered via something like Vue/React) because the JS code needs to initialize before the CSS can be injected.
If the FOUC drives you crazy (like it does for me), a workaround would be something like this in your vite.config.js
file:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig(({ command }) => {
const alias = command === 'serve' ? {
'/fonts': '/public/fonts',
}: {}
return {
resolve: {
alias,
},
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
};
});
This will cause Vite to rewrite the absolute path from /fonts/AvenirLTStd-Roman.woff
to /public/fonts/AvenirLTStd-Roman.woff
during development only, causing the browser to load the font via http://127.0.0.1:5173/public/fonts/AvenirLTStd-Roman.woff, which will work because the Vite dev server will serve any asset from the root directory of your project.
There are potentially other options, but this is all I can think of now.
Personally, if I were using server-rendered content, I think I'd use a relative path and let Vite version it.
@jessarcher thanks! super helpful! I tried the alias method and that works great.
I had previously tried a relative path and that worked fine too. May I ask, what is the benefit of versioning fonts? I don't understand why you would need them in the build? The file size seems the same pre and post build, so there's no compression happening. Coding is just a hobby for me, so there's probably some reason I'm not aware of. Apologies for picking your brain!
It's great that you helped me but I wonder if the laravel docs need updating on this issue? They are quite clear that when "referencing assets in your application's HTML, CSS, or JS" using an absolute path Vite won't include them in the build. There's no warning that this will break your dev environment if you have absolute urls in your CSS. I spent quite a while searching on this issue and found several forum posts (laracasts, etc) where people were struggling with this same issue, both with fonts and images referenced from CSS. No one managed to answer those posts properly. You're the first person I've found who's written something explaining what's actually the problem and a solution. It took me a few hours to convince myself that I had actually migrated from Mix to Vite properly and the issue was not with my configuration.
Thanks again for your help and time.
Hey @goldmerc, I don't think there's much benefit to versioning fonts unless you're updating them and want to ensure the user has the latest version. However, I don't see any harm in versioning them, and it avoids this problem and keeps things consistent with other assets.
I agree the docs could be improved. I've submitted a small change at https://github.com/laravel/docs/pull/9824 to warn people about this issue. I'm hesitant to "officially" recommend the alias approach in the docs because it feels like more of a workaround, and I've only briefly tested it. Hopefully, determined folks will find this thread if they want to get it to work.
Vite Plugin Version
1.0.5
Laravel Version
11.20.0
Node Version
22.4.1
NPM Version
10.8.1
Operating System
macOS
OS Version
14.4.1
Web browser and version
Chrome 127.0.6533.89 (Official Build) (arm64)
Running in Sail?
No
Description
The laravel docs says: -
If I use an absolute path in my css (for instance for a font which doesn't need versioning), and then run npm run dev, vite still tries to serve the font from the vite server...
http://127.0.0.1:5173/fonts/AvenirLTStd-Roman.woff
Which results in a 404.
Perhaps I'm missing something but if Vite is not including the item in the production build, why is it trying to serve it in dev? The behaviour I would expect would be to leave it using the absolute path, which is what happens in the production build.
Steps To Reproduce
repo to reproduce issue - https://github.com/goldmerc/vite-asset