1- import { readFileSync , appendFileSync , existsSync } from "node:fs" ;
1+ import { readFileSync , existsSync } from "node:fs" ;
22import { resolve } from "node:path" ;
33import tsconfigPaths from "vite-tsconfig-paths" ;
44import react from "@vitejs/plugin-react" ;
@@ -9,21 +9,30 @@ import dts from "vite-plugin-dts";
99const whenProductionBuild = ( mode : string ) => mode === "production" ;
1010
1111/**
12- * Appends the pre-generated fonts.generated.css to dist/app-shell.css
13- * after Vite finishes bundling. This avoids Vite trying to resolve woff2
14- * urls during build while still including fonts in the default styles export.
12+ * Appends the pre-generated fonts.generated.css to the CSS bundle asset
13+ * during generation. This avoids Vite trying to resolve woff2 urls during
14+ * build while still including fonts in the default styles export.
15+ *
16+ * Using generateBundle (instead of closeBundle/writeBundle) ensures the file
17+ * is written to disk only once, preventing spurious change-detection in
18+ * downstream dev servers during watch mode.
1519 */
1620function appendFonts ( props : { appendCSSFile : string } ) : Plugin {
1721 return {
1822 name : "append-fonts" ,
19- closeBundle ( ) {
23+ enforce : "post" ,
24+ generateBundle ( _ , bundle ) {
2025 const fontsPath = resolve ( import . meta. dirname , "src/assets/fonts.generated.css" ) ;
2126 if ( ! existsSync ( fontsPath ) ) {
2227 this . error ( "src/assets/fonts.generated.css not found. Run `pnpm generate:fonts` first." ) ;
2328 }
24- const dist = resolve ( import . meta. dirname , "dist" ) ;
2529 const fontCss = readFileSync ( fontsPath , "utf8" ) ;
26- appendFileSync ( resolve ( dist , props . appendCSSFile ) , "\n" + fontCss ) ;
30+ const cssAsset = Object . values ( bundle ) . find (
31+ ( asset ) => asset . type === "asset" && asset . fileName . endsWith ( ".css" ) ,
32+ ) ;
33+ if ( cssAsset && cssAsset . type === "asset" ) {
34+ cssAsset . source += "\n" + fontCss ;
35+ }
2736 } ,
2837 } ;
2938}
0 commit comments