使用 Serverless Framework 将 Redwood 应用部署到 AWS
【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwood
本指南基于 Redwood 官方部署文档整理,配套源码实现可参考仓库中的 CLI setup 命令 与 CLI deploy 命令。本文假设你已经阅读过 General Deployment Setup 章节,理解了部署前需要在
redwood.toml中配置apiUrl、准备构建命令、配置 Prisma 数据库与生产环境变量这四类前置工作。
Serverless Framework 提供了一个非常有趣的选项——直接部署到你自己的云服务商账号中,完全跳过中间商!默认情况下,Serverless 只负责编排云服务商(本文即 AWS)上的服务启动,并把你的代码推送上去。你收到的任何账单都来自你的托管服务商(不过许多服务商都提供了慷慨的免费额度)。你可以选择性地使用 Serverless Dashboard 来监控部署,并搭建 CI/CD 在推送到代码仓库时自动部署;如果不配置 CI/CD,你就直接从自己的开发机器(或另外指定的部署机器)发起部署。
阅读完本指南,你将掌握:一条命令完成 Serverless 部署配置、首次部署(--first-run)时 API 与 Web 两侧的编排流程、serverless.yml的读写方法、环境变量的分层管理、多 stage 部署与最终资源拆除的完整实战方案。
前置条件
当前 Redwood 默认只支持部署到 AWS。未来希望能支持更多服务商,但需要社区帮忙确认哪些服务与我们在 AWS 中使用的服务等价——API 侧对应 AWS Lambda,Web 侧对应 S3/CloudFront。
大部分部署命令 Redwood 都会替你处理,你只需要在开始之前准备好:
- 一个 AWS 账号;
- 一对 Access/Secret keys(访问/密钥对)。
Setup:一条命令完成配置
执行下面的命令,Redwood 会为你配置好(几乎)所有东西:
yarn rw setup deploy serverless从源码看,这条命令背后会依次执行一组任务(见 providers/serverless.js):
- 在项目根目录、
web与api侧分别安装开发依赖:serverless、serverless-lift、@vercel/nft、archiver、fs-extra; - 生成两份 Serverless 配置文件:
api/serverless.yml与web/serverless.yml; - 更新
redwood.toml,将apiUrl改为"${API_URL:/api}",即生产环境优先取API_URL环境变量,缺省回退到/api; - 把
.serverless目录加入.gitignore; - 在
.env中追加 AWS 凭证占位行; - 为 Prisma 增加
rhel-openssl-1.0.x二进制目标(AWS Lambda 运行时需要)。
正如安装完成后的提示所说,你需要把自己的 AWS Access Key 与 Secret Access Key 填入.env文件对应位置:
# .env AWS_ACCESS_KEY_ID=<your-key-here> AWS_SECRET_ACCESS_KEY=<your-secret-key-here>务必不要把.env提交进代码仓库!它默认已被写入.gitignore,请保持这种状态。
生成的 serverless.yml 长什么样
api/serverless.yml与web/serverless.yml由模板生成,源码见 templates/serverless/api.js 与 templates/serverless/web.js。
API 侧的模板要点(api/serverless.yml):
service: <你的项目名>-api useDotenv: true provider: name: aws runtime: nodejs18.x region: us-east-1 # AWS 区域,默认美国弗吉尼亚北部 httpApi: # 默认使用 API Gateway 的 HTTP API cors: allowedOrigins: - '*' # 默认放开所有来源;若使用 allowCredentials 则不能为 '*' allowedHeaders: - authorization - auth-provider - content-type # ... 其余 AWS 签名相关请求头 payload: '1.0' environment: # 在这里声明环境变量: # VARIABLE_NAME: ${env:VARIABLE_NAME} 从本地环境取 # VARIABLE_NAME: ${param:VARIABLE_NAME} 从 Serverless Dashboard 取 functions: auth: description: auth function deployed on AWS Lambda package: artifact: dist/zipball/auth.zip memorySize: 1024 # 单位 MB timeout: 25 # 单位秒(最大 900 秒 / 15 分钟) handler: auth.handler events: - httpApi: path: /auth method: GET - httpApi: path: /auth method: POST graphql: # 结构同上,路径为 /graphqlWeb 侧模板的要点(web/serverless.yml):
service: <你的项目名>-web useDotenv: true plugins: - serverless-lift constructs: web: type: static-website path: dist provider: name: aws runtime: nodejs18.x region: us-east-1Web 侧通过serverless-lift插件的static-websiteconstruct 把构建产物web/dist托管为静态网站(S3 + CloudFront)。
First Deploy:首次部署
首次部署需要给部署命令加一个特殊 flag:
yarn rw deploy serverless --first-run首次部署时,Redwood 会先只部署 API 侧。等 API 上线后,取到它被部署到的 URL,并将其作为环境变量API_URL写入,这样 Web 侧在构建时才能知道该把 GraphQL 与函数请求发往哪里(redwood.toml中的apiUrl = "${API_URL:/api}"就是为此准备的)。
从 deploy/serverless.js 的实现看,--first-run的完整流程是:
- 先部署
api侧(web侧会被跳过,源码中的 skip 逻辑注明 "Skipping web deploy, until environment configured"); - 运行
yarn serverless info --verbose --stage=production并从输出中正则提取HttpApiUrl: https://...得到 API 地址; - 弹出交互式确认,询问是否把
API_URL写入.env.production(它类似.env,但只在NODE_ENV=production时使用,例如构建 Web 与 API 侧进行部署时)。请务必在这个提示处回答Y,之后才会继续部署 Web 侧; - 携带新的
API_URL重新构建并部署 Web 侧; - 再次运行
yarn serverless info,提取url: https://...并打印成功信息框,包含你的站点地址。
命令执行完成后,你应该会看到一条包含站点 URL 的消息——打开该 URL,希望一切正常!
注意
如果从 API 侧加载数据时报错,很可能是因为你的应用仍然指向本地数据库。
记得在生成的
.env.production中添加DATABASE_URL环境变量,指向部署环境要用的数据库。既然你的技术栈在 AWS 上,RDS 是个不错的选择;不过你也可以在 Railway,按需带上连接池端口、sslmode或pgbouncer参数。
Subsequent Deploys:后续部署
从第二次开始,随时可以简单地执行:
yarn rw deploy serverless这条命令会快很多,因为它不再需要 API_URL 的首次编排流程。
注意
如果你新增或生成了新的 serverless 函数(或端点),需要同步更新
./api/serverless.yml中的配置。默认情况下,Redwood 只为
auth和graphql两个函数生成配置。
deploy 命令的完整参数
从源码的 builder 定义 看,yarn rw deploy serverless支持以下参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
--stage | production | Serverless stage 透传参数,对应部署目的地(环境) |
--sides/--side | ['api', 'web'] | 指定要部署的侧(side),可选api、web |
--verbose | true | 日志详细程度 |
--pack-only | false | 只构建并打包,不调用 serverless 推送代码 |
--first-run | false | 首次部署时设置,用于在 Web 侧配置 API URL |
整个部署流程(buildCommands 与 deployCommands)为:先执行yarn rw build api web构建,再用@vercel/nft对每个函数做依赖追踪并打成 zip(详见 packing/nft.js),最后在api与web目录下分别执行yarn serverless deploy --stage <stage>。
Environment Variables:环境变量
对于本地部署(即从你自己的机器或你掌控的其他机器部署),可以把仅用于生产的环境变量放进.env.production,它会覆盖.env中同名变量。这两个文件都不能提交进代码仓库!
如果你使用 Serverless Dashboard 搭建 CI/CD 并从中部署,就需要把所需的环境变量复制到 Serverless 上的应用中,然后告诉它从哪里读取。在api/serverless.yml与web/serverless.yml中找到provider > environment段落,用${param:VAR_NAME}语法列出需要的变量——该语法表示从 Serverless Dashboard 的 "parameters"(他们就是这么称呼环境变量的)中读取。
环境变量的来源还有很多种,可以参考 Serverless 官方的 Variables 文档。
另外值得注意:deploy 命令在启动时会根据--stage加载对应的.env.<stage>文件(见 loadDotEnvForStage),这也是为什么--stage qa时会读取.env.qa、--stage production时会读取.env.production。
Serverless Dashboard
注意:
Serverless Dashboard 的 CI/CD 目前不支持像 Redwood 这样结构的项目(官方正在努力改进)。CD 部分你需要使用类似 GitHub Actions 的方案。
不过将项目接入 Serverless Dashboard 仍然有价值——你可以获得部署日志与监控、分析、密钥管理以及 AWS 账号集成等功能。你也可以在 CI 上下文中认证到你的 Serverless 账号。请记住:如果通过 Dashboard 管理密钥,就需要使用
${param:VAR_NAME}语法。
把站点接入 Serverless Dashboard 有两种方式:
- 运行
yarn serverless login,浏览器应该会打开一个授权确认页面。但根据实际经验,这个命令大约有 50% 的失败概率,会报无效 URL 的错误。如果它确实成功了,你可以在api和web目录下分别运行yarn serverless把它们链接到 Dashboard 中已有的应用,或者按提示创建新应用。之后的部署都会在 Dashboard 上被监控。 - 手动在
api/serverless.yml与web/serverless.yml中填写org和app两行。在文件顶部附近可以看到注释掉的示例。
Environments Besides Production:非生产环境
默认情况下,Redwood 假设你部署到生产环境,但 Serverless 允许部署到任何地方,它把这些目的地称为 "stage",而 Redwood 中production是默认 stage。详细内容可参考其官方 Managing Staging and Environments 博客。
配置好之后,只需在部署命令中加上 stage:
yarn rw deploy serverless --stage qaRemoving Your Deploy:拆除部署
除了创建应用运行所需的全部服务,Serverless 也能把它们全部移除(这在测试阶段很有用,可以避免为不再使用的服务持续付费)。
你需要在api和web两个目录下分别执行:
yarn serverless remove --stage production注意:production是使用yarn rw deploy serverless部署时的默认 stage——如果你自定义过 stage,拆除时必须使用与部署时相同的 stage!
拆除过程需要几分钟,所以不妨倒上一杯喜欢的饮料,享受新的 $0 月账单!
Pro tip
如果厌倦了每次敲
serverless,可以用更短的别名sls:yarn rw deploy sls(源码中sls正是serverless命令的 alias,见 deploy/serverless.js)。
Troubleshooting:故障排查
如果在部署时看到如下错误:
Error: No auth.zip file found in the package path you provided.请确保开发服务器(dev server)没有在运行,然后重试部署。原因在于打包函数(见 packing/nft.js)依赖构建产物api/dist/zipball/*.zip,若 dev server 占用或干扰了构建产物,就会导致 zip 包缺失。
【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwood
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考