Wasp 框架 PaaS 部署完全指南:Fly.io、Railway、Heroku、Netlify 与 Cloudflare 实战
【免费下载链接】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 构建产物是平台无关的(可部署代码 + Docker 镜像 + 静态文件),因此你可以把生成的 Wasp 应用部署到任何支持 Node.js 服务、静态文件托管与 PostgreSQL 数据库的 PaaS 平台。本文以 web/versioned_docs/version-0.18/deployment/deployment-methods/paas.md 为核心,完整讲解通用四步部署流程,并逐步演示在 Fly.io(服务端 + 数据库)、Railway(全栈)、Heroku(服务端 + 数据库)、Netlify 与 Cloudflare Pages(客户端静态托管)上的部署步骤、环境变量配置与 CI 自动化方案。读完本文,你将掌握 Wasp 应用生产部署的完整链路,并能根据需求选择最合适的 PaaS 组合。
通用部署四步走
无论选择哪家 PaaS 提供商,部署一个 Wasp 应用本质上都归结为四件事:
- 生成可部署代码(
wasp build)。 - 部署 API 服务端(后端)。
- 部署 Web 客户端(前端)。
- 部署并持续运行一个 PostgreSQL 数据库。
1. 生成可部署代码
在 Wasp 项目根目录运行:
wasp build该命令会把整个应用的可部署代码生成到.wasp/build/目录(在 version-0.18 这个版本中输出目录为.wasp/build/;较新版本已改为.wasp/out/)。构建产物包含三部分:
- 服务端:一个用于构建服务端镜像的 Dockerfile,位于
.wasp/build/根目录; - 客户端:构建后的静态文件,位于
.wasp/build/web-app/build/; - 数据库:对应的 Prisma schema 与迁移文件,随服务端 Docker 镜像一同打包。
# 确认构建产物结构 ls .wasp/build # Dockerfile server/ web-app/ db/ ...⚠️ 生产环境必须使用 PostgreSQL如果应用使用的是默认的 SQLite 数据库,
wasp build将无法成功构建。在部署到生产环境前,必须先从 SQLite 迁移到 PostgreSQL。
从源码看,服务端 Dockerfile 采用多阶段构建(base → server-builder → server-production),模板位于 waspc/data/Generator/templates/Dockerfile:在server-builder阶段安装依赖并执行npx prisma generate,在server-production阶段只拷贝构建产物(bundle、node_modules、db/),并以npm run start-production作为容器入口;EXPOSE ${PORT}表明容器对外暴露的端口由PORT环境变量控制,这与下文各平台设置PORT=8080的做法直接对应。
2. 部署 API 服务端
.wasp/build目录中有一个定义服务端镜像的 Dockerfile。要运行生产环境服务端,需要把这个 Docker 镜像部署到托管平台,并正确配置所需的环境变量。通常使用平台的控制台 UI 或 CLI 工具来设置这些环境变量。
必须先核对服务端必需的环境变量并确保全部配置到位。下面各平台章节会给出对应的设置命令。
3. 部署 Web 客户端
构建 Web 客户端的方式是先进入.wasp/build/web-app目录,再执行:
cd .wasp/build/web-app npm install && REACT_APP_API_URL=<url_to_wasp_backend> npm run build其中<url_to_wasp_backend>是之前已部署的 Wasp 服务端地址。
- 构建产物是纯静态文件,位于
.wasp/build/web-app/build/,可以部署到任意静态托管平台(如 Netlify、Cloudflare Pages)。 - 客户端环境变量通过构建命令注入:如果在项目中定义了其他客户端环境变量,必须一并加在上述构建命令中。Wasp 会在构建期间把
import.meta.env.REACT_APP_*替换为实际值,因此永远不要把密钥类信息放进客户端环境变量——它们会随静态文件公开可见。 - 不要指望在托管平台给静态文件"注入"客户端环境变量:静态文件构建后是死的,宿主环境变量对它们无效(服务端环境变量则相反,应在宿主上设置)。
4. 部署数据库
任何 PostgreSQL 数据库都可以,只要满足两个条件:
- 向服务端提供正确的
DATABASE_URL环境变量; - 确保数据库能被服务端访问。
各平台数据库方案汇总:
| 平台 | 是否托管数据库 | 说明 |
|---|---|---|
| Fly.io | ✅ 是 | fly launch时选择 PostgreSQL,自动设置DATABASE_URL |
| Railway | ✅ 是 | 新建项目时选择 "Deploy PostgreSQL" |
| Heroku | ✅ 是 | heroku addons:create heroku-postgresql:essential-0,自动设置DATABASE_URL |
| Netlify | ❌ 否 | 仅托管客户端静态文件 |
| Cloudflare | ❌ 否 | 仅托管客户端静态文件 |
推荐的 CLI 一键部署方式:wasp deploy
在各平台章节开始前,先说明一点:Wasp 提供了更省事的 CLI 自动化部署命令wasp deploy,它把手动部署流程自动化,是官方推荐方式。基本用法为:
wasp deploy <provider> launch my-wasp-appwasp deploy会在提供商侧创建全部所需服务、构建 Wasp 应用并完成部署。例如部署到 Fly.io:
wasp deploy fly launch my-wasp-app mia该命令会基于应用名my-wasp-app创建三个独立应用(my-wasp-app-client、my-wasp-app-server、my-wasp-app-db),并在项目根目录生成fly-server.toml与fly-client.toml两个配置文件(应纳入版本控制,方便以后一条命令重新部署)。其他服务端密钥可用wasp deploy fly cmd secrets set --context=server ...追加。
如果你的提供商/平台恰好支持 CLI 自动化(Fly.io、Railway 均支持),优先使用它;下面的手动步骤用于理解底层机制,或在你需要完全掌控部署细节时使用。
部署到 Fly.io(服务端 + 数据库)
Fly.io 提供容器化应用托管,本节演示如何把服务端部署上去并为其配置数据库。
前提条件
- 注册 Fly.io 账号;
- 安装
flyCLI; - 用
flyCLI 登录。
检查是否已登录:
fly auth whoami未登录则执行:
fly auth login创建 Fly.io 应用
每个 Wasp 应用只需执行一次。
如果还没有想复用的 Fly.io 应用,先构建应用,然后进入.wasp/build/目录:
cd .wasp/build运行 launch 命令来创建新应用并生成fly.toml文件:
fly launch --remote-only命令会交互式询问一系列问题(选择区域、是否需要数据库等):
- 对Would you like to set up a PostgreSQL database now?回答yes,并选择Development。Fly.io 会自动为你设置
DATABASE_URL; - 对Would you like to deploy now?(以及其余附加问题)回答no——因为还需要设置多个环境变量。
如果数据库/应用创建失败怎么办?先执行
fly apps destroy <app-name>再重试。Fly 不允许创建同名应用。
把生成的fly.toml复制到 Wasp 项目根目录保存(避免被下次wasp build清掉):
cp fly.toml ../../仓库中的 examples/waspello/fly-server.toml 展示了此类配置的典型形态:internal_port = 8080、force_https = true、单实例shared1 CPU / 1GB 内存,与下文PORT=8080的设置一一对应。
设置服务端环境变量
接下来为服务端代码添加几个必需的环境变量:
fly secrets set PORT=8080 fly secrets set JWT_SECRET=<random_string_at_least_32_characters_long> fly secrets set WASP_WEB_CLIENT_URL=<url_of_where_client_will_be_deployed> fly secrets set WASP_SERVER_URL=<url_of_where_server_will_be_deployed>PORT=8080:必须与fly.toml中http_service.internal_port一致;JWT_SECRET:至少 32 字符的随机字符串,用于签发/校验会话 JWT,泄露它意味着任何人都能伪造会话;WASP_WEB_CLIENT_URL:客户端部署后的地址(决定 CORS 与回调地址);WASP_SERVER_URL:服务端自己的公开地址。
还不知道客户端地址?不必担心,可以先部署客户端,之后再执行
fly secrets set WASP_WEB_CLIENT_URL=<url_of_deployed_client>补上。
如果应用使用了 Wasp 支持的外部认证方式(如 Google、GitHub OAuth),还需要额外设置这些认证方式要求的环境变量。
核对密钥是否设置成功:
fly secrets list注意:出于安全考虑,列表中显示的是密钥的哈希版本。
部署到 Fly.io
仍在.wasp/build/目录下执行:
fly deploy --remote-only --config ../../fly.toml这会构建并把 Wasp 应用的后端部署到 Fly.io,服务地址为https://<app-name>.fly.dev。
之后(如果还没做),部署客户端并补上客户端地址:fly secrets set WASP_WEB_CLIENT_URL=<url_of_deployed_client>。客户端建议使用 Netlify(见下文),也可以用任意静态托管平台。
几个有用的fly命令:
fly logs fly secrets list fly ssh console重新部署(wasp build 之后)
每次执行wasp build都会清空.wasp/build/目录,之前放在里面的fly.toml会丢失。目前有三种应对方式:
- 把
fly.toml放到版本控制目录(如 Wasp 项目根目录),然后在fly deploy --config <path>中引用它(即上面示例的做法); - 备份
fly.toml到别处,wasp build后再复制回.wasp/build/——当fly.toml存在于.wasp/build/时,无需指定--config <path>; - 用
fly config save -a <app-name>从 Fly.io 远程状态重新生成fly.toml。
部署到 Railway(服务端 + 客户端 + 数据库)
Railway 可以在一个项目里同时承载客户端、服务端与 PostgreSQL 数据库,是"全栈单平台"的典型选择。
前提条件
- 在项目目录运行
wasp build完成构建; - 注册 Railway 账号;
- 安装 Railway CLI;
- 运行
railway login,浏览器会打开进行身份认证。
创建项目
- 打开 Railway dashboard,点击New Project,从下拉菜单中选择Deploy PostgreSQL;
- 项目创建后,点击右上角Create按钮,选择Empty Service;
- 点击新服务,把名字改为
server; - 再创建一个空服务,命名为
client; - 点击顶部的Deploy按钮部署这些变更。
部署应用到 Railway
配置域名
服务端和客户端服务都需要域名:
- 进入
server实例的Settings标签页,点击Generate Domain; - 端口填
8080,点击Generate Domain; - 对
client服务重复同样操作; - 复制两个域名,后面会用到。
部署服务端
进入
.wasp/build目录:cd .wasp/build把该目录链接到新建的 Railway 项目:
railway link提示选择服务时选择
server。在 Railway 控制台配置环境变量:进入
server服务的Variables标签页:- 点击Variable reference并选择
DATABASE_URL(会自动填入正确值); - 添加
WASP_WEB_CLIENT_URL,值为client域名(例如https://client-production-XXXX.up.railway.app),必须带https://前缀; - 添加
WASP_SERVER_URL,值为server域名(例如https://server-production-XXXX.up.railway.app),必须带https://前缀; - 添加
JWT_SECRET,值为至少 32 字符的随机字符串。
同样地,使用外部认证时记得追加对应的认证环境变量。
- 点击Variable reference并选择
推送并部署项目:
railway up --ci使用
--ci标志可把日志输出限制为只显示构建过程。Railway 会自动定位.wasp/build中的 Dockerfile 并部署服务端。
部署客户端
进入前端构建目录
.wasp/build/web-app:cd web-app用
server域名作为REACT_APP_API_URL构建生产版本:npm install && REACT_APP_API_URL=<url_to_wasp_backend> npm run build把客户端构建目录链接到
client服务:cd build railway link部署客户端构建产物到 Railway:
railway up --ci提示选择服务时选择
client。Railway 会检测到index.html,把客户端作为静态站点部署。
回到 Railway dashboard,点击项目即可看到三个已部署的服务:PostgreSQL、Server、Client。
更新与重新部署
每次更新代码后的重新部署流程:
运行
wasp build重新构建;进入
.wasp/build目录,部署服务端:railway up --ci进入
.wasp/build/web-app目录,重新构建并部署客户端:npm install && REACT_APP_API_URL=<url_to_wasp_backend> npm run build cd build railway up --ci
部署到 Heroku(服务端 + 数据库)
Heroku 适合托管服务端与 PostgreSQL 数据库;客户端仍需部署到静态托管平台。
前提条件
需要 Heroku 账号、herokuCLI 和dockerCLI。确认已登录:
heroku whoami未登录则:
heroku login创建 Heroku 应用
每个 Wasp 应用只需执行一次。
创建新应用(除非想部署到已有应用):
heroku create <app-name>创建并挂载数据库(除非已有外部 PostgreSQL 数据库):
heroku addons:create --app <app-name> heroku-postgresql:essential-0注意:
essential-0是 Heroku 最便宜的数据库实例,约 $5/月。
- Heroku 会自动设置
DATABASE_URL环境变量;如果使用外部数据库,需要自己配置。 PORT环境变量也由 Heroku 提供,因此只需再设置三个变量:
heroku config:set --app <app-name> JWT_SECRET=<random_string_at_least_32_characters_long> heroku config:set --app <app-name> WASP_WEB_CLIENT_URL=<url_of_where_client_will_be_deployed> heroku config:set --app <app-name> WASP_SERVER_URL=<url_of_where_server_will_be_deployed>暂时不知道客户端地址也没关系,部署完客户端后再补
WASP_WEB_CLIENT_URL即可。
部署 Heroku 应用
构建应用后,进入.wasp/build/目录:
cd .wasp/build登录 Heroku 容器仓库:
heroku container:login把应用的 stack 设置为container,以便以 Docker 容器方式部署:
heroku stack:set container --app <app-name>构建 Docker 镜像并推送到 Heroku:
heroku container:push --app <app-name> web此时应用尚未部署(首次推送因无缓存层会耗时较长)。发布镜像并重启应用:
heroku container:release --app <app-name> web后端即部署完成,地址形如https://<app-name>-XXXX.herokuapp.com。查询确切地址:
heroku info --app <app-name>查看日志:
heroku logs --tail --app <app-name>💡 使用
pg-boss执行器时的特殊配置:如果应用使用了以pg-boss为执行器的 Jobs(后台任务),部署到 Heroku 时需要额外设置环境变量PG_BOSS_NEW_OPTIONS为{"connectionString":"<REGULAR_HEROKU_DATABASE_URL>","ssl":{"rejectUnauthorized":false}}。原因:pg-boss 依赖的pg扩展默认不走 SSL 连接,而 Heroku 要求 SSL 且使用自签名证书。可参阅Jobs 文档了解更多。
部署到 Netlify(客户端)
Netlify 是静态托管方案,很多场景免费。需要 Netlify 账号与 Netlify CLI。检查登录状态:
npx netlify-cli status未登录则:
npx netlify-cli login先构建 Wasp 应用,然后构建客户端 Web 应用(命令见上文"部署 Web 客户端"一节)。
部署客户端:
npx netlify-cli deploy仔细跟随交互提示:决定是新建应用还是复用已有应用、选择部署到哪个 team 等。
最后正式发布:
npx netlify-cli deploy --prod客户端将上线于https://<app-name>.netlify.app。
注意:务必把
https://<app-name>.netlify.app设置为服务端托管环境中的WASP_WEB_CLIENT_URL环境变量。
⚠️ URL 重定向到
index.html:按上述方式操作时,Netlify CLI 会使用 Wasp 默认在.wasp/build/web-app/中生成的netlify.toml,正确地把 URL 重定向到index.html——这对 Wasp 至关重要,因为 Wasp 客户端是单页应用(SPA),需要客户端路由接管页面跳转。如果改用其他方式(如 CI)部署,务必让 Netlify 读取到该netlify.toml,或手动配置 URL 重定向。
通过 GitHub Actions 自动化部署
创建.github/workflows/deploy.yaml文件(文件名可改,但类型不能变),实现每次 push 到main分支时自动部署客户端:
name: Deploy Client to Netlify on: push: branches: - main # Deploy on every push to the main branch jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v2 - name: Setup Node.js id: setup-node uses: actions/setup-node@v4 with: node-version: '22' - name: Install Wasp run: curl -sSL https://get.wasp.sh/installer.sh | sh -s -- -v 0.16.0 # Change to your Wasp version - name: Wasp Build run: wasp build - name: Install dependencies and build the client run: | cd ./.wasp/build/web-app npm install REACT_APP_API_URL=${{ secrets.WASP_SERVER_URL }} npm run build - name: Deploy to Netlify run: | cd ./.wasp/build/web-app npx netlify-cli@17.36.1 deploy --prod --dir=build --auth=$NETLIFY_AUTH_TOKEN --site=$NETLIFY_SITE_NAME env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_NAME: netlify-site-name环境变量从哪来?
NETLIFY_AUTH_TOKEN:在 Netlify 后台生成 Personal Access Token;NETLIFY_SITE_NAME:Netlify 项目的名称;WASP_SERVER_URL:服务端地址,一般只有在后端部署完成后才可用;后端未就绪时可以跳过,但要意识到依赖后端的功能会不可用。
拿到这三个值后,把它们配置到 GitHub Repository Secrets 中。
部署到 Cloudflare Pages(客户端)
Cloudflare 提供免费静态托管服务 Cloudflare Pages。需要 Cloudflare 账号与 Wrangler CLI。登录:
npx wrangler login先构建 Wasp 应用,再构建客户端 Web 应用。进入.wasp/build/web-app目录后执行:
npx wrangler pages deploy ./build --commit-dirty=true --branch=main跟随交互提示(新建应用还是复用已有应用)。客户端将上线于https://<app-name>.pages.dev。
注意:务必把
https://<app-name>.pages.dev设置为服务端托管环境中的WASP_WEB_CLIENT_URL环境变量。
SPA 路由:Cloudflare 会自动把所有路径重定向到
index.html。这对 Wasp 客户端(SPA)至关重要,客户端路由需要在浏览器端接管页面切换。
通过 GitHub Actions 自动化部署
创建.github/workflows/deploy.yaml,实现 push 到main分支时自动部署到 Cloudflare Pages:
name: Deploy Client to Cloudflare on: push: branches: - main # Deploy on every push to the main branch jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v2 - name: Setup Node.js id: setup-node uses: actions/setup-node@v4 with: node-version: '22' - name: Install Wasp run: curl -sSL https://get.wasp.sh/installer.sh | sh -s -- -v 0.16.0 # Change to your Wasp version - name: Wasp Build run: cd ./app && wasp build - name: Install dependencies and build the client run: | cd ./app/.wasp/build/web-app npm install REACT_APP_API_URL=${{ secrets.WASP_SERVER_URL }} npm run build - name: Deploy to Cloudflare Pages uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy ./app/.wasp/build/web-app/build --project-name=${{ env.CLIENT_CLOUDFLARE_APP_NAME }} --commit-dirty=true --branch=main env: CLIENT_CLOUDFLARE_APP_NAME: cloudflare-pages-app-name环境变量从哪来?
CLOUDFLARE_API_TOKEN与CLOUDFLARE_ACCOUNT_ID:从 Cloudflare 控制台获取;令牌需要Cloudflare Pages: Read和Cloudflare Pages: Edit权限;CLIENT_CLOUDFLARE_APP_NAME:Cloudflare Pages 应用名,可通过npx wrangler pages project create <app-name>创建;WASP_SERVER_URL:服务端地址,一般在后端部署完成后才有;可跳过,但依赖后端的功能会不可用。
同样把这些值配置到 GitHub Repository Secrets 中。
各平台选型速览与通用注意事项
| 平台 | 托管能力 | 关键 CLI/命令 | 必设服务端环境变量 |
|---|---|---|---|
| Fly.io | 服务端 + 数据库 | fly launch --remote-only、fly deploy --remote-only、fly secrets set | PORT、JWT_SECRET、WASP_WEB_CLIENT_URL、WASP_SERVER_URL |
| Railway | 服务端 + 客户端 + 数据库 | railway link、railway up --ci | DATABASE_URL(引用)、JWT_SECRET、WASP_WEB_CLIENT_URL、WASP_SERVER_URL |
| Heroku | 服务端 + 数据库 | heroku container:push、heroku container:release | JWT_SECRET、WASP_WEB_CLIENT_URL、WASP_SERVER_URL(DATABASE_URL、PORT自动设置) |
| Netlify | 客户端(静态) | npx netlify-cli deploy --prod | 只需在服务端设置WASP_WEB_CLIENT_URL指向 Netlify 域名 |
| Cloudflare Pages | 客户端(静态) | npx wrangler pages deploy ./build | 只需在服务端设置WASP_WEB_CLIENT_URL指向 Pages 域名 |
通用注意事项总结:
- 服务端环境变量:生产环境会忽略
.env.server,必须通过托管平台的机制(fly secrets set、Railway Variables 面板、heroku config:set等)设置。必设项包括DATABASE_URL、WASP_WEB_CLIENT_URL、WASP_SERVER_URL、JWT_SECRET,外部认证(OAuth)等场景还需追加对应变量。 - 客户端环境变量:生产环境会忽略
.env.client,必须在构建客户端时以命令行前缀注入(REACT_APP_*),并且每次重新部署都要重新提供。切勿在其中存放密钥。 - SPA 路由:客户端是单页应用,静态托管方必须把所有路径重定向到
index.html(Netlify 用 Wasp 生成的netlify.toml,Cloudflare Pages 自动处理)。 - 构建产物的可丢弃性:
wasp build会清空.wasp/build/,所以需要长期保留的配置(如fly.toml)要存到版本控制目录或另行备份。 - 数据库连接:任何 PostgreSQL 均可用,前提是
DATABASE_URL正确且数据库可从服务端访问;涉及 SSL(如 Heroku + pg-boss)时按平台要求处理连接配置。
如果上述列表中找不到你心仪的 PaaS 提供商,也不要紧——只要它支持 Wasp 的构建格式(Node.js 服务、静态文件、PostgreSQL),你就可以按"通用部署四步走"完成部署。
【免费下载链接】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),仅供参考