@@ -5,12 +5,22 @@ import util from '../shared/util.ts'
5
5
import type { RouterURL } from '../types.ts'
6
6
import type { Application } from './app.ts'
7
7
8
+ export type SSRData = {
9
+ expires : number
10
+ value : any
11
+ }
12
+
13
+ export type SSROutput = {
14
+ html : string
15
+ data : Record < string , SSRData > | null
16
+ }
17
+
8
18
/** The framework render result of SSR. */
9
19
export type FrameworkRenderResult = {
10
20
head : string [ ]
11
21
body : string
12
22
scripts : Record < string , any > [ ]
13
- data : Record < string , string > | null
23
+ data : Record < string , SSRData > | null
14
24
}
15
25
16
26
/** The framework renderer for SSR. */
@@ -26,7 +36,7 @@ export type FrameworkRenderer = {
26
36
export class Renderer {
27
37
#app: Application
28
38
#renderer: FrameworkRenderer
29
- #cache: Map < string , Map < string , [ string , any ] > >
39
+ #cache: Map < string , Map < string , SSROutput > >
30
40
31
41
constructor ( app : Application ) {
32
42
this . #app = app
@@ -41,25 +51,36 @@ export class Renderer {
41
51
async useCache (
42
52
namespace : string ,
43
53
key : string ,
44
- render : ( ) => Promise < [ string , any ] >
54
+ render : ( ) => Promise < [ string , Record < string , SSRData > | null ] >
45
55
) : Promise < [ string , any ] > {
46
56
let cache = this . #cache. get ( namespace )
47
57
if ( cache === undefined ) {
48
58
cache = new Map ( )
49
59
this . #cache. set ( namespace , cache )
50
60
}
51
- const cached = cache . get ( key )
52
- if ( cached !== undefined ) {
53
- return cached
61
+ if ( cache . has ( key ) ) {
62
+ const { html, data } = cache . get ( key ) !
63
+ let expires = 0
64
+ if ( data !== null ) {
65
+ Object . values ( data ) . forEach ( ( { expires : _expires } ) => {
66
+ if ( expires === 0 || ( _expires > 0 && _expires < expires ) ) {
67
+ expires = _expires
68
+ }
69
+ } )
70
+ }
71
+ if ( expires === 0 || Date . now ( ) < expires ) {
72
+ return [ html , data ]
73
+ }
74
+ cache . delete ( key )
54
75
}
55
- const ret = await render ( )
76
+ let [ html , data ] = await render ( )
56
77
if ( namespace !== '-' ) {
57
78
this . #app. getCodeInjects ( 'ssr' ) ?. forEach ( transform => {
58
- ret [ 0 ] = transform ( key , ret [ 0 ] )
79
+ html = transform ( key , html )
59
80
} )
60
81
}
61
- cache . set ( key , ret )
62
- return ret
82
+ cache . set ( key , { html , data } )
83
+ return [ html , data ]
63
84
}
64
85
65
86
clearCache ( url ?: string ) {
@@ -71,7 +92,7 @@ export class Renderer {
71
92
}
72
93
73
94
/** render page base the given location. */
74
- async renderPage ( url : RouterURL , nestedModules : RouteModule [ ] ) : Promise < [ string , any ] > {
95
+ async renderPage ( url : RouterURL , nestedModules : RouteModule [ ] ) : Promise < [ string , Record < string , SSRData > | null ] > {
75
96
const start = performance . now ( )
76
97
const isDev = this . #app. isDev
77
98
const appModule = this . #app. findModuleByName ( 'app' )
0 commit comments