ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Storybook 实战:在 TanStack React 框架中屏蔽服务端模块(`sb.mock` + `__mocks__` 文件注册指南)

Storybook 实战:在 TanStack React 框架中屏蔽服务端模块(`sb.mock` + `__mocks__` 文件注册指南) Storybook 实战在 TanStack React 框架中屏蔽服务端模块sb.mock__mocks__文件注册指南【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook导读TanStack Start 应用的路由文件常在模块顶层导入数据库客户端、认证库等仅运行于 Node.js 的服务端包。当 Storybook 在浏览器中加载路由树时这些导入会直接导致运行时崩溃。本文基于 Storybook 官方文档的 TanStack React 框架集成讲解如何在.storybook/preview.ts中通过sb.mock(import(../src/db/client.ts))注册 mock并结合__mocks__文件彻底阻止服务端模块及其依赖链在浏览器中被求值——同时覆盖 CSF 3 与 CSF Next 两代配置写法并附上源码级的原理剖析。场景背景为什么 TanStack Start 的路由会带崩浏览器TanStack Start 是构建在 TanStack Router 之上的全栈 React 框架其路由文件经常在模块顶层直接导入服务端专用依赖例如数据库客户端postgres、pg、drizzle-orm/postgres-js等认证 / 会话库~/auth/index.server等其他依赖 Node.js 运行时能力的包Storybook 需要加载整棵路由树才能渲染路由组件这些模块级导入一旦进入浏览器就会出现类似does not provide an export named default或AsyncLocalStorage is not defined的报错。针对这一问题TanStack React 框架文档 给出了三层处理策略框架级自动 mockstorybook/tanstack-react的 preset 会自动拦截tanstack/react-start、tanstack/react-start/server、tanstack/start-storage-context等 TanStack 相关模块并把createServerFn().handler(...)的结果替换为可观察、可覆写的 mock 函数此层无需开发者干预应用级服务端模块对于应用自有的服务端代码如~/db/client、~/auth/index.server需要在.storybook/preview.ts中注册sb.mock并配套__mocks__文件识别排查根据报错堆栈定位需要 mock 的模块详见下文。本文聚焦第二层——即关联文档中演示的注册写法。在.storybook/preview.ts中注册模块 mock当你的路由引入了应用自有的服务端模块例如~/db/client内部import了postgres时需要先在项目级 Storybook 配置.storybook/preview.ts中注册 mock。关联文档提供了两种写法CSF 3 写法import { sb } from storybook/test; // Prevents postgres (Node-only) from loading in the browser sb.mock(import(../src/db/client.ts)); export default {};CSF Next 写法import { definePreview } from storybook/tanstack-react; import { sb } from storybook/test; // Prevents postgres (Node-only) from loading in the browser sb.mock(import(../src/db/client.ts)); export default definePreview({});两种写法的核心都是这一行sb.mock(import(../src/db/client.ts));区别仅在于配置文件的导出方式CSF 3 导出普通对象而 CSF Next 使用storybook/tanstack-react提供的definePreview包裹配置。从 源码实现 可以看到definePreview本质上是调用storybook/react的__definePreview并把 TanStack 专用的 preview 注解路由装饰器、loader、beforeEach 等定义于 preview.tsx注入进去export function definePreview(preview) { return __definePreview({ ...preview, addons: [tanstackPreview, ...(preview.addons ?? [])], }); }创建配套的__mocks__文件注册之后还要在真实模块旁边创建对应的__mocks__文件。以src/db/client.ts为例创建src/db/__mocks__/client.ts且只使用import type确保不会把任何服务端包带入浏览器import type { drizzle } from drizzle-orm/postgres-js; import type * as schema from ../schema; export const db new Proxy({} as ReturnTypetypeof drizzletypeof schema, { get: () () Promise.resolve([]), });关键点用import type引入drizzle与schema——类型导入在编译期会被擦除不会产生任何运行时加载用Proxy提供惰性db对象任何属性访问都返回一个 resolve 为空数组的 Promise 函数模拟查询方法的形状mock 文件必须以 JavaScript/ESM 的命名导出方式导出与原始模块同名的导出模块 mock 文档 的 automocking 章节对此有完整约束说明。为什么这里必须用__mocks__文件而不是 automockingsb.mock的 automocking 机制默认会把原模块的导出替换为 Vitest mock 函数但原模块本身及其依赖仍然会被求值。对于导入postgres、pg这类纯 Node.js 包的模块一旦模块被求值就会在浏览器中崩溃。因此TanStack React 框架文档 明确指出__mocks__文件是唯一能完全阻止原始模块及其依赖链被求值的方案。sb.mock在解析时会优先在对应目录下查找__mocks__文件命中后直接加载 mock 文件原始模块永远不会进入浏览器。该机制底层如何工作从 preset.ts 的实现可以看到storybook/tanstack-react的viteFinal会注入三个关键 Vite 插件serverCodeEliminationPlugin在构建期消除服务端专用代码serverOnlyStubPlugin对服务端专用模块提供桩stubmoduleInterceptionPlugin把tanstack/react-router等模块的导入重定向到storybook/tanstack-react内置的 mock 层export-mocks 目录。而sb.mock本身建立在 Storybook 的 automocking 机制之上基于 Vitest mocking 引擎所有 mock 决策在构建期完成没有运行时开销mock 的注册只允许出现在项目级.storybook/preview.*文件中不能在单个 story 文件中注册。定位该 mock 谁的排查方法如果浏览器仍报错可按以下规则定位目标模块框架文档mock 服务端模块本身而不是使用它的组件或路由。例如Dashboard.tsx→~/auth/session→~/db/client→postgres应 mock 离postgres最近的、且由你控制的模块这里是~/db/client从报错堆栈顶部往下走停在第一个你自己编写的 import处为它添加__mocks__文件以下两种情况无需mock模块来自tanstack/*已被框架 preset 处理请确保使用最新版storybook/tanstack-react模块只导入createServerFn已被自动 mock报错应来自同一文件中的其他 import。使用场景与后续扩展完成上述两步后TanStack Start 的组件包括依赖服务端函数的页面即可在 Storybook 中直接渲染。在此基础上你还可以在 story 中用标准 mock API 覆写被自动 mock 的createServerFn().handler(...)分别呈现 loading、success、error 状态详见 TanStack 框架文档结合 Storybook 的模块 mock 全量能力spy-only、fully automocked、mock files 三种注册方式与 Vitest mock 方法表见 Mocking modules 文档。参考框架文档docs/get-started/frameworks/tanstack-react.mdx模块 mock 总览docs/writing-stories/mocking-data-and-modules/mocking-modules.mdx框架源码code/frameworks/tanstack-react/src/index.ts、code/frameworks/tanstack-react/src/preset.ts【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表