create-fullstack-scaffold 0.5.3 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/template/package.json
CHANGED
|
@@ -17,7 +17,23 @@ import { logger } from '../utils/logger'
|
|
|
17
17
|
import { createApp } from '../app'
|
|
18
18
|
import { getDb, runMigrations } from '../db'
|
|
19
19
|
import { createISRCache, isISRRoute } from '@server/core/isr-cache'
|
|
20
|
-
import {
|
|
20
|
+
import { renderISRPage } from '@server/core/isr-renderer'
|
|
21
|
+
// @client/entry-server 仅含 client 的 preset 存在;cli-only 会因静态
|
|
22
|
+
// 导入悬空(verify 链已拦过一次)。运行时按需加载,缺省回退壳渲染。
|
|
23
|
+
type RenderSSRFn = (pathname: string, data: never) => { html: string }
|
|
24
|
+
|
|
25
|
+
async function loadRenderSSR(): Promise<RenderSSRFn | null> {
|
|
26
|
+
try {
|
|
27
|
+
// 变量说明符:tsc 不做模块解析(cli-only 无 client 目录时字面量
|
|
28
|
+
// 动态导入也会被 tsc 拦——与 vitest.config 的 react 插件同法)
|
|
29
|
+
const mod = '@client/entry-server'
|
|
30
|
+
const m = (await import(/* @vite-ignore */ mod)) as { renderSSR: RenderSSRFn }
|
|
31
|
+
return m.renderSSR
|
|
32
|
+
} catch {
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
import { isrRegistry, type ISRRouterContext } from '@server/core/isr-registry'
|
|
21
37
|
import { setISRCache } from '@server/core/isr-invalidation'
|
|
22
38
|
import { setRuntimeAdapter } from '@server/core/runtime'
|
|
23
39
|
import { getNodeRuntimeAdapter } from '@server/core/runtime-node'
|
|
@@ -130,11 +146,13 @@ app.get('*', async c => {
|
|
|
130
146
|
}
|
|
131
147
|
|
|
132
148
|
if (result.status === 'stale' && result.html) {
|
|
133
|
-
|
|
134
|
-
.then(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
149
|
+
renderISRForRoute(pathname)
|
|
150
|
+
.then(html => {
|
|
151
|
+
if (html) {
|
|
152
|
+
isrCache.store(pathname, html).catch(e => {
|
|
153
|
+
console.warn('ISR cache store (background revalidation) failed:', e)
|
|
154
|
+
})
|
|
155
|
+
}
|
|
138
156
|
})
|
|
139
157
|
.catch(e => {
|
|
140
158
|
console.warn('ISR background render failed:', e)
|
|
@@ -142,11 +160,14 @@ app.get('*', async c => {
|
|
|
142
160
|
return c.html(result.html)
|
|
143
161
|
}
|
|
144
162
|
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
163
|
+
const html = await renderISRForRoute(pathname)
|
|
164
|
+
if (html) {
|
|
165
|
+
isrCache.store(pathname, html).catch(e => {
|
|
166
|
+
console.warn('ISR cache store failed:', e)
|
|
167
|
+
})
|
|
168
|
+
return c.html(html)
|
|
169
|
+
}
|
|
170
|
+
return c.html(indexHtml)
|
|
150
171
|
}
|
|
151
172
|
|
|
152
173
|
return c.html(indexHtml)
|
|
@@ -191,6 +212,34 @@ export async function createServer() {
|
|
|
191
212
|
return { server, port: config.port }
|
|
192
213
|
}
|
|
193
214
|
|
|
215
|
+
/**
|
|
216
|
+
* 真 ISR 渲染(与 CF 入口同管线):registry fetch 数据 → renderSSR
|
|
217
|
+
* 页面级渲染 → renderISRPage 注入 body + meta + __SSR_DATA__。
|
|
218
|
+
* 返回 null 表示无注册路由/渲染失败,调用方回退 SPA index.html。
|
|
219
|
+
*/
|
|
220
|
+
async function renderISRForRoute(pathname: string): Promise<string | null> {
|
|
221
|
+
const entry = isrRegistry.match(pathname)
|
|
222
|
+
if (!entry) return null
|
|
223
|
+
const ctx: ISRRouterContext = { db: await getDb(), env: {} }
|
|
224
|
+
let data: unknown = {}
|
|
225
|
+
let meta = { title: 'App', description: '' }
|
|
226
|
+
try {
|
|
227
|
+
data = await entry.fetch(pathname, ctx)
|
|
228
|
+
meta = entry.meta(data, pathname)
|
|
229
|
+
} catch {
|
|
230
|
+
// DB 错误——回退默认 meta 继续渲染壳
|
|
231
|
+
}
|
|
232
|
+
const renderSSR = await loadRenderSSR()
|
|
233
|
+
if (!renderSSR) return null // 无 client(cli-only 等)——调用方回退 SPA
|
|
234
|
+
try {
|
|
235
|
+
const ssr = renderSSR(pathname, data as never)
|
|
236
|
+
return renderISRPage({ template: indexHtml, body: ssr.html, meta, data })
|
|
237
|
+
} catch (e) {
|
|
238
|
+
console.warn('ISR render failed:', e)
|
|
239
|
+
return null
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
194
243
|
export async function startServer() {
|
|
195
244
|
const bootstrapLog = logger.bootstrap()
|
|
196
245
|
|