Skip to content
This repository was archived by the owner on Jul 6, 2025. It is now read-only.

Commit db57397

Browse files
author
Je
committed
feat: cache app data and refresh by refreshInterval
1 parent f48e4ce commit db57397

File tree

2 files changed

+59
-34
lines changed

2 files changed

+59
-34
lines changed

project.ts

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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) : [],

server.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,16 @@ export async function start(appDir: string, port: number, isDev = false, reload
8989

9090
let body = ''
9191
if (mod.id === '/data.js') {
92-
const data = await project.getStaticData()
9392
if (project.isDev) {
9493
body = [
95-
`import { createHotContext } from "./-/deno.land/x/aleph/hmr.js";`,
96-
`import events from "./-/deno.land/x/aleph/events.js";`,
97-
`import.meta.hot = createHotContext("/data.js");`,
98-
`export default ${JSON.stringify(data, undefined, 4)};`,
99-
`import.meta.hot.accept(({ default: data }) => events.emit("update-data", data));`
100-
].join('\n')
94+
`import { createHotContext } from "./-/deno.land/x/aleph/hmr.js"`,
95+
`import events from "./-/deno.land/x/aleph/events.js"`,
96+
`import.meta.hot = createHotContext("/data.js")`,
97+
`export default ${JSON.stringify(project.appData, undefined, 4)}`,
98+
`import.meta.hot.accept(({ default: data }) => events.emit("update-data", data))`
99+
].join(';\n')
101100
} else {
102-
body = `export default ${JSON.stringify(data)}`
101+
body = `export default ${JSON.stringify(project.appData)}`
103102
}
104103
} else if (reqSourceMap) {
105104
body = mod.jsSourceMap

0 commit comments

Comments
 (0)