@mandujs/core 0.20.5 → 0.20.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 +1 -1
- package/src/runtime/ssr.ts +13 -1
- package/src/runtime/streaming-ssr.ts +5 -2
package/package.json
CHANGED
package/src/runtime/ssr.ts
CHANGED
|
@@ -282,6 +282,17 @@ export function renderToHTML(element: ReactElement, options: SSROptions = {}): s
|
|
|
282
282
|
devtoolsScript = generateDevtoolsScript();
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
// #179: body 내 <link> 태그를 <head>로 호이스팅
|
|
286
|
+
// React 컴포넌트(layout.tsx 등)에서 <link>를 렌더링하면 body 안에 위치하게 되는데,
|
|
287
|
+
// 폰트/스타일시트는 <head>에 있어야 FOUT 없이 로드됨
|
|
288
|
+
const linkTagPattern = /<link\s[^>]*(?:rel=["'](?:stylesheet|preconnect|preload|icon|dns-prefetch)["'][^>]*|href=["'][^"']+["'][^>]*)\/?\s*>/gi;
|
|
289
|
+
const hoistedLinks: string[] = [];
|
|
290
|
+
const bodyContent = content.replace(linkTagPattern, (match) => {
|
|
291
|
+
hoistedLinks.push(match);
|
|
292
|
+
return "";
|
|
293
|
+
});
|
|
294
|
+
const hoistedLinkTags = hoistedLinks.join("\n ");
|
|
295
|
+
|
|
285
296
|
return `<!doctype html>
|
|
286
297
|
<html lang="${escapeHtmlAttr(lang)}">
|
|
287
298
|
<head>
|
|
@@ -289,11 +300,12 @@ export function renderToHTML(element: ReactElement, options: SSROptions = {}): s
|
|
|
289
300
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
290
301
|
<title>${escapeHtmlText(title)}</title>
|
|
291
302
|
${cssLinkTag}
|
|
303
|
+
${hoistedLinkTags}
|
|
292
304
|
${headTags}
|
|
293
305
|
${collectedHeadTags}
|
|
294
306
|
</head>
|
|
295
307
|
<body>
|
|
296
|
-
<div id="root">${
|
|
308
|
+
<div id="root">${bodyContent}</div>
|
|
297
309
|
${dataScript}
|
|
298
310
|
${routeScript}
|
|
299
311
|
${hydrationScripts}
|
|
@@ -540,12 +540,15 @@ function generateHTMLTailContent(options: StreamingSSROptions): string {
|
|
|
540
540
|
}
|
|
541
541
|
}
|
|
542
542
|
|
|
543
|
-
// 9.
|
|
543
|
+
// 9. #179: body 내 <link> 태그를 <head>로 호이스팅 (외부 폰트/스타일시트 지원)
|
|
544
|
+
scripts.push(`<script>document.querySelectorAll('#root link[rel="stylesheet"],#root link[rel="preconnect"],#root link[rel="preload"],#root link[rel="icon"],#root link[rel="dns-prefetch"]').forEach(function(l){document.head.appendChild(l)})</script>`);
|
|
545
|
+
|
|
546
|
+
// 10. HMR 스크립트 (개발 모드 — Zero-JS 페이지에서도 CSS 핫리로드 지원)
|
|
544
547
|
if (isDev && hmrPort) {
|
|
545
548
|
scripts.push(generateHMRScript(hmrPort));
|
|
546
549
|
}
|
|
547
550
|
|
|
548
|
-
//
|
|
551
|
+
// 11. DevTools 번들 로드 (개발 모드)
|
|
549
552
|
if (isDev) {
|
|
550
553
|
scripts.push(`<script type="module" src="/.mandu/client/_devtools.js"></script>`);
|
|
551
554
|
}
|