@mandujs/core 0.39.1 → 0.39.2

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandujs/core",
3
- "version": "0.39.1",
3
+ "version": "0.39.2",
4
4
  "description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -1173,6 +1173,72 @@ export function setCreateApp(fn: CreateAppFn): void {
1173
1173
  defaultRegistry.setCreateApp(fn);
1174
1174
  }
1175
1175
 
1176
+ /**
1177
+ * Issue #232 follow-up — eager page-component registration.
1178
+ *
1179
+ * After a dev-mode HMR reload, `registerPageHandler` / `registerPageLoader`
1180
+ * install lazy thunks. The actual component import and
1181
+ * `registerRouteComponent` call is deferred until the first request for
1182
+ * that route. On a brand-new browser reload triggered by HMR the request
1183
+ * normally populates the registry in time, but any code path that renders
1184
+ * without going through `loadPageData` first (or a thrown error that
1185
+ * short-circuits it) leaves `routeComponents` empty, and the default
1186
+ * appCreator renders the "404 - Route Not Found" fallback even though the
1187
+ * route is valid.
1188
+ *
1189
+ * `prewarmPageRoutes()` walks every registered `pageHandler` / `pageLoader`
1190
+ * once and drives it through the same code path the first request would
1191
+ * take, so `routeComponents` is fully populated before the server starts
1192
+ * serving. The cost is a one-time module import per page route — trivial
1193
+ * in dev. Production `mandu start` is unaffected because it already runs
1194
+ * requests through the same lazy path without HMR races.
1195
+ */
1196
+ export async function prewarmPageRoutes(
1197
+ registry: ServerRegistry = defaultRegistry,
1198
+ ): Promise<{ prewarmed: string[]; failed: Array<{ routeId: string; error: string }> }> {
1199
+ const prewarmed: string[] = [];
1200
+ const failed: Array<{ routeId: string; error: string }> = [];
1201
+
1202
+ // pageHandlers path (routes with .slot.ts / filling)
1203
+ for (const routeId of registry.pageHandlers.keys()) {
1204
+ try {
1205
+ await ensurePageRouteMetadata(routeId, registry);
1206
+ prewarmed.push(routeId);
1207
+ } catch (err) {
1208
+ failed.push({
1209
+ routeId,
1210
+ error: err instanceof Error ? err.message : String(err),
1211
+ });
1212
+ }
1213
+ }
1214
+
1215
+ // pageLoaders path (plain page components, no slot)
1216
+ for (const routeId of registry.pageLoaders.keys()) {
1217
+ if (registry.routeComponents.has(routeId)) continue; // already warm
1218
+ try {
1219
+ const loader = registry.pageLoaders.get(routeId);
1220
+ if (!loader) continue;
1221
+ const module = await loader();
1222
+ const exported: unknown = module.default;
1223
+ const exportedObj = exported as Record<string, unknown> | null;
1224
+ const component = typeof exported === "function"
1225
+ ? (exported as RouteComponent)
1226
+ : (exportedObj?.component as RouteComponent | undefined);
1227
+ if (typeof component === "function") {
1228
+ registry.registerRouteComponent(routeId, component);
1229
+ prewarmed.push(routeId);
1230
+ }
1231
+ } catch (err) {
1232
+ failed.push({
1233
+ routeId,
1234
+ error: err instanceof Error ? err.message : String(err),
1235
+ });
1236
+ }
1237
+ }
1238
+
1239
+ return { prewarmed, failed };
1240
+ }
1241
+
1176
1242
  /**
1177
1243
  * Layout 로더 등록 (전역)
1178
1244
  */