app router模式next.js的SSR提前注入数据的方法

125 阅读1分钟

方法一:直接在 page.tsx 中使用 async 函数加载数据

在 App Router 中,页面组件本身就是一个可以是 async 的函数。你可以在其中请求远程 JSON 文件或 API 并将数据作为 props 注入到组件内:

// app/page.tsx
import React from 'react'

export default async function Page() {
  // 例如:远程语言包和皮肤 JSON 请求
  const [langRes, themeRes] = await Promise.all([
    fetch('https://your-cdn.com/i18n/zh.json'),
    fetch('https://your-cdn.com/theme/default.json'),
  ])

  const langData = await langRes.json()
  const themeData = await themeRes.json()

  return (
    <main style={{ backgroundColor: themeData.bgColor }}>
      <h1>{langData.title}</h1>
    </main>
  )
}

方法二:将加载逻辑写在 layout.tsx 中,全局注入

如果语言包和皮肤信息是整个 app 都需要的,推荐将数据加载逻辑写在 layout.tsx 中,并通过 props 传递给子组件。

示例结构:

/app
 ├─ layout.tsx   ✅ 读取全局数据(语言包、皮肤)
 ├─ page.tsx     ✅ 使用注入的数据

layout.tsx 示例:

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const langRes = await fetch('https://your-cdn.com/i18n/zh.json')
  const themeRes = await fetch('https://your-cdn.com/theme/default.json')

  const lang = await langRes.json()
  const theme = await themeRes.json()

  return (
    <html>
      <body style={{ background: theme.bgColor }}>
        {/* 使用 React context 或 props 传递数据 */}
        <LangProvider value={lang}>
          <ThemeProvider value={theme}>
            {children}
          </ThemeProvider>
        </LangProvider>
      </body>
    </html>
  )
}

方法三:结合中间件进行重定向注入

中间件适用于权限跳转、重定向,不适合加载大数据(如 JSON 语言包、主题皮肤等),因为它运行在 Edge Runtime,不能用 Node API,且不能传递复杂数据到组件中。

总结注入策略对比:

注入方式是否推荐是否支持 SSR适用场景
page.tsx 中直接加载✅✅✅页面级数据,接口+文件注入
layout.tsx 中加载✅✅✅全局数据,如皮肤、语言、配置
middleware.ts 中处理🚫用于跳转/权限,不能传数据