modern.js icon indicating copy to clipboard operation
modern.js copied to clipboard

[Bug]: <Outlet /> 在 renderToString 模式下空白

Open rosslo opened this issue 3 months ago • 1 comments

版本信息

@modern-js 版本 "2.68.16"

问题详情

一個簡易的 modernjs 專案,在單立安裝依賴後運行,能夠如預期 SSR 所有內容。

但將這個專案放到一個 monorepo 裡時,似乎因為在依賴提升的交互影響下,<Outlet /> 無法正常 SSR 內容了。

// /src/routes/layout.tsx
import { Outlet } from '@modern-js/runtime/router';

export default function Layout() {
  return (
    <div>
       <div>Layout</div> // => 可以正確 SSR 
      <Outlet /> // => 沒有 SSR
    </div>
  );
}

以下是在 server.ssr.mode: "string" 下的 SSR 結果

<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, viewport-fit=cover, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <meta name="renderer" content="webkit">
        <meta name="layoutmode" content="standard">
        <meta name="imagemode" content="force">
        <meta name="wap-font-scale" content="no">
        <meta name="format-detection" content="telephone=no">
        <script defer src="/static/js/builder-runtime.js"></script>
        <script>
            ;(function() {
                window._MODERNJS_ROUTE_MANIFEST = {
                    "routeAssets": {
                        "main": {
                            "chunkIds": ["builder-runtime", "lib-react", "lib-polyfill", "lib-router", "vendors-node_modules_modern-js_main_index_jsx-node_modules_modern-js_app-tools_node_modules_r-1f73df", "main"],
                            "assets": ["static/js/builder-runtime.js", "static/js/lib-react.js", "static/js/lib-polyfill.js", "static/js/lib-router.js", "static/js/vendors-node_modules_modern-js_main_index_jsx-node_modules_modern-js_app-tools_node_modules_r-1f73df.js", "static/js/main.js"],
                            "referenceCssAssets": []
                        },
                        "page": {
                            "chunkIds": ["vendors-node_modules_modern-js_app-tools_node_modules_rsbuild_core_node_modules_rspack_core_d-8a2aba", "page"],
                            "assets": ["static/js/async/vendors-node_modules_modern-js_app-tools_node_modules_rsbuild_core_node_modules_rspack_core_d-8a2aba.js", "static/js/async/page.js", "static/css/async/page.css"],
                            "referenceCssAssets": ["static/css/async/page.css"]
                        }
                    }
                };
            }
            )();
        </script>
        <script defer src="/static/js/lib-react.js"></script>
        <script defer src="/static/js/lib-polyfill.js"></script>
        <script defer src="/static/js/lib-router.js"></script>
        <script defer src="/static/js/vendors-node_modules_modern-js_main_index_jsx-node_modules_modern-js_app-tools_node_modules_r-1f73df.js"></script>
        <script defer src="/static/js/main.js"></script>
        <title data-react-helmet="true"></title>
    </head>
    <body>
        <div id="root">
            <div>
                <div>Layout</div>
            </div>
        </div>
        <script id="__LOADABLE_REQUIRED_CHUNKS__" type="application/json">
            [
            ]</script>
        <script id="__LOADABLE_REQUIRED_CHUNKS___ext" type="application/json">
            {
                "namedChunks": [
                ]
            }</script>
        <script>
            window._SSR_DATA = {
                "data": {},
                "context": {
                    "request": {
                        "params": {},
                        "query": {},
                        "pathname": "\u002F",
                        "host": "localhost:3000",
                        "url": "http:\u002F\u002Flocalhost:3000\u002F"
                    },
                    "reporter": {}
                },
                "mode": "string",
                "renderLevel": 2
            }
        </script>
        <script>
            window._ROUTER_DATA = {
                "loaderData": {
                    "layout": null,
                    "page": null
                },
                "errors": null
            }
        </script>
    </body>
</html>

嘗試將 server.ssr.mode 切換到 stream,則可看到 <Outlet />的 SSR 內容

    <body>
        <div id="root">
            <div>
                <div>Layout</div>
                <!--$-->
                <div>Index</div>
                <!--/$-->
            </div>
   </body>

另外補充幾個信息:

  1. 測試了 RuntimePlugin 的 api.wrapRoot,其內容在 mode: string 模式下,也是正常的。

  2. 在 SSR 有問題的狀況下訪問 "localhost:3000",page.tsx 似乎沒有被執行,但也沒有返回404

// /src/routes/page.tsx

const Index = () => {
  console.log('render Index page') // => 沒有在終端裡看到 log
  return <div>Index</div>
}

export default Index

rosslo avatar Oct 02 '25 08:10 rosslo

可以提供一个复现的仓库吗

zllkjc avatar Oct 13 '25 02:10 zllkjc