1- import { FileSystemRouter } from "bun" ;
1+ import { FileSystemRouter , type BunFile } from "bun" ;
22import { NJSON } from "next-json" ;
33import { readFileSync , statSync } from "node:fs" ;
4- import { join , relative } from "node:path" ;
4+ import { join , relative , normalize } from "node:path" ;
55import { renderToReadableStream } from "react-dom/server" ;
66import { ClientOnlyError } from "./client" ;
77import { MetaContext , PreloadModule } from "./preload" ;
@@ -14,12 +14,25 @@ export class StaticRouters {
1414 #dependencies! : Record < string , string [ ] > ;
1515 #hashed! : Record < string , string > ;
1616 #cached = new Set < string > ( ) ;
17+ #static_cache: StaticFileCache ;
18+ public baseDir : string ;
19+ public buildDir = ".build" ;
20+ public pageDir = "pages" ;
1721
1822 constructor (
19- public baseDir : string ,
20- public buildDir = ".build" ,
21- public pageDir = "pages"
23+ base : string ,
24+ {
25+ buildDir = ".build" ,
26+ pageDir = "pages" ,
27+ } : {
28+ buildDir ?: string ;
29+ pageDir ?: string ;
30+ } = { }
2231 ) {
32+ this . baseDir = base ;
33+ this . buildDir = buildDir ;
34+ this . pageDir = pageDir ;
35+ this . #static_cache = new StaticFileCache ( join ( base , buildDir ) ) ;
2336 this . reload ( ) ;
2437 }
2538
@@ -59,6 +72,7 @@ export class StaticRouters {
5972 this . #routes_dump = NJSON . stringify ( Object . fromEntries ( this . #routes) , {
6073 omitStack : true ,
6174 } ) ;
75+ this . #static_cache. reset ( ) ;
6276 }
6377
6478 async serve < T = void > (
@@ -87,12 +101,10 @@ export class StaticRouters {
87101 }
88102 ) : Promise < Response | null > {
89103 const { pathname, search } = new URL ( request . url ) ;
90- const staticResponse = await serveFromDir ( {
91- directory : this . buildDir ,
92- path : pathname ,
93- } ) ;
94- if ( staticResponse )
95- return new Response ( staticResponse , { headers : staticHeaders } ) ;
104+ const file = this . #static_cache. match ( pathname ) ;
105+ if ( file ) {
106+ return new Response ( file , { headers : staticHeaders } ) ;
107+ }
96108 const serverSide = this . server . match ( request ) ;
97109 if ( ! serverSide ) return null ;
98110 const clientSide = this . client . match ( request ) ;
@@ -206,6 +218,29 @@ function* scanCacheDependencies(
206218 } catch { }
207219}
208220
221+ export class StaticFileCache {
222+ #cache = new Map < string , BunFile > ( ) ;
223+ constructor ( public base : string ) { }
224+ reset ( ) {
225+ this . #cache. clear ( ) ;
226+ }
227+ match ( pathname : string ) : BunFile | undefined {
228+ if ( this . #cache. has ( pathname ) ) {
229+ return this . #cache. get ( pathname ) ! ;
230+ }
231+ const final = join ( this . base , pathname ) ;
232+ try {
233+ const stat = statSync ( final ) ;
234+ if ( stat ?. isFile ( ) ) {
235+ const file = Bun . file ( final ) ;
236+ this . #cache. set ( pathname , file ) ;
237+ return file ;
238+ }
239+ } catch { }
240+ }
241+ }
242+
243+ /** @deprecated */
209244export async function serveFromDir ( config : {
210245 directory : string ;
211246 path : string ;
0 commit comments