Alchemy 2.0.0-beta.39 实战指南:Vite 环境变量内联、Worker HTTP 生命周期与 SendEmail 绑定

发布时间:2026/9/13 13:52:56
Alchemy 2.0.0-beta.39 实战指南:Vite 环境变量内联、Worker HTTP 生命周期与 SendEmail 绑定 Alchemy 2.0.0-beta.39 实战指南Vite 环境变量内联、Worker HTTP 生命周期与 SendEmail 绑定【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code这篇技术指南以 AlchemyEffect 生态的云基础设施即代码框架v2.0.0-beta.39版本发布说明为主体系统讲解该版本落地的高价值修复Cloudflare.Website.Vite的VITE_*环境变量内联机制、Cloudflare Worker HTTP 适配器切换到 Effect 标准 HTTP 生命周期以及SendEmailWorker 绑定的类型推断补全。读完本文你将掌握如何让 SPA 在构建期拿到部署后的 Worker URL、如何在 workerd 下正确运行基于RpcServer.toHttpEffect的 Effect HTTP 应用以及如何声明并使用send_email绑定。文中所有结论均可在仓库源码与文档中验证。版本定位beta.38 之后的三处即时痛点v2.0.0-beta.39是一个纯修复版本fix-only release针对的是用户在 beta.38 之后立刻撞上的三个问题读取import.meta.env.VITE_*的 SPA 在构建期拿不到注入的变量运行在 Cloudflare Worker 适配器下的 Effect RPC 服务尤其是RpcServer.toHttpEffect会挂起全新的SendEmail绑定没有出现在 Worker 绑定类型中部署时绑定元数据被静默丢弃。对应修复记录可在 CHANGELOG 中查到Vite env 内联issue #330、Worker HTTP effect 生命周期PR #328、SendEmail 绑定类型与元数据PR #326。Cloudflare.Website.Vite将VITE_*环境变量内联进产物问题背景env 只进了运行时绑定没进构建产物此前Cloudflare.Website.Vite(Site, { env: { ... } })中的env只会被当作运行时 Worker bindings 转发给 Cloudflare值从未进入客户端client或 SSR bundle。于是 SPA 里读取import.meta.env.VITE_API_URL的代码会回退到代码中硬编码的默认值导致后端动态 URL 在构建期就断链。修复方案构建步骤走 Vite 的define钩子构建流程现在会把props.env传给 Vite 的define钩子模拟vite build的原生 env 语义。官方示例const web yield* Cloudflare.Website.Vite(Web, { env: { VITE_API_URL: worker.url.asstring() }, }); // SPA 中import.meta.env.VITE_API_URL 现在包含部署后的 Worker URL规则与 Vite 本身保持一致只有VITE_前缀的键会被内联进 bundle成为import.meta.env.key与 Vite 默认envPrefix一致非VITE_前缀的条目不会进入 bundle但仍会作为运行时绑定挂到部署后的 Worker 上Redacted值在键为VITE_前缀时会被解包——用VITE_命名本身就是显式选择将其公开进产物。源码级原理getDefine 与 resolveViteEnv在 Sources/Vite.ts 中getDefine的实现精确体现了上述规则// Emulate vite build env semantics for props.env: only // keys with Vites default VITE_ prefix are inlined into // the bundle as import.meta.env.*. Redacted values are // unwrapped — by prefixing with VITE_ the user is opting // them into the public bundle. const getDefine (env: Recordstring, unknown) Object.fromEntries( Object.entries(env).flatMap(([key, raw]) { if (!key.startsWith(VITE_)) return []; const value Redacted.isRedacted(raw) ? Redacted.value(raw) : raw; return [[import.meta.env.${key}, JSON.stringify(value)] as const]; }), );与之配套的resolveViteEnv同文件 L273-L306负责把env解析成 Viteimport.meta.env字面量可计算的最终值从中可以看到几类值的处理差异普通字符串原样透传Redactedstring被解包绑定到环境的 Effect 会被求值带~alchemy/Kind标记的WorkerLoader属于绑定而非可内联的 env 条目会被跳过避免在构建期被误执行。实战模式构建期注入 Worker URL官方教程 vite-spa.mdx 新增了 Inject the Worker URL at build time 一节覆盖该模式的完整链路。纯 SPA 没有服务端在每次请求时解析后端地址因此必须在构建期把后端 URL 烤进 JS bundle// alchemy.run.ts const worker yield* Worker; const web yield* Cloudflare.Website.Vite(Website, { env: { VITE_API_URL: worker.url.asstring(), }, });SPA 侧读取// src/main.tsx const apiUrl import.meta.env.VITE_API_URL; await fetch(${apiUrl}/api/hello);需要注入站点自身 URL用于 canonical 链接、OG 标签或 OAuth 回调 URI时可用Cloudflare.Worker.URL——站点不能引用自己的urlOutputAlchemy 会在构建前解析并同样内联const web yield* Cloudflare.Website.Vite(Website, { env: { VITE_API_URL: worker.url.asstring(), VITE_PUBLIC_URL: Cloudflare.Worker.URL, }, });注意Output值如worker.url.asstring()会在部署时、构建运行之前解析完成。Cloudflare Worker HTTP 适配器接入 Effect 标准生命周期问题背景手写桥接与标准生命周期分叉此前 Worker HTTP 适配器手写了HttpServerRequest/HttpServerResponse的桥接逻辑。对简单 handler 没问题但它与 EffectHttpEffect.toHandled/toWebHandler的生命周期存在分叉导致 scoped HTTP 应用在 workerd 下运行异常——最典型的症状是RpcServer.toHttpEffect通过 Alchemy 部署后会挂起而同样的应用用原生 Wrangler 跑却是正常的。修复方案保留 Worker 特性 补齐标准生命周期适配器现在让 handler 走 Effect 的标准 HTTP 生命周期同时保留每一项 Worker 专属行为cf-connecting-ip请求头 →remoteAddress原始的 CloudflareRequest服务打过补丁的request.raw访问来自serveWebRequest的既有 500 响应映射。并补上了此前缺失的部分stream-scope 转移、HEAD 请求响应体抑制、请求中止abort时的中断处理。源码级原理makeRequestEffect 与 toHandledWebResponse在 HttpServer.ts 中可以看到桥接层的核心实现const request HttpServerRequest.fromWeb( webRequest as any as globalThis.Request, ).modify({ remoteAddress: Option.fromUndefinedOr( webRequest.headers.get(cf-connecting-ip) ?? undefined, ), }); Object.defineProperty(request, raw, { get: () Object.assign(request.stream, { raw: webRequest.body, }), });响应侧toHandledWebResponse通过EffectHttp.toHandled走 Effect 的标准生命周期并在回调中完成 Web Response 转换yield* EffectHttp.toHandled(handler, (request, response) Deferred.succeed( webResponse, // 转换逻辑与 EffectHttp.toWebHandler 的回调保持一致 HttpServerResponse.toWeb(EffectHttp.scopeTransferToStream(response), { withoutBody: request.method HEAD, context, }), ), );这里可以清楚地看到三个关键修复点的落点scopeTransferToStream完成 stream-scope 转移、withoutBody: request.method HEAD抑制 HEAD 响应体、toHandled本身接管了请求中止时对 Effect 执行的中断。净效果标准生命周期应用全面解锁最终效果正如发布说明所写任何能在effect/platform标准 HTTP 生命周期下运行的应用现在都能在Cloudflare.Worker下运行。特别是RpcServer.toHttpEffect被彻底解锁——Effect RPC 服务端现在可以放心通过 Alchemy 部署到 Cloudflare Workers。该修复由 Will KingPR #328贡献同时修复了 issue #327。SendEmail绑定类型推断与部署元数据补全问题背景两处 wiring 遗漏beta.38 引入了Cloudflare.Email.SendEmail但Worker.ts中有两处接线点被遗漏绑定类型推断不认识SendEmail——在 Worker 上写bindings: { EMAIL: Email }会直接报类型错误部署时的绑定元数据没有生成send_email条目——部署会静默丢弃该绑定。修复方案接入绑定联合与元数据发射两处现已全部接通SendEmail成为 Worker 绑定联合binding union的一等成员env key 携带正确的运行时类型部署时 Cloudflare 会收到预期的send_email绑定元数据。源码级证据send_email 元数据的完整字段在 WorkerAsyncBindings.ts 中可以看到send_email绑定元数据的发射逻辑} else if (isSendEmail(binding)) { return { type: send_email, name: bindingName, destinationAddress: binding.destinationAddress, allowedDestinationAddresses: binding.allowedDestinationAddresses, allowedSenderAddresses: binding.allowedSenderAddresses, }; }也就是说部署到 Cloudflare 的绑定配置至少包含目标地址destinationAddress、允许的目标地址列表与允许的发件人地址列表这几项约束。绑定声明与运行时使用SendEmail绑定本身的声明定义在 SendEmail.ts它是 Worker-only 绑定不创建任何云端资源支持配置destinationAddress、allowedDestinationAddresses、allowedSenderAddresses等属性。示例声明const Email Cloudflare.Email.SendEmail(Email, { destinationAddress: opsexample.com, });通过 Send.ts 中的Cloudflare.Email.Send服务可以在运行时发送邮件其底层实现在 SendBinding.ts 中按绑定名从env取出运行时SendEmail绑定并执行发送发送失败时返回SendEmailError。该修复由 Gerben MulderPR #326发现并贡献。版本升级建议v2.0.0-beta.39面向以下三类使用场景属于应当立即升级的修复版SPA / SSR 站点通过env注入VITE_*变量升级前变量不会进入产物升级后与vite build语义完全一致在 Cloudflare Worker 上运行 Effect RPC 或 scoped HTTP 应用升级前RpcServer.toHttpEffect可能挂起升级后等价于effect/platform标准生命周期使用Cloudflare.Email.SendEmail绑定升级前类型报错且部署静默丢绑定升级后类型与部署元数据均已接通。升级后建议做一次完整的部署验证先确认import.meta.env.VITE_API_URL在产物中已展开为实际 Worker URL再跑一遍 RPC 端到端调用确认无挂起最后检查 Cloudflare 控制台中的 Worker 绑定配置确实包含send_email条目。【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考