网站导航

搭配 Next.js 使用 Master CSS:何时选择渐进式渲染

从预渲染的 Next.js HTML 生成 CSS,在浏览器处理后续 class,并厘清动态 SSR 的适用边界。

组件可能组合出源代码中不存在完整字符串的 class 名称。如果 Next.js 在构建期间渲染该组件,最终 HTML 就会包含这个 class,即使源代码扫描器无法推断它。@master/css-next 的渐进式渲染会利用该 HTML 生成页面 CSS,再由 Master CSS runtime 处理浏览器中后续出现的 classes。

静态渲染仍是默认选项。完整 class 名称能在源代码中找到,且普通生成样式表已符合需求时,请使用静态模式。静态或预渲染页面需要按最终标记生成 CSS,并支持后续 class 变更时,再选择渐进式模式。

适用边界是构建时的 HTML。 适配器会处理 next build 的静态与预渲染输出,不会处理请求时生成的动态 SSR 响应;在渐进式模式下,这些响应的生成规则依赖浏览器 runtime。

本页内容

#为何使用最终 HTML

Next.js 的 Adapter API 会提供完成的构建输出。@master/css-next 使用 onBuildComplete 钩子找出静态与预渲染 HTML,并将每份文档交给 Master CSS 服务器渲染器。

此时,页面已将布局、组件与内容组合成标记。Master CSS 可直接读取文档中的 class 字符串,不必推断应用如何组合它们。只要 Next.js 在构建期间输出其 HTML,这种方式就适合生成式标记与组件变体。


#Next.js 的渐进式渲染

交接流程分为三部分:

  1. Next.js 在 next build 期间生成静态与预渲染 HTML。
  2. Master CSS 读取各文档,将生成规则插入 style#master-css。
  3. 浏览器 runtime 跟踪页面 manifest 已覆盖的 classes。未覆盖的 class 会启动引擎,引擎先验证并采用相符规则,再生成新规则。

Next.js 渐进式模式的适用边界

请分别验证预渲染页面与动态路由。构建时 CSS 的覆盖范围,不代表请求时 SSR 也受到覆盖。

文字说明
  1. 构建时 HTML. Next.js 输出静态或预渲染 HTML。Master CSS 构建适配器插入生成 CSS,并提供页面 hydration 数据。
  2. 请求时 HTML. 动态 SSR 响应在构建适配器结束后才生成。此集成不会预渲染其生成 CSS;渐进式模式依赖浏览器 runtime 提供这些规则。

#CSS 与 runtime 的交接

含有生成规则的文档会收到外部页面 hydration manifest。style 元素通过 data-master-css-hydration-manifest 指向它,让 runtime 在延后加载引擎时仍可跟踪已覆盖的 classes。引擎启动后,会验证并采用相符的 CSSOM 规则。runtime 需要生成页面 manifest 以外的 class 时,才加载引擎。

行内 CSS 在交接前就能使用。manifest 用于支持后续规则管理,浏览器应用文档中既有 CSS 时并不需要它。完整传递与 hydration 行为请参阅渲染模式。


#验证生产构建的交接

请按照 Next.js 安装指南选择渐进式模式并加载 CSS 入口。下方示例以该设置为前提;配置与适配器组合选项集中在集成指南中。

请使用 Next.js 会在构建时预渲染的页面。将下一节的 <Badge tone="blue" /> 放入该页面,再运行:

npm run buildnpm run start

检查页面的响应源代码。style#master-css 应包含蓝色徽标的生成规则与 data-master-css-hydration-manifest 引用,并确认引用的资源可正常加载。不要只检查实时 DOM,请检查响应源代码,否则 runtime 生成可能掩盖构建时 CSS 缺漏。

接着,通过客户端交互加入 <Badge tone="neutral" />。该 class 若不在页面 manifest 中,就由浏览器生成补上缺少的规则。第二项观察测试后续运行,初始响应则测试构建时覆盖范围。渲染模式说明 runtime 就绪与恢复的边界。


#源代码扫描与渲染后的 classes

Master CSS 源代码扫描需要完整 class 字符串,不会对组件插值求值。变体已预先确定时,适合使用包含所有完整 classes 的显式映射表。

渐进式渲染可改用预渲染文档中实际出现的 class 名称。以下列组件为例:

Badge.tsx
export function Badge({ tone }: {  tone: 'blue' | 'neutral'}) {  return (    <span className={`px-xs py-3xs r-sm bg-${tone}/.1 fg-text-${tone}`}>      New    </span>  )}

渲染 <Badge tone="blue" /> 会生成:

blue.html
<span class="px-xs py-3xs r-sm bg-blue/.1 fg-text-blue">New</span>

渲染 <Badge tone="neutral" /> 会生成:

neutral.html
<span class="px-xs py-3xs r-sm bg-neutral/.1 fg-text-neutral">New</span>

只要任一徽标出现在构建时 HTML 中,适配器就会针对实际的 class 列表生成 CSS。前景 classes 分别解析为 color: var(--color-text-blue) 与 color: var(--color-text-neutral);背景 classes 则使用对应色彩的 10% 不透明度。只有蓝色徽标的页面,初始生成 CSS 不需要 neutral 变体规则。neutral 徽标之后才出现时,runtime 可生成其规则。

这项选择以已渲染 HTML 的覆盖范围加上浏览器 runtime,取代源代码导向的覆盖范围。有限的 class 映射表已能提供全部所需变体时,静态模式仍然合适。


#页面会有哪些变化

#CSS 可用时机

预渲染文档会在响应中带有生成 CSS。这些规则不必等待 Master CSS runtime 启动,就能应用到页面。这让 runtime 生成不再是这些样式的前提,但不代表已实测证明首次绘制改善;图片、字体、其他样式表与脚本仍会影响渲染。

#路由级 CSS 输出

每份文档都会收到自身 HTML 需要的生成 class 规则。共用原生样式仍遵循应用的样式表设置。预渲染不代表页面上每个样式都是生成 utility,也不代表所有应用 CSS 都是路由专属。

#保留 runtime 的灵活性

仅在客户端出现的组件与后续 class 变更仍受到支持。渐进式模式会增加 runtime 与 hydration manifest 的传递成本,选择模式时应将其与更简单的静态样式表比较。

编写语法保持不变。模式改变的是读取 classes 的时机,以及生成规则如何送达页面。


#当前适用边界

只存在于请求时 SSR 响应中的路由,没有完成的 HTML 可供构建时适配器处理。渐进式模式不会为该响应提供预渲染 CSS。代表性的动态路由应与预渲染页面分开测试,尤其是在 JavaScript 启动前就必须有样式的情况。

部署集成若也会处理构建输出,请遵循适配器组合设置,并检查部署后的响应。本地构建正确,不代表后续适配器保留了生成 CSS 与 manifest URL。


#何时保持静态渲染

源代码扫描能找到完整 class 字符串时,请使用 Next.js 默认设置。静态模式会生成样式表,不需要 Master CSS 浏览器 runtime。请独立验证所选 bundler;安装指南列出当前生成资源的限制与 Webpack 构建方式。交互组件仍可切换样式表中已包含的 classes。

有明确需求时再选择渐进式模式:根据最终构建时 HTML 生成 CSS,并由 runtime 支持新 classes。应用到整个应用之前,请同时验证预渲染页面与动态路由。