Nuxt Server Components
翻译:Claude
DeepdiveintoNuxtServer_Components.pdf 5708427
PPT
Nuxt 项目贡献者,Nuxt Bridge 维护者
与其他类似技术的区别
让大家了解 Nuxt Server Components:
举例:使用 markdown 转 HTML 显示内容的场景
A:因为如果两者不执行相同的 DOM 结构,就无法进行 Hydration
:::tip 如果有只在服务器上渲染的组件就能解决。
:::
有那么方便的机制吗?
• 从Nuxt 3引入的功能
• 仍然是实验性的
• 可以创建仅在服务器上渲染的组件
不强制要求服务器
.server.vue
启用 experimental.componentIslands 配置
components/islands 目录下的组件会只在服务器端渲染
使用者可以不用 import 使用
或者从 #components 导入
(从实际路径导入尚未支持)
• 服务器组件的基础
.server.vue
将被转换为使用 Nuxtlsland 组件的代码
• 在 components/islands 中创建组件时,将成为只能在服务器上渲染的组件
静态部分称为岛屿(Island)
NuxtIsland
是在动态部分中嵌入静态内容的架构。
Nuxt Server Components 可以实现的功能(部分摘录)
• 可以使用异步组件
• 可以嵌套服务器组件和客户端组件
• 服务器组件中,只有一部分可以进行 Hydration
通过使用 nuxt-client 指令,可以对 Server Component 的一部分进行 Hydration。
定时显示的组件
制作 Nuxt 服务器组件并解释其机制
最终完成的东西
Nuxt Server Components 的流(在服务器端渲染的情况下)
与传统渲染的差异
Nuxt Server Components 的构成要素
• 渲染 Vue 组件的端点
• 在服务器上渲染 Vue 组件的处理
• 向渲染 Vue 组件的端点发送请求的组件
渲染 Vue 组件的端点
从 URL 中提取组件名和 props 的处理
实际的 URL
/nuxtisland/CodeExample_XdPPUtbPQW.json?props={"count":4}
从 URL 中提取组件名:CodeExample
从查询参数中提取 props: { count: 4 }
创建端点
SSR 上下文
- 可以添加在 Server-Side Rendering 中想要使用的数据
- 在 Nuxt 中,也会使用请求事件
- 通过使用 useSSRContext 可以从组件内部访问
在服务器上渲染 Vue 组件的处理
创建组件名称与组件的映射。
创建动态渲染组件的组件
可以动态渲染组件
使用 createSSRApp 和 renderToString
将动态组件渲染处理结合起来。
在服务器上渲染 Vue 组件
此render函数在/nuxtisland执行
相当简化的代码
渲染HTML字符串 不进行Hydration
Nuxtlsland 会发送 /nuxtisland 请求并渲染响应的 HTML 字符串。
组件级别的渲染机制已完成
这样下去,Server Component 的子组件就不能拥有交互式的组件。
通过使用插槽,可以将服务器组件和客户端组件嵌套在一起。
:::tip 问:包含插槽进行渲染会怎样?
:::
答:会变成普通的HTML字符串,因此不会进行水合(没有事件处理程序等信息)。
目标是在槽被内容替换的状态下进行渲染。
在构建时转换为自定义占位符。
:::tip 嵌套 Client Component 所需的事项
:::
• 在构建时将
• 用 Teleport 包围 Slot 的内容进行渲染→接下来是这里
• 在占位符部分插入 Slot 的内容
像这样改写
为了使Teleport部分更容易理解,代码如下所示。
•一个内置组件,可以将组件模板的一部分"传送"到位于该组件 DOM 层次结构之外的 DOM 节点
v-if 为 true 时插入到 body 元素中。
在服务器端渲染时,SSR Context 的 teleports 中会公开 Teleport 内的内容
(SSR Context 是传递给 renderToString 的第二个参数的对象)https://ja.vuejs.org/guide/scaling-up/ssr.htm|#teleports
当包含 Teleport 的 NuxtIsland 组件进行服务器端渲染时,可以获得如下的 Teleport 内的内容。
• 在构建时将
• 用 Teleport 包围并渲染 Slot 的内容
• 将 Slot 的内容插入到占位符部分
在构建时转换为自定义占位符。
当 Nuxtlsland 被渲染时,data-island-uid 将被设置。
查看 uid=xXX,slot=default 可以知道应该插入到哪里。
因为找到了插入的位置,所以插入了 Teleport 的内容(在服务器渲染时用正则表达式替换)。
在服务器上完成的 HTML
指定的属性一致
Teleport之后
:::tip 问:为什么需要在 Server 和 Client 都执行?
:::
答:因为如果不在两者上执行并达到相同的 DOM 结构,就无法进行 Hydration。
与在服务器上完成的 HTML 相比
详细的技术实现代码请参考: https://github.com/wattanx/mini-nuxt-sc
• 最小化 Nuxt 服务器组件
• 独立于 Nuxt 制作
• 使用 Vue 可以实现
与 Nuxt Server Components 相反(在动态部分嵌入静态内容)
巧妙运用 Teleport 技术
实验性功能尚在发展中:
因为还在实验阶段,所以请使用并反馈。
graph TD
A[HTML] --> B[GET /bundle.js]
B --> C[JS]
C --> D[Render]
graph LR
A[空的 HTML 被下载] --> B[JS 被下载]
B --> C[渲染]
sequenceDiagram
participant Browser
participant Server
Browser->>Server: GET /
Server-->>Browser: HTML
Browser->>Server: GET /bundle.js
Server-->>Browser: JS
Browser->>Browser: Hydration
Note over Browser: 绑定事件监听器<br/>建立响应式数据
Browser->>Browser: 交互事件
Browser->>Browser: 重新渲染
Note over Browser: 客户端渲染
sequenceDiagram
participant Server
participant Browser
participant Vue.js
Server->>Browser: 发送服务端渲染的 HTML
Browser->>Browser: 显示静态 HTML
Browser->>Server: 请求 JavaScript 包
Server->>Browser: 发送 JavaScript 包
Browser->>Vue.js: 初始化 Vue.js 应用
Vue.js->>Browser: 查找根 Vue 组件
Vue.js->>Browser: 附加事件监听器和数据绑定
Note over Browser,Vue.js: Hydration 完成
Browser->>Vue.js: 交互事件
Vue.js->>Browser: 更新 DOM
Note over Browser,Vue.js: 客户端渲染
npm create vite-extra@latest app -- --template
ssr-vue-ts