fresh icon indicating copy to clipboard operation
fresh copied to clipboard

Vite plugin: fonts from `node_modules` does not load in dev mode

Open cailloumajor opened this issue 3 months ago • 6 comments

Starting from @fresh/plugin-vite v0.9.11, using fonts from node_modules does not work in development mode.

In production build, the fonts are bundled and used as expected.

Up to version 0.9.10 of the plugin, using fonts from node_modules worked as expected, and did not involve fetching the font file by the browser.

Reproduction

  1. Scaffold a fresh project
> deno run -A jsr:@fresh/init .

 🍋 Fresh: The next-gen web framework. 
    version 2.0.2

The target directory is not empty (files could get overwritten). Do you want to continue anyway? [y/N] y
Set up Tailwind CSS for styling? [y/N] y
Do you use VS Code? [y/N] y

Project initialized!

Run deno task dev to start the project. CTRL-C to stop.

Stuck? Join our Discord https://discord.gg/deno 

Happy hacking! 🦕

  1. Install a font from npm
> deno install npm:@fontsource-variable/roboto

  1. Make Tailwind use the font
diff --git a/assets/styles.css b/assets/styles.css
index 5d8109d..79c66af 100644
--- a/assets/styles.css
+++ b/assets/styles.css
@@ -1,4 +1,11 @@
 @import "tailwindcss";
+
+@import "@fontsource-variable/roboto";
+
+@theme {
+  --font-sans: "Roboto Variable";
+}
+
 .fresh-gradient {
   background-color: rgb(134, 239, 172);
   background-image: linear-gradient(

  1. Start the development server
> deno task dev

  1. Browse the served page and see in the browser console failure to fetch the font file
Image

cailloumajor avatar Sep 13 '25 16:09 cailloumajor

Works for me, commands used:

deno run -Ar jsr:@fresh/init fresh-fonts
cd fresh-fonts
deno add npm:@fontsource-variable/roboto --allow-scripts

assets/styles.css:

@import "tailwindcss";
@import "@fontsource-variable/roboto";
@theme {
  --font-sans: "Roboto Variable";
}
.fresh-gradient {
  background-color: rgb(134, 239, 172);
  background-image: linear-gradient(
    to right bottom,
    rgb(219, 234, 254),
    rgb(187, 247, 208),
    rgb(254, 249, 195)
  );
}

Terminal output:

$ deno task dev
  VITE v7.1.5  ready in 1625 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
GET http://localhost:5173/
Shared value hello
GET http://localhost:5173/node_modules/.deno/@[email protected]/node_modules/@fontsource-variable/roboto/files/roboto-latin-wght-normal.woff2

Screenshot: Image

fry69 avatar Sep 13 '25 17:09 fry69

Repro repo: https://github.com/fry69/fresh-vite-fonts-repro

fry69 avatar Sep 13 '25 17:09 fry69

@fry69 maybe I am wrong, but the font on your screenshot is definitely not Roboto. Expected font rendering is as below.

Image

Did you check your browser console after loading the page? I tested again and it shows an error.

cailloumajor avatar Sep 13 '25 17:09 cailloumajor

@cailloumajor ACK, I can reproduce the problem now.

Log from the browser console:

GET
http://localhost:5173/node_modules/.deno/@[email protected]/node_modules/@fontsource-variable/roboto/files/roboto-latin-wght-normal.woff2
[HTTP/1.1 404 Not Found 9ms]

downloadable font: download failed (font-family: "Roboto Variable" style:normal weight:100..900 stretch:100 src index:0): status=2147746065 source: http://localhost:5173/node_modules/.deno/@[email protected]/node_modules/@fontsource-variable/roboto/files/roboto-latin-wght-normal.woff2 

fry69 avatar Sep 13 '25 17:09 fry69

@cailloumajor Is that even supposed to work?

The fonts sources need to be put into the bundle and the URLs to them need to be rewritten. Is that supposed to happen automatically?

Update: It seems so

Extras / why the plain @import in assets/styles.css failed for you

  • Fontsource expects the bundler to rewrite @font-face src: url(@fontsource-variable/...). When that rewrite doesn’t happen, the browser tries to fetch the literal path and gets 404. Fontsource docs specifically mention this bundler rewriting behavior.
  • With Deno’s npm compatibility, package files often live in a different place than a normal node_modules, which can confuse Vite’s default dev-server lookup unless you import the CSS in the client bundle or make Vite explicitly aware of that path.

fry69 avatar Sep 13 '25 18:09 fry69

@cailloumajor Is that even supposed to work?

I suppose: as I stated in the issue description, it worked up to v0.9.10 of the Vite plugin. Additionally, loading fonts from node_modules works seamlessly in a frontend project I made using Vue with Vite.

cailloumajor avatar Sep 14 '25 13:09 cailloumajor