@mandujs/core 0.9.20 → 0.9.22
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 +1 -1
- package/src/runtime/server.ts +13 -1
- package/src/runtime/streaming-ssr.ts +18 -2
package/package.json
CHANGED
package/src/runtime/server.ts
CHANGED
|
@@ -358,7 +358,19 @@ async function handleRequest(req: Request, router: Router): Promise<Response> {
|
|
|
358
358
|
if (loader) {
|
|
359
359
|
try {
|
|
360
360
|
const module = await loader();
|
|
361
|
-
|
|
361
|
+
// module.default가 { component, filling } 객체인 경우 component 추출
|
|
362
|
+
const exported = module.default;
|
|
363
|
+
const component = typeof exported === 'function'
|
|
364
|
+
? exported
|
|
365
|
+
: exported?.component ?? exported;
|
|
366
|
+
registerRouteComponent(route.id, component);
|
|
367
|
+
|
|
368
|
+
// filling이 있으면 loader 실행
|
|
369
|
+
const filling = typeof exported === 'object' ? exported?.filling : null;
|
|
370
|
+
if (filling?.hasLoader?.()) {
|
|
371
|
+
const ctx = new ManduContext(req, params);
|
|
372
|
+
loaderData = await filling.executeLoader(ctx);
|
|
373
|
+
}
|
|
362
374
|
} catch (err) {
|
|
363
375
|
const pageError = createPageLoadErrorResponse(
|
|
364
376
|
route.id,
|
|
@@ -345,6 +345,8 @@ function generateHTMLShell(options: StreamingSSROptions): string {
|
|
|
345
345
|
lang = "ko",
|
|
346
346
|
headTags = "",
|
|
347
347
|
bundleManifest,
|
|
348
|
+
routeId,
|
|
349
|
+
hydration,
|
|
348
350
|
} = options;
|
|
349
351
|
|
|
350
352
|
// Import map (module scripts 전에 위치해야 함)
|
|
@@ -375,6 +377,16 @@ function generateHTMLShell(options: StreamingSSROptions): string {
|
|
|
375
377
|
}
|
|
376
378
|
</style>`;
|
|
377
379
|
|
|
380
|
+
// Island wrapper (hydration이 필요한 경우)
|
|
381
|
+
const needsHydration = hydration && hydration.strategy !== "none" && routeId && bundleManifest;
|
|
382
|
+
let islandOpenTag = "";
|
|
383
|
+
if (needsHydration) {
|
|
384
|
+
const bundle = bundleManifest.bundles[routeId];
|
|
385
|
+
const bundleSrc = bundle?.js || "";
|
|
386
|
+
const priority = hydration.priority || "visible";
|
|
387
|
+
islandOpenTag = `<div data-mandu-island="${routeId}" data-mandu-src="${bundleSrc}" data-mandu-priority="${priority}">`;
|
|
388
|
+
}
|
|
389
|
+
|
|
378
390
|
return `<!DOCTYPE html>
|
|
379
391
|
<html lang="${lang}">
|
|
380
392
|
<head>
|
|
@@ -386,7 +398,7 @@ function generateHTMLShell(options: StreamingSSROptions): string {
|
|
|
386
398
|
${importMapScript}
|
|
387
399
|
</head>
|
|
388
400
|
<body>
|
|
389
|
-
<div id="root"
|
|
401
|
+
<div id="root">${islandOpenTag}`;
|
|
390
402
|
}
|
|
391
403
|
|
|
392
404
|
/**
|
|
@@ -464,7 +476,11 @@ function generateHTMLTail(options: StreamingSSROptions): string {
|
|
|
464
476
|
scripts.push(generateHMRScript(hmrPort));
|
|
465
477
|
}
|
|
466
478
|
|
|
467
|
-
|
|
479
|
+
// Island wrapper 닫기 (hydration이 필요한 경우)
|
|
480
|
+
const needsHydration = hydration && hydration.strategy !== "none" && routeId && bundleManifest;
|
|
481
|
+
const islandCloseTag = needsHydration ? "</div>" : "";
|
|
482
|
+
|
|
483
|
+
return `${islandCloseTag}</div>
|
|
468
484
|
${scripts.join("\n ")}
|
|
469
485
|
</body>
|
|
470
486
|
</html>`;
|