根入口是客户端边界
从@gunkin/uiify导入很方便,同时也会标记一个客户端边界。在Server Component中,应从组件自身的入口导入;该入口不含"use client"指令。
// convenient: a client boundary
import { Accordion } from "@gunkin/uiify";
// server-compatible: no client JavaScript
import { Accordion } from "@gunkin/uiify/components/accordion";受控变体位于/client下
受控组件始终需要客户端边界,因为必须有代码保存值并触发重新渲染。因此,受控变体位于/client子路径下,而不是通过prop切换。
import { Modal } from "@gunkin/uiify/components/modal"; // uncontrolled, 0 kB
import { ModalClientContent } from "@gunkin/uiify/components/modal/client"; // controlled这样,水合成本直接体现在你写下的导入语句中,无须等到打包报告才发现。水合前能够工作的是非受控组件。
跨边界组合
Client Component可以渲染通过children传入的Server Component,使交互外壳保持轻量,同时将内容留在服务端。
// server component
<ClientShell>
<ExpensiveServerRenderedThing />
</ClientShell>避免React context
Tier 0禁用React context:Server Component不能使用context,因此通过provider通信的组成部分无法在服务端渲染。它们改用HTML属性和确定性id连接。
基于@gunkin/uiify/elements构建时也应遵循同一规则:浏览器无须JavaScript就能解析commandfor、popovertarget、for和name。查看架构
水合前
Tier 0组件完整通过禁用JavaScript的测试套件:既可见,也可操作。Tier 1保留原生状态行为,只缺少客户端孤岛添加的能力。Tier 2渲染有意义的标记;键盘导航、过滤和ARIA同步需等到水合后。
每个组件页面都展示级别和实测预算;验证依据说明了两者的来源。