Remix Supa Fly Stack
此自述文件即将重写
了解更多关于 Remix Stacks 的信息。
npx create-remix --template rphlmr/supa-fly-stack
Stack 中包含什么
- 使用 Docker 的 Fly 应用部署
- 生产就绪的 Supabase 数据库
- 用于 Fly 备份区域回退的健康检查端点
- GitHub Actions 用于在合并到生产和暂存环境时进行部署
- 使用 基于 cookie 的会话进行电子邮件/密码身份验证 / Magic Link
- 使用 Prisma 的数据库 ORM
- 使用 Remix Params Helper 进行表单模式(客户端和服务器端!)验证
- 使用 Tailwind 进行样式设置
- 使用 Cypress 进行端到端测试
- 使用 MSW 进行本地第三方请求模拟
- 使用 Vitest 和 Testing Library 进行单元测试
- 使用 Prettier 进行代码格式化
- 使用 ESLint 进行代码检查
- 使用 TypeScript 进行静态类型检查
不喜欢 stack 中的某些部分?Fork 它,修改它,然后使用 npx create-remix --template your/repo
!使其成为您自己的。
开发
-
创建一个 Supabase 数据库(免费层级提供 2 个数据库)
注意:仅用于尝试 Supabase 或 2 个用于
staging
和production
注意:使用完所有免费层级了吗?也可以使用 Supabase CLI 和本地自托管
注意:创建一个强大的数据库密码,但最好使用密码短语,它在连接字符串中更容易使用(无需转义特殊字符)
例如:my_strong_passphrase
-
转到 https://app.supabase.io/project/{PROJECT}/settings/api 查找您的密钥
-
“项目 API 密钥”
-
将您的
SUPABASE_URL
、SERVER_URL
、SUPABASE_SERVICE_ROLE
(又名service_role
secret
)、SUPABASE_ANON_PUBLIC
(又名anon
public
) 和DATABASE_URL
添加到.env
文件中注意:
SERVER_URL
是开发环境中的 localhost。它将用于 magic link 登录
DATABASE_URL="postgres://postgres:{STAGING_POSTGRES_PASSWORD}@db.{STAGING_YOUR_INSTANCE_NAME}.supabase.co:5432/postgres"
SUPABASE_ANON_PUBLIC="{ANON_PUBLIC}"
SUPABASE_SERVICE_ROLE="{SERVICE_ROLE}"
SUPABASE_URL="https://{STAGING_YOUR_INSTANCE_NAME}.supabase.co"
SESSION_SECRET="super-duper-s3cret"
SERVER_URL="https://127.0.0.1:3000"
-
仅当您选择不使用 CLI 为您安装依赖项时,才应用此步骤
npx remix init
-
初始设置
npm run setup
-
启动开发服务器
npm run dev
这将在开发模式下启动您的应用程序,并在文件更改时重建资源。
数据库种子脚本会创建一个新用户,其中包含一些可用于入门的数据
- 电子邮件:
[email protected]
- 密码:
supabase
相关代码
这是一个非常简单的笔记应用程序,但它是一个很好的示例,说明如何使用 Prisma、Supabase 和 Remix 构建一个全栈应用程序。主要功能是创建用户、登录和注销(处理访问和刷新令牌 + 在过期时刷新)以及创建和删除笔记。
- 身份验证 / 会话 ./app/modules/auth
- 创建和删除笔记 ./app/modules/note
部署
如果您是 Fly.io 专家,请执行您知道的操作。
此 Remix Stack 带有两个 GitHub Actions,用于处理自动将您的应用程序部署到生产和暂存环境。
在您首次部署之前,您需要做一些事情
-
注册并登录 Fly
fly auth signup
注意:如果您有多个 Fly 帐户,请确保您在 Fly CLI 中登录的帐户与您在浏览器中登录的帐户相同。在您的终端中,运行
fly auth whoami
并确保电子邮件与浏览器中登录的 Fly 帐户匹配。 -
在 Fly 上创建两个应用程序,一个用于暂存,一个用于生产
fly apps create supa-fly-stack-template fly apps create supa-fly-stack-template-staging # ** not mandatory if you don't want a staging environnement **
注意:对于生产应用程序,请确保此名称与您的
fly.toml
文件中设置的app
匹配。否则,您将无法部署。- 初始化 Git。
git init
-
创建一个新的 GitHub 存储库,然后将其添加为项目的远程存储库。不要立即推送您的应用程序!
git remote add origin <ORIGIN_URL>
-
将
FLY_API_TOKEN
添加到您的 GitHub 存储库。为此,请转到 Fly 上的用户设置并创建一个新的 令牌,然后使用名称FLY_API_TOKEN
将其添加到 您的存储库机密中。 -
将
SESSION_SECRET
、SUPABASE_URL
、SUPABASE_SERVICE_ROLE
、SUPABASE_ANON_PUBLIC
、SERVER_URL
和DATABASE_URL
添加到您的 fly 应用程序机密注意:要查找您的
SERVER_URL
,请转到 您的 fly.io 仪表板为此,您可以运行以下命令
# production (--app name is resolved from fly.toml) fly secrets set SESSION_SECRET=$(openssl rand -hex 32) fly secrets set SUPABASE_URL="https://{YOUR_INSTANCE_NAME}.supabase.co" fly secrets set SUPABASE_SERVICE_ROLE="{SUPABASE_SERVICE_ROLE}" fly secrets set SUPABASE_ANON_PUBLIC="{SUPABASE_ANON_PUBLIC}" fly secrets set DATABASE_URL="postgres://postgres:{POSTGRES_PASSWORD}@db.{YOUR_INSTANCE_NAME}.supabase.co:5432/postgres" fly secrets set SERVER_URL="https://{YOUR_STAGING_SERVEUR_URL}" # staging (specify --app name) ** not mandatory if you don't want a staging environnement ** fly secrets set SESSION_SECRET=$(openssl rand -hex 32) --app supa-fly-stack-template-staging fly secrets set SUPABASE_URL="https://{YOUR_STAGING_INSTANCE_NAME}.supabase.co" --app supa-fly-stack-template-staging fly secrets set SUPABASE_SERVICE_ROLE="{STAGING_SUPABASE_SERVICE_ROLE}" --app supa-fly-stack-template-staging fly secrets set SUPABASE_ANON_PUBLIC="{STAGING_SUPABASE_ANON_PUBLIC}" --app supa-fly-stack-template-staging fly secrets set DATABASE_URL="postgres://postgres:{STAGING_POSTGRES_PASSWORD}@db.{STAGING_YOUR_INSTANCE_NAME}.supabase.co:5432/postgres" --app supa-fly-stack-template-staging fly secrets set SERVER_URL="https://{YOUR_STAGING_SERVEUR_URL}" --app supa-fly-stack-template-staging
如果您没有安装 openssl,您也可以使用 1password 生成一个随机密钥,只需将
$(openssl rand -hex 32)
替换为生成的密钥。
现在一切都已设置好,您可以提交并将更改推送到您的存储库。每次提交到您的 main
分支都将触发部署到您的生产环境,每次提交到您的 dev
分支都将触发部署到您的暂存环境。
注意:要手动部署,只需运行
fly deploy
(它将部署在 fly.toml 中定义的应用程序)
GitHub Actions
免责声明:Github actions ==> 我不是这方面的专家。请在使用前仔细阅读
我们使用 GitHub Actions 进行持续集成和部署。任何进入 main
分支的内容都将在运行测试/构建等之后部署到生产环境。dev
分支中的任何内容都将部署到暂存环境。
👉 您必须为 cypress 添加一些 env 密钥。 👈
将 SESSION_SECRET
、SUPABASE_URL
、SUPABASE_SERVICE_ROLE
、SUPABASE_ANON_PUBLIC
、SERVER_URL
和 DATABASE_URL
添加到 您的存储库机密中
测试
Cypress
我们在此项目中使用 Cypress 进行端到端测试。您可以在 cypress
目录中找到这些测试。在您进行更改时,请在 cypress/e2e
目录中添加到现有文件或创建新文件来测试您的更改。
我们使用 @testing-library/cypress
以语义方式选择页面上的元素。
要在开发环境中运行这些测试,请完成您的 .env
并运行 npm run test:e2e:dev
,这将启动应用程序的开发服务器以及 Cypress 客户端。确保数据库如上所述在 docker 中运行。
我们还有一个实用程序,可以在测试结束时自动删除用户。只需确保将其添加到每个测试文件中
afterEach(() => {
cy.cleanupUser();
});
这样,我们就可以保持您的测试数据库清洁并使您的测试彼此隔离。
Vitest
对于实用程序和单个组件的较低级别测试,我们使用 vitest
。我们通过 @testing-library/jest-dom
拥有特定于 DOM 的断言助手。
类型检查
此项目使用 TypeScript。建议为您的编辑器设置 TypeScript,以便获得良好的编辑器内体验,包括类型检查和自动完成。要对整个项目运行类型检查,请运行 npm run typecheck
。
代码检查
此项目使用 ESLint 进行代码检查。它在 .eslintrc.js
中配置。
格式化
我们在此项目中使用 Prettier 进行自动格式化。建议安装一个编辑器插件(如 VSCode Prettier 插件)以在保存时进行自动格式化。还有一个 npm run format
脚本,您可以运行它来格式化项目中的所有文件。
开始使用 Supabase
您现在可以继续进行下一步了,恭喜!
要扩展您的 Prisma 模式并将更改应用到您的 supabase 数据库
-
在 ./app/database/schema.prisma 中进行更改
-
准备您的模式迁移
npm run db:prepare-migration
-
在 ./app/database/migrations 中检查您的迁移
-
将此迁移应用到生产环境
npm run db:deploy-migration
如果您的令牌在少于 1 小时(Supabase 仪表板中的 3600 秒)内过期
如果您的令牌生命周期比我短(1 小时),您应该查看 ./app/modules/auth/session.server.ts 中的 REFRESH_ACCESS_TOKEN_THRESHOLD
并设置您认为最适合您的用例的值。
Supabase RLS
您可能会问“我可以在 Remix 中使用 RLS 吗”。
答案是“可以”,但它有成本。
使用 Supabase SDK 服务器端查询您的数据库(对于那些使用 RLS 功能的人)会增加额外的延迟,因为调用 Gotrue rest API 而不是直接调用 Postgres 数据库(这没问题,因为 Supabase SDK 最初是为那些没有/不想使用后端的人准备的)。
在我的基准测试中,这使得我的页面速度慢了两倍。(与使用 Prisma 的直接查询相比,约 +200 毫秒)
使用 magic link 登录 Supabase
为了使使用 magic link 的注册/登录工作,您需要向 Supabase 添加一些配置。您需要添加站点 URL 以及本地、测试和实时应用程序的重定向 URL,这些 URL 将用于 oauth。为此,请导航到身份验证 > URL 配置并添加以下值