RedwoodJS 全栈应用部署实战:从 SQLite 到 Postgres 再到 Netlify 的完整上线指南
RedwoodJS 全栈应用部署实战从 SQLite 到 Postgres 再到 Netlify 的完整上线指南【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwood本篇指南以 RedwoodJSRedwood 框架教程第五章部署章节为核心完整讲解如何将一个本地基于 SQLite 的 Redwood 全栈应用迁移至 Postgres 数据库并借助 Netlify 的 Git 集成完成生产环境部署。你将掌握数据库提供方切换、迁移重建、环境变量配置、Netlify 部署设置、自定义域名与分支预览以及 Serverless 场景下数据库连接与安全加固的完整实战方案。为什么部署是 RedwoodJS 的最后一公里RedwoodJS 设计之初就以让全栈 Web 应用在 Jamstack 上更容易构建和部署为目标。教程前几章虽然已经让应用跑了起来但那只是本地开发环境真正让它面向互联网活起来需要解决两个核心问题把数据放到互联网上可达的数据库以及把代码托管给持续集成部署平台。本教程演示的路径是业界最典型的 Redwood 部署组合Git托管代码GitHub / GitLab / BitbucketRailway或其他托管服务提供 Postgres 实例Netlify负责构建与托管 Web 端和 Serverless 函数先把代码推上 Git如果你此前一直跳过 Git 使用教程那么从部署这一步开始必须启用它。最简单的方式是在 GitHub或 GitLab / Bitbucket新建一个仓库平台会给出把本地代码提交并推送所需的完整命令清单。与新建空仓库时只添加 README不同这里要提交整个代码库git add . git commit -m Initial commit git push数据库为什么本地 SQLite 不能直接上生产RedwoodJS 本地开发默认使用 SQLite其文件型数据库依赖持久化磁盘存储。而 Serverless 部署环境如 Netlify 背后的 AWS Lambda没有可写入的文件系统持久层因此必须切换到 Postgres。Prisma 目前支持 SQLite、Postgres、MySQL 和 SQL Server但同一时间只能使用一种数据库 provider——这意味着一旦切换本地开发也必须改用同一数据库否则会出现本地与生产环境行为不一致的问题。:::danger 关键约束Prisma 同一时间仅支持一个数据库 provider。既然生产环境无法使用 SQLite、必须改用 Postgres 或 MySQL那么本地开发环境在切换后也必须使用相同数据库。请参阅 本地 Postgres 环境搭建指南 完成本地环境准备。:::从 本地 Postgres 环境搭建指南 可以看到完整的本地切换路径通过brew install postgresql14Mac等方式安装 Postgres用createdb创建数据库然后在.env中配置DATABASE_URLDATABASE_URLpostgresql://postgreslocalhost:5432/redwoodblog_dev?connection_limit1注意其中的connection_limit1参数——这是 Prisma 官方在 Serverless 场景下针对关系型数据库的推荐配置生产环境的DATABASE_URL同样需要追加该参数后文 Netlify 环境变量配置中会再次用到。选择一个托管 Postgres 服务教程给出了多个可快速创建 Postgres 实例的托管服务Railway免费、无需登录即可起步但不注册账户数据库会在 24 小时后被删除Heroku PostgresDigital Ocean Managed DatabasesAWS RDS for PostgreSQL教程选择 Railway因为其起步门槛最低。操作流程为进入 Railway 点击Start a New Project然后选择 Provision PostgreSQL。创建完成后在左侧点击PostgreSQL进入Connect选项卡复制以postgresql://开头的Postgres Connection URL该连接串就是后续配置的核心凭据。切换数据库 Provider 并重建迁移拿到生产数据库连接串后需要完成三步切换第一步修改 Prisma schema更新api/db/schema.prisma中的provider配置原文档示例为schema.prisma若项目按 Redwood 标准布局则为api/db/schema.prisma可参考 本地 Postgres 环境搭建指南 中的datasource db块datasource db { provider postgresql url env(DATABASE_URL) }第二步配置 DATABASE_URL打开项目根目录的.env文件取消DATABASE_URL变量的注释并填入从 Railway 复制的连接串。:::info.env与.env.defaults的分工.env默认不会也绝不应该被提交进 Git。它存放代码库所需的全部机密信息——数据库 URL、API 密钥等一旦提交到公开仓库任何人都能看到你的秘密数据。而.env.defaults用于存放非敏感的公共环境变量如日志级别、第三方库的非敏感配置它应当提交进仓库与团队共享。:::第三步删除旧迁移并重新生成SQLite 格式的迁移文件无法在 Postgres 上直接使用需要完全删除后重新生成rm -rf api/db/migrations # 删除旧迁移目录Windows 下用 rmdir /s api\db\migrations yarn rw prisma migrate devyarn rw prisma migrate dev会把此前所有 schema 变更合并为一个全新的迁移文件并直接应用到 Railway 上的远程数据库实例。命令执行时会要求为迁移命名可以起一个类似 initial schema 的名字。如果此步骤遇到 PrismaClientInitializationError 之类的错误可先执行yarn rw prisma generate重新生成 Prisma Client参见 本地 Postgres 环境搭建指南 中的提示。注意本地 Postgres 服务需要手动启停Redwood CLI 不会像 SQLite 那样自动管理它。接入 Netlify构建与部署配置数据库就绪后接下来把代码部署到 Netlify。标准做法分为命令行生成配置与网页端关联仓库两步。生成 netlify.toml在项目根目录执行yarn rw setup deploy netlify从源码看该命令由 packages/cli/src/commands/setup/deploy/providers/netlify.js 实现它实际做了两件事把api侧的 API URL 更新为/.netlify/functions对应 Netlify 的函数挂载路径并向项目根目录写入netlify.toml。该配置文件由 packages/cli/src/commands/setup/deploy/templates/netlify.js 中的NETLIFY_TOML模板生成内容如下[build] command yarn rw deploy netlify publish web/dist functions api/dist/functions [build.environment] NODE_VERSION 20 [[redirects]] from /* to /200.html status 200 [dev] framework redwoodjs # 确保 targetPort 与 redwood.toml 中的 web.port 一致 targetPort 8910 # 浏览器访问端口 port 8888各配置项含义[build]Netlify 的构建配置段。command指定构建命令publish是静态资源输出目录Web 端构建产物functions是 Serverless 函数目录API 端产物。[build.environment]构建期环境变量模板默认指定NODE_VERSION 20确保构建环境与 RedwoodJS 要求的 Node 版本一致。[[redirects]]将根路径/*的所有请求重定向到200.html。这是 Redwood 的 SPA 路由回退fallback机制让浏览器端路由在静态托管环境下正常工作。[dev]Netlify Dev 本地调试配置framework redwoodjs让 Netlify 识别 Redwood 项目。其中构建命令yarn rw deploy netlify由 packages/cli/src/commands/deploy/netlify.js 提供它复用 packages/cli/src/commands/deploy/helpers/helpers.js 中的通用逻辑按顺序执行三条命令yarn rw build --verbose # 生产构建--build默认开启 yarn rw prisma migrate deploy # 应用数据库迁移--prisma默认开启 yarn rw>yarn rw g secret从源码 packages/cli/src/commands/generate/secret/secret.js 可以看到它的实现使用 Node 的crypto.randomBytes生成 32 字节随机数并做 base64 编码默认长度 32可通过--length调整--raw可只输出裸字符串。命令输出后还会提示如果配合 dbAuth 使用请将其设为SESSION_SECRET环境变量。为什么这个变量不可或缺在 packages/auth-providers/dbAuth/api/src/DbAuthHandler.ts 的_validateOptions()中dbAuth 在登录/注册前会强制校验SESSION_SECRET// validates that we have all the ENV and options we need to login/signup _validateOptions() { // must have a SESSION_SECRET so we can encrypt/decrypt the cookie if (!process.env.SESSION_SECRET) { throw new DbAuthError.NoSessionSecretError() } ... }没有SESSION_SECRETdbAuth 会直接抛出NoSessionSecretError。把DATABASE_URL和SESSION_SECRET两个变量都配置好后点击Create variable。触发部署并验证进入顶部导航的Deploys选项卡打开右侧Trigger deploy下拉菜单选择Deploy siteNetlify 将重新拉取仓库并执行完整构建流程构建 → 迁移 → 部署函数。部署成功后点击部署日志页顶部的Preview按钮或返回站点首页点击 Netlify 站点 URL 即可访问线上应用。:::info Preview 与正式 URL 的区别通过Preview按钮查看的部署URL 中包含最近一次提交的 hash。Netlify 会为每次推送到main的提交都生成一个这样的预览地址但它只会展示该次确切提交的内容——如果你再次部署后刷新这个预览页看不到任何变化。而站点主页上展示的真实 URL 始终指向最近一次成功部署的结果。关于分支部署的更多细节见下文 Branch Deploys。:::如何判断是否成功如果首页 About 和 Contact 链接下显示Empty就说明部署成功了——因为全新的生产数据库里还没有任何文章。此时访问/admin/posts创建几篇文章再回到首页就能看到它们。如果部署失败检查 Netlify 构建日志中的报错输出如果部署成功但站点无法访问打开浏览器开发者工具Web Inspector查看前端报错确认是否完整粘贴了 Postgres 连接串仍无法解决时可到 Redwood 社区论坛求助。自定义子域名与自定义域名默认的agitated-mongoose-849e99.netlify.app这类随机域名显然不理想。在Site SettingsDomain ManagementDomainsCustom Domains中打开Options菜单选择Edit site name即可把站点发布到自定义子域名如redwood-tutorial.netlify.app几乎立即生效。注意两点子域名在 Netlify 全局范围内必须唯一blog.netlify.app这类常见名称大概率已被占用如需完全自定义域名点击Add custom domain按钮按提示绑定你拥有的域名。分支部署Branch Deploys与部署预览Netlify 的**分支部署Branch Deploys**是很有用的特性当你创建分支并推送到仓库时Netlify 会为这个分支在独立 URL 上构建一次部署方便在不动主站的情况下测试改动。分支合并回main后主站自动触发部署改动即对全世界可见。开启方式Site settingsBuild deployContinuous Deployment在Branches区域点击Edit settings把Branch deploys改为 All。同时可以启用Deploy previews为针对该仓库的任何 Pull Request 自动生成预览部署。:::tip 锁定 main 分支你还可以锁定main分支让主站不在每次 push 时自动部署而是需要手动触发通过站点控制台或 Netlify CLI才部署最新版本。:::数据库运维关注点连接数Serverless 场景的连接池问题教程部署方案中每个 Serverless 函数都会直连Postgres 数据库。而 Postgres 能接受的并发连接数有限默认 100MySQL 默认 151。设想流量洪峰使 Serverless 函数调用量增长 100 倍Netlify底层是 AWS会毫不犹豫地拉起 100 个 Lambda 实例来处理流量问题在于每个实例都会各自打开一条数据库连接很可能瞬间耗尽可用连接数。正确的做法是在 Postgres 前面架设连接池服务让 Lambda 函数连接连接池而非直连数据库。详细方案参见 Connection Pooling 指南其中介绍了多种选择Prisma Data ProxyPrisma 官方的连接管理与池化服务支持 MySQL 和 PostgresPrisma PgBouncer在 Prisma Client 与数据库之间放置 PgBouncer 作为连接池代理Serverless 函数中需要在连接串上追加?pgbouncertruePgBouncer 端口通常是 6543区别于 Postgres 默认的 5432。注意Prisma Migrate 依赖事务检查迁移状态不能走 PgBouncer 执行迁移迁移时必须直连数据库Supabase / Heroku / Digital Ocean / AWS RDS Proxy等托管方案各有对应配置如 AWS 的 RDS Proxy 必须与 Lambda 在同一 VPC 内、不可公开访问。安全性开放数据库的权衡生产数据库必须对公网开放因为 Serverless 函数运行时的 IP 地址不可预知。理论上可以获取托管商全部 IP 的 CIDR 网段并做白名单但这些网段通常随时间变化维护成本很高。只要数据库用户名/密码保管得当这种开放但加密凭据的方案在可接受范围内尽管并非理想方案。堵住注册漏洞改造 dbAuth 的 signupOptions安全方面还有一个明显的隐患任何人都能注册新账户并开始创建博客文章。一个快速且有效的缓解措施是创建完自己的账户后移除signup路由让普通用户无法访问注册页面。但这对老练的黑客无效——dbAuth 的注册和登录 API 是客户端可调用的即使没有注册页面攻击者依然可以直接构造 API 请求调用同一端点创建新用户。堵住这个洞的关键在api/src/functions/auth.jsTypeScript 项目为auth.ts这是 dbAuth 配置所在。其中signupOptions对象里的handler()函数定义了收到注册表单数据后的行为——只需让它返回false而不创建用户就从 API 层面关上了注册的大门。从 dbAuth 的模板源码 packages/auth-providers/dbAuth/setup/src/templates/api/functions/auth.ts.template 可以看到默认实现的完整结构const signupOptions: DbAuthHandlerOptionsUserType, UserAttributes[signup] { // 新用户注册时对数据的处理。Redwood 在调用此 handler 前会先检查用户名是否重复。 // 至少需要把 username、hashedPassword 和 salt 保存到 user 表。 // userAttributes 包含传给 signUp() 的对象中任何额外的成员。 handler: ({ username, hashedPassword, salt, userAttributes: _userAttributes }) { return db.user.create({ data: { email: username, hashedPassword: hashedPassword, salt: salt, // name: userAttributes.name }, }) }, // 密码格式校验。返回 true 表示密码合法否则抛出 PasswordValidationError。 passwordValidation: (_password) { return true }, errors: { fieldMissing: ${field} is required, usernameTaken: Username ${username} already in use, }, }默认的handler()会执行db.user.create(...)创建用户。要关闭公开注册把handler改为handler: () { return false },如此即使用户数据被提交dbAuth 也不会创建任何账户。修改完成后提交并推送代码Netlify 会自动重新部署注册漏洞即被堵住。总结至此一个 RedwoodJS 全栈应用完成了从本地 SQLite 到生产环境的完整上线Git 托管代码 → 托管 Postgres 承载数据 → 重建 Prisma 迁移 → Netlify 关联仓库并自动构建 → 配置DATABASE_URL与SESSION_SECRET→ 触发部署并验证 → 自定义域名与分支预览 → 理解连接池与数据库安全 → 通过改造 dbAuth 堵住公开注册漏洞。这套流程的核心经验可以沉淀为三点生产与开发必须使用同一数据库 provider让 CI/CD 平台而非本地 CLI执行构建以保证 Prisma 引擎与运行环境匹配Serverless 架构下数据库连接与安全需要提前规划连接池、connection_limit1、独立的SESSION_SECRET。掌握这些你就能把任何 RedwoodJS 应用可靠地部署到 Jamstack 世界。【免费下载链接】redwoodRedwoodGraphQL项目地址: https://gitcode.com/gh_mirrors/re/redwood创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考