
Wasp 客户端配置指南rootComponent、setupFn 与 baseDir 全解析【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/waspWasp 通过在app声明Wasp 0.18 时代的main.wasp中暴露一个client字段让你以声明式的方式配置 React 前端用rootComponent定义应用的包裹根组件用setupFn挂载客户端启动前的自定义逻辑用baseDir支持从子路径部署。读完本文你将掌握这三个核心配置项的参数语义、写法与底层实现能够为 Wasp 应用注入全局 Provider、公共布局、全局查询缓存策略与子目录部署能力。client 字段应用声明的组成部分在app声明内部与title、db、auth等字段平级client是一个对象字面量集中描述客户端的三个可选配置项rootComponent、setupFn与baseDir。一个最小完整的写法如下app MyApp { title: My app, // ... client: { rootComponent: import Root from src/Root.jsx, setupFn: import mySetupFunction from src/myClientSetupCode.js } }TypeScript 项目的写法一致仅把导入路径换成.tsx/.tsapp MyApp { title: My app, // ... client: { rootComponent: import Root from src/Root.tsx, setupFn: import mySetupFunction from src/myClientSetupCode.ts } }说明本文对应 Wasp 0.18versioned_docs/version-0.18的配置语法在新版本中Wasp 已迁移到 TypeScript 规范的main.wasp.ts可参考 web/docs/project/client-config.md配置项语义保持一致。仓库示例 examples/kitchen-sink/main.wasp.ts 中即可看到client字段同时携带rootComponent、setupFn与envValidationSchema的完整用法。Root Component应用级包裹组件Wasp 允许你定义一个包裹wrapper组件作为 React 应用的根。它的典型用途有两个定义全站公共布局以及挂载应用需要的各种 Provider。定义公共布局假设要为整个应用统一加上页头与页脚只需把Root组件接入client.rootComponentapp MyApp { title: My app, // ... client: { rootComponent: import Root from src/Root.jsx, } }对应的根组件源码TypeScript 项目把扩展名换成.tsx即可import { Outlet } from react-router-dom export default function Root() { return ( div header h1My App/h1 /header Outlet / footer pMy App footer/p /footer /div ) }关键点必须从react-router-dom导入Outlet并把它放在希望渲染当前页面的位置。Outlet是 React Router 的出口Wasp 生成的路由会在此处渲染当前页面组件。仓库中的真实示例非常直观examples/waspello/src/Layout.tsx被注册为 examples/waspello/main.wasp.ts 的rootComponent其实现就是直接渲染Outlet /而examples/ask-the-documents与examples/websockets-realtime-voting同样以各自Layout作为根组件。这说明根组件 布局容器是 Wasp 官方示例中的标准用法。挂载全局 Provider当应用需要全局状态如 Redux store、主题或国际化上下文时把 Provider 包在Outlet外层即可import { Outlet } from react-router-dom import store from ./store import { Provider } from react-redux export default function Root() { return ( Provider store{store} Outlet / /Provider ) }只要渲染了Outlet在根组件里放任何内容Provider、布局、错误边界等都是合法的。API 层面rootComponent的类型是ExtImport即指向一个 React 组件的 Wasp 导入声明。Setup Function客户端启动前的钩子setupFn声明一个 JavaScript/TypeScript 函数Wasp 会在客户端一切其他逻辑之前执行它。从 API 契约看该函数应当是异步的Wasp 会等待其完成后再渲染页面不接收任何参数返回值会被忽略。适合放置客户端周期任务、第三方 SDK 初始化、全局查询配置等启动前必做的工作。在 setup 函数中运行任意代码例如下面的 setup 函数每小时在控制台打印一条在线时长消息export default async function mySetupFunction() { let count 1 setInterval( () console.log(You have been online for ${count} hours.), 1000 * 60 * 60 ) }TypeScript 版本只需加上返回类型标注export default async function mySetupFunction(): Promisevoid { let count 1 setInterval( () console.log(You have been online for ${count} hours.), 1000 * 60 * 60 ) }仓库示例 examples/kitchen-sink/src/clientSetup.js 展示了真实项目中的 setup 写法打印启动日志、根据import.meta.env.SSR跳过浏览器专属逻辑、并调用configureQueryClient调整全局查询默认值——这正是下文要讲的典型场景。覆盖 Query 的全局默认行为Wasp 的useQueryhook 底层基于react-query的useQuery实现。react-query 自带激进但合理的默认选项如窗口聚焦时自动重新拉取、缓存陈旧策略等多数应用无需改动如果确实需要调整全局默认值就在客户端 setup 函数里通过configureQueryClient完成。configureQueryClient从wasp/client/operations导出接收一个与QueryClient构造函数兼容的配置对象import { configureQueryClient } from wasp/client/operations export default async function mySetupFunction() { // ... some setup configureQueryClient({ defaultOptions: { queries: { staleTime: Infinity, }, }, }) // ... some more setup }staleTime: Infinity表示数据永不过期——只要拉取过一次就不会因为组件重新挂载或窗口聚焦而再次请求适合更新频率极低的数据。从源码看这套机制的实现见 waspc/data/Generator/templates/sdk/wasp/client/operations/queryClient.tsconfigureQueryClient(config)只是暂存配置若在 QueryClient 初始化之后再次调用会直接抛出Attempted to configure the QueryClient after initializationinitializeQueryClient()才真正以该配置new QueryClient(...)并标记初始化完成两个函数通过queryClientInitializedPromise 串联wasp/client/operations的公共出口 index.ts 同时导出二者——这正是setup 函数必须先于一切执行、再初始化 QueryClient这一时序约束的代码级体现。单条 Query 的选项覆盖如果只想调整某一条Query 的行为不必动用全局配置直接使用useQuery的options对象参数即可详见 web/docs/data-model/operations/queries.md 中 useQuery hook 一节。baseDir从子路径提供服务默认情况下Wasp 应用部署在域名根路径。如果你的应用需要挂在某个子路径下例如https://example.com/my-app使用baseDir选项app MyApp { title: My app, // ... client: { baseDir: /my-app, } }设置baseDir后Wasp 会做两件事API 参考中的原话一是把 React Router 的basenameprop 设为/my-app让路由在子路径下正常工作二是把 Vite 配置的base选项设为/my-app让所有静态资源JS/CSS/图片等都从https://example.com/my-app下加载。务必同步设置 WASP_WEB_CLIENT_URL启用baseDir时有一个容易踩坑的配套要求见 web/docs/project/_baseDirEnvNote.md环境变量WASP_WEB_CLIENT_URL必须包含该子路径。如果应用托管在https://example.com/my-app那么WASP_WEB_CLIENT_URL应设为https://example.com/my-app而不是仅设为https://example.com否则服务端生成的前端 URL、认证回调等链路会出现路径不一致的问题。底层校验逻辑baseDir的取值不是任意的。从 waspc/src/Wasp/AppSpec/Valid.hs 的校验函数validateWebAppBaseDir可以看到baseDir必须以斜杠/开头否则 Wasp 会抛出校验错误The app.client.baseDir should start with a slash e.g. \/test\。生成阶段WebAppGenerator/Common.hs 会把baseDir解析为绝对路径缺省时回退到根路径/。此外Vite 插件生成器 VitePluginG.hs 也会把baseDir写入生成配置印证了router basename Vite base双重生效的实现方式。API Reference 速查把三项配置合在一起的完整形态如下TypeScript 项目把导入路径替换为.tsx/.ts并可额外携带baseDirapp MyApp { title: My app, // ... client: { rootComponent: import Root from src/Root.tsx, setupFn: import mySetupFunction from src/myClientSetupCode.ts, baseDir: /my-app, } }三个选项的类型与语义速查rootComponent: ExtImport客户端应用的根组件。必须是一个 React 组件Wasp 会以它为客户端应用根它必须渲染react-router-dom的Outlet以显示当前页面。适合同时挂 Provider 与自定义布局例如把 Provider 放在外层、Layout内部再渲染Outlet。setupFn: ExtImport客户端启动前执行的异步函数Wasp 会等待其 Promise 完成后才开始渲染页面函数不接受参数返回值被忽略。适合执行任意自定义初始化如客户端周期任务、全局 QueryClient 配置。baseDir: String客户端部署子路径。设置后同时影响 React Router 的basename与 Vite 的base且必须以/开头配套要求WASP_WEB_CLIENT_URL环境变量包含该子路径。若需在源码中进一步确认这些字段的类型定义可查看 waspc/src/Wasp/AppSpec/App/Client.hs其中baseDir :: Maybe String等字段与上述语义一一对应。【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考