@typeset/vite-plugin-static-component-react

把 React 静态组件提前渲染为 HTML,并内联到调用方的 renderWrapper。组件内的计算发生在 Vite 模块转换阶段,浏览器运行外层 React wrapper。

本包是仓库内的私有 workspace 包。应用需声明对本包的 workspace:* 依赖,并具备 React、React DOM、Vite 和 @vitejs/plugin-react 环境;依赖约束见 package.json

接入 Vite

在已有 React 应用的 vite.config.ts 中注册静态组件插件,并保留 React 编译插件:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import staticComponentReact from "@typeset/vite-plugin-static-component-react";

export default defineConfig({
  plugins: [staticComponentReact(), react()],
});

staticComponentReact() 当前不接收配置参数。

定义静态组件

创建 Greeting.html.tsx

import { staticComponent } from "@typeset/vite-plugin-static-component-react/runtime";

type GreetingProps = {
  name: string;
  children: string;
};

export default staticComponent(function Greeting(props: GreetingProps) {
  return (
    <p>
      Hello {props.name}: {props.children}
    </p>
  );
});

.html.tsx 用于提示文件用途,插件实际通过 staticComponent() 标记识别组件。组件文件和调用方都应使用 .tsx

在应用中使用

在同一目录的 App.tsx 中导入并提供 wrapper:

import Greeting from "./Greeting.html.tsx";

export default function App() {
  return (
    <Greeting
      name="Typeset"
      children="Welcome"
      renderWrapper={(html) => <section dangerouslySetInnerHTML={{ __html: html }} />}
    />
  );
}

插件将上述调用替换成等价的 wrapper JSX:

<section dangerouslySetInnerHTML={{ __html: "<p>Hello Typeset: Welcome</p>" }} />

原静态组件 import 被移除。静态内容没有 hydration,也不保留内部 React 事件处理器;需要交互时,将状态和事件放在外层普通 React 组件或 wrapper 中。

API 与渲染行为

可以标记具名导出,也可以传入异步函数。异步操作会影响模块转换所需的时间。直接返回的字符串被视为 HTML,需由生成端负责转义。

由于顶层静态函数在 React 渲染器外直接调用,不要在该函数中依赖 useStateuseContext 等需要 React 渲染上下文的 hooks。

使用限制

完整输入范围、资源行为和实现说明见核心包 README

样式、图片和排查入口

组件可以导入 CSS Module,并把类名写入静态 JSX。图片使用 import photoUrl from "./photo.png?url",插件会保留资源依赖并尝试把 HTML 中的开发 URL 改写为 Vite 管理的构建 URL。

包含 CSS Module、PNG、共享 SVG 和具名组件的完整用例见 React 构建 fixture

若浏览器出现 staticComponent() was evaluated in the browser 警告,说明标记函数进入了客户端执行。检查插件是否注册、文件是否为 .tsx、标记是否来自本包 /runtime,以及导出方式是否在支持范围内。标记函数自身不会执行 wrapper,不能作为插件缺失时的完整降级方案。

验证

在仓库根目录执行:

pnpm --filter @typeset/vite-plugin-static-component-react test
pnpm --filter @typeset/vite-plugin-static-component-react exec tsc --noEmit
pnpm --filter @typeset/vite-plugin-static-component-integration-test test
pnpm --filter @typeset/vite-plugin-static-component-integration-test test:types

本包单元测试检查适配配置及生成的模块源码;集成测试验证真实构建产物。