
Wasp 服务端配置指南setupFn 与 middlewareConfigFn 深度实践【免费下载链接】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本文基于 Wasp 0.11.8 版本官方文档server-config.md编写结合仓库源码与示例应用系统讲解如何通过app声明中的server字段定制服务端行为。读完你将掌握两件事一是用setupFn在服务启动时注入自定义逻辑注册路由、初始化资源、提交后台任务二是用middlewareConfigFn全局定制 Express 中间件栈如扩展 CORS 域名并能理解这些配置在生成代码中的落地位置。Wasp 是一个电池全带的全栈框架其服务端基于 Express 构建但大部分中间件、路由挂载、启动流程都由框架自动生成。当默认行为无法满足需求时你不需要弹出整个工程只需在main.wasp的app声明中填写server字段声明两个钩子函数即可app MyApp { title: My app, // ... server: { setupFn: import { mySetupFunction } from server/myServerSetupCode.js, middlewareConfigFn: import { myMiddlewareConfigFn } from server/myServerSetupCode.js } }app.server是一个包含setupFn、middlewareConfigFn两个字段的字典。其中setupFn负责启动时初始化middlewareConfigFn负责全局中间件定制。下面分别展开。一、Setup Function服务启动时的初始化钩子setupFn声明一个在服务端启动时执行的函数JavaScript 或 TypeScript 均可。它必须是 async 函数且 Wasp 会等待它完成后才开始接收请求——这意味着你可以放心地在其中完成依赖资源的初始化而不必担心出现竞态。它的能力边界很宽可以建立额外的数据库连接、初始化 WebSocket 服务、启动 cron/定时任务等。它的上下文context中带有express.Application和http.Server两个实例分别用于注册自定义路由和搭建socket.io这类需要原生 HTTP Server 的能力。1. 在 setupFn 中注册自定义路由最常见的用法是添加框架默认没有提供的路由。以下示例在服务启动时向 Express 应用挂载一个GET /customRouteimport { ServerSetupFn, Application } from wasp/types export const mySetupFunction: ServerSetupFn async ({ app }) { addCustomRoute(app) } function addCustomRoute(app: Application) { app.get(/customRoute, (_req, res) { res.send(I am a custom route) }) }在 TypeScript 项目中ServerSetupFn及其上下文的类型定义如下来自wasp/typesexport type ServerSetupFn (context: ServerSetupFnContext) Promisevoid export type ServerSetupFnContext { app: Application // express.Application server: Server // http.Server }从 Wasp 生成模板server.ts可以看出该函数的真实调用位置生成的服务端入口会先创建http.createServer(app)随后在监听端口之前调用你声明的setupFn并await它确认初始化完成后才对外提供服务。这一实现与文档启动时执行、完成后才接受请求的描述完全一致。2. 在 setupFn 中初始化资源并供 Operations 复用当你需要初始化某些资源例如数据库连接池、内存缓存、外部服务客户端并希望之后在 Query/ActionOperations中读取时同样在setupFn中完成。官方推荐的模式是模块即单例把变量放在定义 setup 函数的同一模块中再导出只读访问函数供 Operations 导入import { ServerSetupFn } from wasp/types let someResource undefined export const mySetupFunction: ServerSetupFn async () { // 假设 setUpSomeResource 与 startSomeCronJob 在下方实现或从其他文件导入 someResource await setUpSomeResource() startSomeCronJob() } export const getSomeResource () someResource然后在 Query 中直接导入使用import { SomeQuery } from wasp/queries/types import { getSomeResource } from ./myServerSetupCode.js export const someQuery: SomeQuery... async (args, context) { const someResource getSomeResource() return queryDataFromSomeResource(args, someResource) }注意官方明确建议不要试图通过闭包变量在模块间共享而是在定义 setupFn 的同一模块中持有变量并导出读取函数。这样该模块就等价于一个构造发生在服务启动时的单例语义清晰、便于测试。仓库中的真实示例 examples/kitchen-sink/src/serverSetup.ts 完整演示了这一模式模块顶部声明let someResourceserverSetup函数内await一个 2 秒的初始化过程后赋值同时注册自定义路由、提交后台 Job并导出getSomeResource供其他模块读取。这印证了 setupFn 的三类典型用途路由注册、资源初始化、任务提交。另一个示例 examples/waspleau/src/serverSetup.js 则展示了 setupFn 的轻量形态——它导出一个无参 async 函数在启动时直接向 Job 队列提交refreshGitHubRepoData与measureLoadTime两个任务用几行代码完成了服务启动即拉取指标的定时任务编排可见 setupFn 也可以作为后台任务的点火开关。二、Middleware Config Function定制全局中间件middlewareConfigFn用于修改全局中间件栈其改动会影响所有 OperationsQuery 与 Action以及所有api路由。1. Wasp 默认提供的全局中间件每个 Wasp 应用都会自带一套精简但实用的 Express 中间件见 middleware-config 文档中间件作用Helmet通过设置各类 HTTP 响应头加固 Express 应用非银弹但良好的起点CORS启用跨域支持前端与后端通信的必要条件MorganloggerHTTP 请求日志记录器dev 格式express.json基于 body-parser 解析 JSON 请求体结果挂到req.bodyOperations 正常工作的必要条件express.urlencoded解析application/x-www-form-urlencoded请求体cookieParser解析 Cookie 头并填充req.cookies其底层定义是一个以字符串为键的 Map例如export type MiddlewareConfig Mapstring, express.RequestHandler // 示例中用到的类型 export type MiddlewareConfigFn (middlewareConfig: MiddlewareConfig) MiddlewareConfig const defaultGlobalMiddleware: MiddlewareConfig new Map([ [helmet, helmet()], [cors, cors({ origin: config.allowedCORSOrigins })], [logger, logger(dev)], [express.json, express.json()], [express.urlencoded, express.urlencoded()], [cookieParser, cookieParser()] ])2. 自定义全局中间件在main.wasp中声明middlewareConfigFn并在对应源码文件中实现该函数。函数接收中间件 Map 的克隆副本对其进行增删改后返回app MyApp { title: My app, // ... server: { setupFn: import { mySetupFunction } from server/myServerSetupCode.js, middlewareConfigFn: import { myMiddlewareConfigFn } from server/myServerSetupCode.js } }import cors from cors import { config } from wasp/server import type { MiddlewareConfigFn } from wasp/server export const myMiddlewareConfigFn: MiddlewareConfigFn (middlewareConfig) { // 示例在默认 CORS 域名基础上追加额外的域名 middlewareConfig.set( cors, cors({ origin: [...config.allowedCORSOrigins, https://example1.com, https://example2.com] }) ) return middlewareConfig }⚠️警示修改全局中间件会波及所有 Operations 和 API请务必谨慎。如果只想影响某一条路由应优先使用 per-api 或 per-path 级别的定制。从源码看该函数的调用逻辑位于生成模板 globalMiddleware.ts 的globalMiddlewareConfigForExpress函数中当未提供middlewareConfigFn时直接返回全局 Map 的中间件数组提供时则先克隆一份全局 Map防止修改污染其他路由再调用你的函数并返回修改后的中间件数组。这也解释了为什么自定义函数中可以安全地delete、set而不影响默认配置。仓库示例 examples/kitchen-sink/src/serverSetup.ts 中的serverMiddlewareFn正是此模式的标准实现读取config.allowedCORSOrigins并追加http://127.0.0.1:3000用于本地开发时允许额外来源访问。对应的 examples/kitchen-sink/main.wasp.ts 中同时配置了setupFn、middlewareConfigFn与envValidationSchema可作为完整参考。3. 更细粒度的中间件定制延伸如果你只想影响个别路由可参考 middleware-config 文档 中的另外两级定制per-api 定制在api声明上配置middlewareConfigFn例如把 webhook 回调的express.json换成express.raw({ type: */* })。底层按方法级别安装等价于router.post(/webhook/callback, webhookCallbackMiddleware, ...)。per-path 定制在apiNamespace上配置middlewareConfigFn可作用于某路径下的所有方法对同时需要OPTIONS与GET的复杂 CORS 场景尤其有用底层等价于router.use(/foo/bar, fooBarNamespaceMiddleware)。从 AppSpec 源码 与 ApiNamespace.hs 可以看到middlewareConfigFn在 Wasp 内部是以ExtImport外部导入引用形式存储的字段分别挂在Api与ApiNamespace数据结构上而 Server.hs 则把setupFn、middlewareConfigFn、envValidationSchema一并定义为app声明中server字段的合法选项——三者共同构成服务端可配置面的完整骨架。三、API Referenceserver 字段速查app.server字段汇总如下setupFn: ServerImport声明一个在服务启动时执行的函数。要求为 async 函数且在服务开始接受请求前被 await。可用于自定义数据库/WebSocket 初始化、启动 cron/定时任务等。函数上下文包含appexpress.Application与serverhttp.Server两个实例便于注册自定义路由或接入socket.io。middlewareConfigFn: ServerImport指向 Express 全局中间件配置函数的导入声明。属于全局修改影响所有 Operations 与 API 的中间件栈详见 配置中间件一节。envValidationSchema: ServerImport由 Server.hs 确认存在 服务端环境变量的 Zod 校验 Schema可与setupFn、middlewareConfigFn并列配置用于在启动前校验服务端环境变量。四、实践建议把初始化集中在 setupFn 中凡是服务端首次可用前必须就绪的资源连接池、外部客户端、内存状态都放进 setupFn 并await框架保证请求到达前完成。用模块单例模式暴露资源在 setupFn 所在模块持有变量并导出访问函数而非在模块间传递闭包便于 Operations 直接导入且语义清晰。全局中间件改动要克制优先使用 per-api / per-path 定制确需全局修改时利用返回的 Map 克隆安全增删典型场景是扩展 CORS 白名单。善用 Job 编排启动任务参考 waspleau 示例在 setupFn 中提交后台 Job即可用最少代码实现启动即拉取数据/执行周期任务的效果。参考完整示例需要同时使用setupFn、middlewareConfigFn的完整工程可直接阅读 kitchen-sink 示例 及其 serverSetup.ts其中包含了自定义路由、异步初始化、CORS 扩展、Job 提交与类型标注的完整组合。关于 OperationsQuery/Action如何与初始化后的资源协作可继续阅读 Operations 概览关于中间件更细粒度的 per-api / per-path 定制参见 middleware-config 文档。【免费下载链接】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),仅供参考