@@ -45,6 +45,8 @@ export class Project {
4545 readonly config : Config
4646 readonly ready : Promise < void >
4747
48+ #appData: Record < string , any > = { }
49+ #appDataRefreshTimer: number | null = null
4850 #modules: Map < string , Module > = new Map ( )
4951 #routing: Routing = new Routing ( )
5052 #apiRouting: Routing = new Routing ( )
@@ -249,24 +251,8 @@ export class Project {
249251 return html
250252 }
251253
252- async getStaticData ( ) {
253- const mod = this . #modules. get ( '/data.js' )
254- if ( mod ) {
255- try {
256- const { default : Data } = await import ( 'file://' + mod . jsFile )
257- let data : any = Data
258- if ( util . isFunction ( Data ) ) {
259- data = await Data ( )
260- }
261- if ( util . isPlainObject ( data ) ) {
262- return data
263- }
264- log . warn ( `module '${ mod . url } ' should return a plain object as default` )
265- } catch ( error ) {
266- log . error ( 'getStaticData:' , error )
267- }
268- }
269- return { }
254+ get appData ( ) {
255+ return { ...this . #appData }
270256 }
271257
272258 async build ( ) {
@@ -366,10 +352,10 @@ export class Project {
366352 ] )
367353 } ) )
368354
369- // write static data
355+ // write app data
370356 if ( this . #modules. has ( '/data.js' ) ) {
371357 const { hash } = this . #modules. get ( '/data.js' ) !
372- const data = await this . getStaticData ( )
358+ const data = await this . appData
373359 const jsContent = `export default ${ JSON . stringify ( data ) } `
374360 await writeTextFile ( path . join ( distDir , `data.${ hash . slice ( 0 , hashShort ) } .js` ) , jsContent )
375361 logModule ( 'modules' , jsContent . length )
@@ -542,7 +528,7 @@ export class Project {
542528 this . #renderer = { renderPage, renderHead }
543529
544530 log . info ( colors . bold ( 'Aleph.js' ) )
545- log . info ( colors . bold ( ' Config ' ) )
531+ log . info ( colors . bold ( ' Global ' ) )
546532 if ( this . #modules. has ( '/data.js' ) ) {
547533 log . info ( ' ✓' , 'App Static Data' )
548534 }
@@ -964,7 +950,7 @@ export class Project {
964950 ` }, []);` ,
965951 ` return React.createElement("div", {className: "markdown-page", ref, dangerouslySetInnerHTML: {__html: ${ JSON . stringify ( html ) } }});` ,
966952 `}` ,
967- `MarkdownPage.meta = ${ JSON . stringify ( props , undefined , this . isDev ? 4 : undefined ) } ;` ,
953+ `export const __getPageProps = ${ JSON . stringify ( props , undefined , this . isDev ? 4 : undefined ) } ;` ,
968954 this . isDev && `_s(MarkdownPage, "useRef{ref}\\nuseEffect{}");` ,
969955 this . isDev && `$RefreshReg$(MarkdownPage, "MarkdownPage");` ,
970956 ] . filter ( Boolean ) . map ( l => ! this . isDev ? String ( l ) . trim ( ) : l ) . join ( this . isDev ? '\n' : '' )
@@ -1064,9 +1050,51 @@ export class Project {
10641050 ] )
10651051 }
10661052
1053+ if ( mod . id === '/data.js' ) {
1054+ this . _updateAppData ( )
1055+ }
1056+
10671057 return mod
10681058 }
10691059
1060+ private async _updateAppData ( ) {
1061+ if ( this . #appDataRefreshTimer != null ) {
1062+ clearTimeout ( this . #appDataRefreshTimer)
1063+ this . #appDataRefreshTimer = null
1064+ }
1065+ if ( this . #modules. has ( '/data.js' ) ) {
1066+ const mod = this . getModule ( '/data.js' ) !
1067+ try {
1068+ const start = performance . now ( )
1069+ const { default : Data , refreshInterval } = await import ( 'file://' + mod . jsFile )
1070+ let data : any = Data
1071+ if ( util . isFunction ( Data ) ) {
1072+ data = await Data ( )
1073+ }
1074+ if ( util . isPlainObject ( data ) ) {
1075+ this . #appData = data
1076+ log . debug ( `app data updated in ${ Math . round ( performance . now ( ) - start ) } ms` )
1077+ if ( util . isUNumber ( refreshInterval ) && this . isDev ) {
1078+ this . #appDataRefreshTimer = setTimeout ( async ( ) => {
1079+ this . #appDataRefreshTimer = null
1080+ await this . _updateAppData ( )
1081+ if ( JSON . stringify ( data ) !== JSON . stringify ( this . appData ) ) {
1082+ this . #fsWatchListeners. forEach ( e => e . emit ( 'modify-' + mod . id , mod . hash ) )
1083+ }
1084+ } , refreshInterval * 1000 )
1085+ }
1086+ } else {
1087+ log . warn ( `the Custom App should return a plain object as default` )
1088+ }
1089+ } catch ( error ) {
1090+ log . error ( `${ mod . url } :` , error )
1091+ }
1092+ } else {
1093+ this . #appData = { }
1094+ log . debug ( 'app data reseted' )
1095+ }
1096+ }
1097+
10701098 private _updateDependency ( depPath : string , depHash : string , callback : ( mod : Module ) => void , tracing = new Set < string > ( ) ) {
10711099 this . #modules. forEach ( mod => {
10721100 mod . deps . forEach ( dep => {
@@ -1195,11 +1223,9 @@ export class Project {
11951223 const [
11961224 { default : App } , // todo: cache, re-import when hash changed
11971225 { default : E404 } , // todo: cache, re-import when hash changed
1198- staticData // todo: real static
11991226 ] = await Promise . all ( [
12001227 appModule && url . pagePath != '' ? await import ( 'file://' + appModule . jsFile ) : Promise . resolve ( { } ) ,
1201- e404Module ? await import ( 'file://' + e404Module . jsFile ) : Promise . resolve ( { } ) ,
1202- await this . getStaticData ( )
1228+ e404Module ? await import ( 'file://' + e404Module . jsFile ) : Promise . resolve ( { } )
12031229 ] )
12041230 const pageComponentTree : { id : string , Component ?: any } [ ] = pageModuleTree . map ( ( { id } ) => ( { id } ) )
12051231 const imports = pageModuleTree . map ( async ( { id } ) => {
@@ -1211,7 +1237,7 @@ export class Project {
12111237 }
12121238 } )
12131239 await Promise . all ( imports )
1214- const html = this . #renderer. renderPage ( url , staticData , App , E404 , pageComponentTree )
1240+ const html = this . #renderer. renderPage ( url , this . appData , App , E404 , pageComponentTree )
12151241 const head = await this . #renderer. renderHead ( [
12161242 appModule && url . pagePath != '' ? this . _lookupStyleDeps ( appModule . id ) : [ ] ,
12171243 e404Module && url . pagePath == '' ? this . _lookupStyleDeps ( e404Module . id ) : [ ] ,
0 commit comments