Wasp 运行时配置详解:通过 Server/Client 配置对象访问 WASP_WEB_CLIENT_URL 与 REACT_APP_API_URL
【免费下载链接】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 应用启动时实际运行的是两个独立进程(React 客户端与 Express 服务端),而两端之间、前端与后端之间的 URL 关系,正是跨域(CORS)、认证回调、邮件链接等功能能否正常工作的关键。本文围绕 Wasp 官方的《Accessing the configuration》文档展开,讲清楚两个进程各自的配置对象如何暴露、背后对应哪些环境变量,并结合 waspc 生成器源码说明这些配置在底层是如何被注入、消费和校验的,帮助你在部署排障时能快速定位“URL 配置”类问题。
Wasp 应用的运行时模型:两个进程,两种形态
根据官方文档 accessing-app-config.md,每次启动一个 Wasp 应用,你实际上启动了两个进程:
- 客户端进程(client process):一个实现应用前端的 React 应用。
- 开发阶段:这是一个带热重载(hot reloading)的开发服务器(dev server)。
- 生产阶段:只是一个静态进程,负责提供构建产物(pre-built static files),环境变量在构建时就被嵌入,具体细节取决于你的部署方式(见 deployment/intro)。
- 服务端进程(server process):一个实现应用后端的 Express 服务器。
- 开发阶段:这个 Express 服务器由
nodemon进程控制,负责热重载与重启。 - 生产阶段:由 Node 直接运行的普通 Express 服务器。
- 开发阶段:这个 Express 服务器由
Wasp 运行时的更完整架构说明可以参考 introduction。两个进程都通过环境变量来配置,完整的环境变量清单见 env-vars。
配置对象总览:运行时读取进程配置的唯一入口
Wasp 通过configuration objects(配置对象)在运行时把两个进程的配置暴露给你的业务代码,而不是让你直接去读process.env。核心 API 只有两组导入:
// 服务端代码 import { config } from 'wasp/server' // 客户端代码 import { config } from 'wasp/client'这两个config并不是手写文件,而是 waspc 编译 Wasp 应用时由 SDK 生成器注入的代码。在生成器模板中可以看到服务端配置的完整实现:waspc/data/Generator/templates/sdk/wasp/server/config.ts,以及客户端配置的实现:waspc/data/Generator/templates/sdk/wasp/client/config.ts。
Server 配置对象:frontendUrl 字段
官方文档说明,server 配置对象包含以下字段:
frontendUrl: String—— 通过环境变量WASP_WEB_CLIENT_URL设置。- 你的客户端(应用前端)的 URL;
- 开发阶段运行
wasp start时由 Wasp 自动设置; - 生产阶段应设置为服务端视角下的客户端 URL(即考虑 DNS 与代理之后的最终地址)。
访问方式:
import { config } from 'wasp/server' console.log(config.frontendUrl)源码视角:frontendUrl 不止是一个字符串
从生成模板 server/config.ts 可以看到几个文档未展开的实现细节:
环境变量名由生成器注入:模板中
env['{= clientUrlEnvVarName =}']是占位符,真实值WASP_WEB_CLIENT_URL定义在 Haskell 生成器里 —— waspc/src/Wasp/Generator/ServerGenerator/Common.hs 中的clientUrlEnvVarName = "WASP_WEB_CLIENT_URL"。会自动去除尾部斜杠:
const frontendUrl = stripTrailingSlash(env['WASP_WEB_CLIENT_URL']),因此你配置https://app.example.com/和https://app.example.com效果一致,拼接 URL 时不会多出/。直接驱动生产环境 CORS 白名单:
const allowedCORSOriginsPerEnv: Record<NodeEnv, Config['allowedCORSOrigins']> = { development: [/.*/], production: [getOrigin(frontendUrl)] }开发环境下放行所有来源;生产环境仅放行
frontendUrl的 origin。这也解释了 waspc/ChangeLog.md 中的一条历史变更记录:WASP_WEB_CLIENT_URL被设为必需的环境变量,用于收紧 CORS 安全。如果生产环境frontendUrl配错,前端请求会在浏览器端被 CORS 直接拦截。服务端配置对象实际比文档示例更丰富:同一模板中还导出了
serverUrl、port、databaseUrl、env、isDevelopment、allowedCORSOrigins,以及启用认证时的auth.jwtSecret等字段。官方文档此处只介绍面向用户的核心字段frontendUrl,其余属于 Wasp 内部使用的字段。
谁在消费 frontendUrl:认证与 WebSocket 的默认行为
frontendUrl并不是一个仅供你查询的字段,Wasp SDK 内部多处默认行为依赖它:
- 认证邮件链接:waspc/data/Generator/templates/sdk/wasp/server/auth/email/utils.ts 中,验证邮箱等场景生成的链接形如
`${waspServerConfig.frontendUrl}${clientRoute}?token=${jwtToken}`。若该值指向错误地址,用户点邮件里的验证链接会跳到错误的域名。 - OAuth 回调重定向:waspc/data/Generator/templates/sdk/wasp/server/auth/oauth/redirect.ts 用
config.frontendUrl构造.../#oneTimeCode或带error参数的回调 URL。 - WebSocket 连接校验:waspc/data/Generator/templates/server/src/webSocket/initialization.ts 中把
config.frontendUrl的 origin 作为verifyClient的允许来源。
可以推断:只要你的应用涉及认证(邮箱验证、社交登录)或 WebSocket 实时功能,frontendUrl配错的症状都会指向“URL 配置”而非业务代码本身,这是排障时的第一排查点。
Client 配置对象:apiUrl 字段
官方文档说明,client 配置对象包含以下字段:
apiUrl: String—— 通过环境变量REACT_APP_API_URL设置。- 你的服务端(应用后端)的 URL;
- 开发阶段运行
wasp start时由 Wasp 自动设置; - 生产阶段应包含用户浏览器视角下的服务端 URL(即考虑 DNS 与代理之后的最终地址)。
访问方式:
import { config } from 'wasp/client' console.log(config.apiUrl)源码视角:构建时内联 + 运行时校验
客户端配置的实现见 waspc/data/Generator/templates/sdk/wasp/client/config.ts:
const apiUrl = stripTrailingSlash(env["{= serverUrlEnvVarName =}"]) // PUBLIC API export type ClientConfig = { apiUrl: string, } // PUBLIC API export const config: ClientConfig = { apiUrl, }同样地,这里也做了stripTrailingSlash处理。而它依赖的env来自 waspc/data/Generator/templates/sdk/wasp/client/env.ts:
export const env: z.infer<CompleteClientEnvSchema> = ensureEnvSchema( import.meta.env, clientEnvSchema, )从这段源码结构看,客户端配置有两个值得注意的特性:
- 值来自
import.meta.env:这是 Vite 的机制,环境变量在构建时被静态内联进前端产物。这与文档中“生产阶段客户端是提供静态文件的进程,环境变量在构建时嵌入”的描述一致——这意味着生产环境改REACT_APP_API_URL必须重新构建前端,而不是重启进程就能生效。 - 有 zod schema 运行时校验:
ensureEnvSchema配合clientEnvSchema在客户端代码首次访问env时校验取值,配置缺失或非法会在运行时直接暴露,而不是静默地拿到undefined。
开发环境的 URL 管理:交给 wasp start 自动处理
文档反复强调“Wasp automatically sets it during development when you runwasp start”,这一点在源码中同样有对应:生成器会按运行环境把 URL 环境变量注入服务端的运行配置,见 waspc/src/Wasp/Generator/ServerGenerator/RunConfig.hs 中把clientUrlEnvVarName对应的值(clientUrl)写入启动环境。
更需要注意的是,waspc/ChangeLog.md 记录了这一机制的收紧:
Wasp now manages your app's URLs in development, so setting
WASP_SERVER_URL,WASP_WEB_CLIENT_URL, orREACT_APP_API_URLyourself is now an error.
也就是说,在较新版本中,Wasp 在开发阶段接管这三个 URL 变量,你自己在开发环境中手动设置它们反而会报错。这两个变量本质上只需要你在生产部署时显式提供。部署工具链也印证了这一点:Wasp 的部署提供者在生成部署配置时会自动写入这些变量,例如 Fly 部署会写入WASP_WEB_CLIENT_URL=<前端应用的 Fly App 地址>(见 waspc/data/packages/deploy/src/providers/fly/commands/setup/setup.ts),Railway 部署同样会自动带上WASP_WEB_CLIENT_URL(见 waspc/data/packages/deploy/src/providers/railway/commands/setup/setup.ts)。
生产环境配置清单与实践建议
结合文档与源码,一个 Wasp 应用上线时关于“配置对象”的最小事实清单如下:
| 配置字段 | 访问方式 | 对应环境变量 | 设置责任方 |
|---|---|---|---|
config.frontendUrl(server 侧) | import { config } from 'wasp/server' | WASP_WEB_CLIENT_URL | 开发:wasp start自动设置;生产:部署时设为服务端视角的前端 URL |
config.apiUrl(client 侧) | import { config } from 'wasp/client' | REACT_APP_API_URL | 开发:wasp start自动设置;生产:设为浏览器视角的后端 URL |
由此可得出几条可直接落地的实践结论(均有文档或源码依据):
- 两个变量视角不同,不能互相照抄。
frontendUrl是“服务端眼中的前端”,apiUrl是“浏览器眼中的后端”。如果你的前后端分别部署在不同域名/端口,这两个变量会取到不同的值;同一域名下则可以相同。 - 生产环境
WASP_WEB_CLIENT_URL必须准确:它参与生产 CORS 白名单(getOrigin(frontendUrl))、认证链接拼接与 WebSocket 来源校验,是多数“部署后前端请求 403/CORS 报错、验证邮件打不开、WebSocket 连不上”问题的根源。 - 前端 URL 变更需要重新构建客户端:因为
apiUrl在构建时内联进静态产物,修改后必须重新 build 前端,仅重启服务端无效。 - 不要在开发环境手动覆盖这三个 URL 变量:新版本会将其作为错误处理(见 ChangeLog)。
小结
Wasp 的“访问应用配置”机制本质上很简单:两个进程各暴露一个config对象,分别用WASP_WEB_CLIENT_URL和REACT_APP_API_URL描述“前端在哪”和“后端在哪”。而深入源码后可以确认,这两个值不是摆设——服务端配置模板 server/config.ts 用它们驱动生产 CORS 策略、认证邮件与 OAuth 回调链接、WebSocket 来源校验,客户端配置模板 client/config.ts 则通过 Vite 构建时内联 + zod 校验保证值可用。理解这条“环境变量 → 生成器注入 → 配置对象 → SDK 内部消费”的链路,基本就能覆盖 Wasp 应用中与 URL 配置相关的全部排障场景。
【免费下载链接】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),仅供参考