nextjs渲染篇

本文详细解释了Next.js中的服务器组件工作原理,包括其呈现方式、渲染策略(静态、动态和流式),以及客户端组件的使用和组合模式,如如何区分服务器与客户端组件,上下文提供和交错组件的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 服务器组件

默认情况下,Next.js 使用服务器组件。

1.1 服务器组件是如何呈现的?

在服务器上,Next.js 使用 React 的 API 来编排渲染。渲染工作被拆分为多个块:按单个路段和Suspense

每个区块分两个步骤呈现:

  1. React 将服务器组件渲染为一种称为 React Server 组件有效负载 (RSC Payload) 的特殊数据格式。
  2. Next.js 使用 RSC 有效负载和客户端组件 JavaScript 指令在服务器上呈现 HTML

然后,在客户端上:

  1. HTML 用于立即显示路由的快速非交互式预览 - 这仅适用于初始页面加载。
  2. React Server 组件有效负载用于协调客户端和服务器组件树,并更新 DOM。
  3. JavaScript 指令用于 hydrate客户端组件,并使应用程序具有交互性。

RSC 有效负载是渲染的 React Server 组件树的紧凑二进制表示。客户端上的 React 使用它来更新浏览器的 DOM。

 1.2 渲染策略

1.2.1 静态渲染(默认)

使用静态渲染时,路由在构建时渲染,或在数据重新验证后在后台渲染。结果被缓存,

1.2.2 动态渲染

当路由包含对用户个性化的数据或具有仅在请求时才能知道的信息(例如 cookie 或 URL 的搜索参数)

在渲染过程中,如果发现动态函数或未缓存的数据请求,Next.js将切换到动态渲染整个路由。下表总结了动态函数和数据缓存如何影响路由是静态呈现还是动态呈现:

动态函数数据路线
缓存静态渲染
是的缓存动态渲染
未缓存动态渲染
是的未缓存动态渲染

注:静态渲染只有在非动态函数和数据缓存同时存在情况 

1.2.3 流式

通过流式处理,可以从服务器逐步呈现 UI。工作被拆分为多个块,并在准备就绪时流式传输到客户端。这允许用户在整个内容完成呈现之前立即看到页面的某些部分。

 例如:

<Suspense fallback={<Loading />}>
  <Albums />
</Suspense>

children:要呈现的实际 UI。

fallback:如果实际 UI 尚未完成加载,则要代替实际 UI 进行渲染的备用 UI 

2 客户端组件

"use client"用于声明服务器和客户端组件模块之间的边界
例如:

'use client'
 
import { useState } from 'react'
 
export default function Counter() {
  const [count, setCount] = useState(0)
 
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  )
}

 3 组合模式

何时使用服务器和客户端组件?

3.1 将仅限服务器的代码排除在客户端环境之外

npm install server-only

 然后导入server-only

import 'server-only'
 
export async function getData() {
  const res = await fetch('https://external-service.com/data', {
    headers: {
      authorization: process.env.API_KEY,
    },
  })
 
  return res.json()
}

 3.2 使用第三方软件包和提供程序

import { Carousel } from 'acme-carousel'
 
export default function Page() {
  return (
    <div>
      <p>View pictures</p>
 
      {/* Error: `useState` can not be used within Server Components */}
      <Carousel />
    </div>
  )
}

由于三方组件使用了客户端组件,服务器组件不能使用useState

则需要包装一层:

'use client'
 
import { Carousel } from 'acme-carousel'
 
export default Carousel

现在,可以直接在服务器组件中使用:<Carousel />

import Carousel from './carousel'
 
export default function Page() {
  return (
    <div>
      <p>View pictures</p>
 
      {/*  Works, since Carousel is a Client Component */}
      <Carousel />
    </div>
  )
}

3.3 使用上下文提供程序

上下文提供者通常在应用的根附近渲染,以共享全局关注点,例如当前主题。

(1)错误例子:

import { createContext } from 'react'

//  createContext is not supported in Server Components
export const ThemeContext = createContext({})

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ThemeContext.Provider value="dark">{children}</ThemeContext.Provider>
      </body>
    </html>
  )
}

(2)正确例子:(由于服务器组件不支持 React 上下文,采用children的方式)

app/theme-provider.tsx

'use client'
 
import { createContext } from 'react'
 
export const ThemeContext = createContext({})
 
export default function ThemeProvider({
  children,
}: {
  children: React.ReactNode
}) {
  return <ThemeContext.Provider value="dark">{children}</ThemeContext.Provider>
}

 app/layout.tsx

import ThemeProvider from './theme-provider'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <ThemeProvider>{children}</ThemeProvider>
      </body>
    </html>
  )
}

3.4 交错的服务器和客户端组件

不支持的模式:将服务器组件导入客户端组件

'use client'
 
// You cannot import a Server Component into a Client Component.
import ServerComponent from './Server-Component'
 
export default function ClientComponent({
  children,
}: {
  children: React.ReactNode
}) {
  const [count, setCount] = useState(0)
 
  return (
    <>
      <button onClick={() => setCount(count + 1)}>{count}</button>
 
      <ServerComponent />
    </>
  )
}

支持的模式:将服务器组件作为道具传递给客户端组件

'use client'
 
import { useState } from 'react'
 
export default function ClientComponent({
  children,
}: {
  children: React.ReactNode
}) {
  const [count, setCount] = useState(0)
 
  return (
    <>
      <button onClick={() => setCount(count + 1)}>{count}</button>
      {children}
    </>
  )
}

 将服务器组件作为子项导入

// This pattern works:
// You can pass a Server Component as a child or prop of a
// Client Component.
import ClientComponent from './client-component'
import ServerComponent from './server-component'
 
// Pages in Next.js are Server Components by default
export default function Page() {
  return (
    <ClientComponent>
      <ServerComponent />
    </ClientComponent>
  )
}

<think>好的,我现在要帮助用户了解Next.js的入门基础教程。首先,我需要整理用户提供的引用内容,看看里面有哪些关键点可以提取出来。用户引用了四关于Next.js的文章,其中提到了Next.js的特点、项目搭建、部署注意事项以及学习路径。 用户的需求是学习Next.js的基础知识和教程,所以需要从零开始引导他们。首先,我应该介绍Next.js是什么,它的核心功能,比如服务端渲染(SSR)、静态生成(SSG)、路由系统等。然后,按照教程的结构,分步骤讲解如何创建项目、目录结构、页面和路由、数据获取、API路由、部署等。 接下来,我需要确保回答符合系统级指令的要求,比如正确使用LaTeX格式,不过在这个回答中可能数学公式不多,但如果有的话要注意格式。比如,如果提到版本号可能需要用$v13$这样的格式。然后,生成相关问题,这些问题应该围绕Next.js的进阶内容、优化方法、应用场景等方面。 同时,引用的部分需要正确标注。例如,引用[4]提到Next.js是一个React框架,用于SSR和静态网站,这一点需要在介绍Next.js时引用。引用[3]提到静态生成的部署不需要Node环境,这在讲解静态生成和部署时要提到。引用[1]和[2]涉及学习路径和项目搭建,可以在教程步骤中引用。 需要注意的是,用户可能没有React基础,所以在教程中可能需要适当提及React的基础知识,但根据引用内容,用户可能更关注Next.js本身的使用,所以重点放在Next.js的特性上。同时,要避免使用专业术语过多,保持语言简洁易懂。 最后,生成的相关问题要引导用户深入Next.js的学习,比如性能优化、SSR与SSG的区别、部署方式比较等。这些问题需要与用户可能遇到的后续学习需求相关,帮助他们进一步探索。 总结下来,回答的结构应该是先介绍Next.js,然后分步骤讲解基础教程,过程中引用提供的资料,最后提出相关问题。同时,确保遵循格式要求,正确使用引用标识,并且语言口语化,符合中文表达习惯。</think>### Next.js 入门基础教程 #### 一、Next.js 核心特性 Next.js 是一个基于 React 的框架,提供以下核心能力: 1. **服务端渲染 (SSR)**:提升首屏加载速度和 SEO 友好性[^4] 2. **静态生成 (SSG)**:预渲染页面为静态 HTML,支持 CDN 加速[^3] 3. **混合渲染模式**:可自由选择页面使用 SSR 或 SSG 4. **文件系统路由**:通过 `/pages` 目录自动生成路由,例如 `pages/about.js` 对应 `/about` 路径 5. **API 路由**:直接在项目中创建后端接口,文件路径为 `/pages/api/*.js` #### 二、环境搭建 1. 安装 Node.js(建议使用 LTS 版本,例如 $v18.x$) 2. 创建项目: ```bash npx create-next-app@latest my-app ``` 3. 选择配置项(按需开启 TypeScript/ESLint 等)[^2] #### 三、目录结构解析 ``` ├── pages/ # 页面路由 ├── public/ # 静态资源 ├── styles/ # 全局样式 ├── components/ # 公共组件 ├── app/ # App Router (v13+) └── next.config.js # 配置文件 ``` #### 四、第一个页面开发 1. 在 `/pages/index.js` 创建首页: ```jsx export default function Home() { return <h1>欢迎学习 Next.js!</h1> } ``` 2. 启动开发服务器: ```bash npm run dev ``` #### 五、数据获取方法 1. **静态生成 (SSG)**: ```jsx export async function getStaticProps() { const data = await fetch('https://api.example.com/data') return { props: { data } } } ``` 2. **服务端渲染 (SSR)**: ```jsx export async function getServerSideProps() { const user = await getUser(req) return { props: { user } } } ``` #### 六、部署方案 1. **静态导出**(适合纯前端): ```bash npm run build && next export # 生成 /out 目录 ``` 2. **Node 服务部署**(支持 SSR): ```bash npm run build npm start ``` #### 七、学习资源推荐 - 官方文档:https://nextjs.org/docs - Next.js 学习专栏(含实战项目)[^1] - Vercel 部署指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流光影下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值