news 2026/9/11 9:17:08

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 框架,其路由文件经常在模块顶层直接导入服务端专用依赖,例如:

  • 数据库客户端(postgrespgdrizzle-orm/postgres-js等)
  • 认证 / 会话库(~/auth/index.server等)
  • 其他依赖 Node.js 运行时能力的包

Storybook 需要加载整棵路由树才能渲染路由组件,这些模块级导入一旦进入浏览器,就会出现类似does not provide an export named 'default'AsyncLocalStorage is not defined的报错。

针对这一问题,TanStack React 框架文档 给出了三层处理策略:

  1. 框架级自动 mock@storybook/tanstack-react的 preset 会自动拦截@tanstack/react-start@tanstack/react-start/server@tanstack/start-storage-context等 TanStack 相关模块,并把createServerFn().handler(...)的结果替换为可观察、可覆写的 mock 函数,此层无需开发者干预;
  2. 应用级服务端模块:对于应用自有的服务端代码(如~/db/client~/auth/index.server),需要在.storybook/preview.ts中注册sb.mock,并配套__mocks__文件;
  3. 识别排查:根据报错堆栈定位需要 mock 的模块(详见下文)。

本文聚焦第二层——即关联文档中演示的注册写法。

.storybook/preview.ts中注册模块 mock

当你的路由引入了应用自有的服务端模块(例如~/db/client内部importpostgres)时,需要先在项目级 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 ReturnType<typeof drizzle<typeof schema>>, { get: () => () => Promise.resolve([]), });

关键点:

  • import type引入drizzleschema——类型导入在编译期会被擦除,不会产生任何运行时加载;
  • Proxy提供惰性db对象,任何属性访问都返回一个 resolve 为空数组的 Promise 函数,模拟查询方法的形状;
  • mock 文件必须以 JavaScript/ESM 的命名导出方式导出与原始模块同名的导出(模块 mock 文档 的 automocking 章节对此有完整约束说明)。

为什么这里必须用__mocks__文件而不是 automocking

sb.mock的 automocking 机制默认会把原模块的导出替换为 Vitest mock 函数,但原模块本身及其依赖仍然会被求值。对于导入postgrespg这类纯 Node.js 包的模块,一旦模块被求值就会在浏览器中崩溃。

因此,TanStack React 框架文档 明确指出:__mocks__文件是唯一能完全阻止原始模块及其依赖链被求值的方案sb.mock在解析时会优先在对应目录下查找__mocks__文件,命中后直接加载 mock 文件,原始模块永远不会进入浏览器。

该机制底层如何工作

从 preset.ts 的实现可以看到,@storybook/tanstack-reactviteFinal会注入三个关键 Vite 插件:

  • serverCodeEliminationPlugin:在构建期消除服务端专用代码;
  • serverOnlyStubPlugin:对服务端专用模块提供桩(stub);
  • moduleInterceptionPlugin:把@tanstack/react-router等模块的导入重定向到@storybook/tanstack-react内置的 mock 层(export-mocks 目录)。

sb.mock本身建立在 Storybook 的 automocking 机制之上(基于 Vitest mocking 引擎):所有 mock 决策在构建期完成,没有运行时开销;mock 的注册只允许出现在项目级.storybook/preview.*文件中,不能在单个 story 文件中注册。

定位"该 mock 谁"的排查方法

如果浏览器仍报错,可按以下规则定位目标模块(框架文档):

  1. mock 服务端模块本身,而不是使用它的组件或路由。例如Dashboard.tsx~/auth/session~/db/clientpostgres,应 mock 离postgres最近的、且由你控制的模块(这里是~/db/client);
  2. 从报错堆栈顶部往下走,停在第一个你自己编写的 import处,为它添加__mocks__文件;
  3. 以下两种情况无需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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 9:14:37

electerm 一次学透:跨平台终端 / SSH / SFTP 客户端,5 步跑通

electerm 一次学透&#xff1a;跨平台终端 / SSH / SFTP 客户端&#xff0c;5 步跑通 【免费下载链接】electerm &#x1f4fb;Free and open-sourced terminal/ssh/sftp/ftp/telnet/serialport/RDP/VNC/Spice client(Linux, Mac, Windows, Android, HarmonyOS, iOS) 项目地址…

作者头像 李华
网站建设 2026/9/11 9:14:28

kube-state-metrics自定义标签暴露指南:allowlist与relabel配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 9:13:10

中小企业做网站怕花冤枉钱?过来人整理的高性价比开发方清单

很多中小企业、初创团队在搭建官网时&#xff0c;都会陷入同一个困境&#xff1a;传统定制建站报价动辄数千元甚至上万元&#xff0c;开发周期长、后期维护成本高&#xff0c;而低价建站工具又容易出现功能残缺、收录差、售后无保障等问题。多数企业每年花在网站搭建、改版、运…

作者头像 李华
网站建设 2026/9/11 9:08:43

DeepSeek Harness本地评测实战:从零安装到跑通代码生成任务

"赶个晚集"这四个字&#xff0c;说的就是我。DeepSeek Harness 在圈子里其实已经讨论过一阵了&#xff0c;Codex Harness 那边带起来的评测框架热度还没退&#xff0c;DeepSeek 也顺势有了自己的 harness 方向。我一直拖着没动&#xff0c;手里的项目一个接一个&…

作者头像 李华
网站建设 2026/9/11 9:08:37

GitHub热门开源项目盘点:AI模型优化与低代码工具

1. 近期GitHub热门开源项目盘点最近在开发者社区中&#xff0c;有四个GitHub开源项目引发了广泛讨论。这些项目覆盖了从开发工具到AI模型的不同领域&#xff0c;每个都解决了特定场景下的痛点需求。作为长期关注开源生态的技术从业者&#xff0c;我整理了这些项目的核心价值、技…

作者头像 李华
网站建设 2026/9/11 9:07:54

配电网N-1扩展规划Matlab实现:从校验到优化决策

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华