Remix Supa Fly Stack

此自述文件即将重写

The Remix Indie Stack

了解更多关于 Remix Stacks 的信息。

npx create-remix --template rphlmr/supa-fly-stack

Stack 中包含什么

不喜欢 stack 中的某些部分?Fork 它,修改它,然后使用 npx create-remix --template your/repo!使其成为您自己的。

开发

  • 创建一个 Supabase 数据库(免费层级提供 2 个数据库)

    注意:仅用于尝试 Supabase 或 2 个用于 stagingproduction

    注意:使用完所有免费层级了吗?也可以使用 Supabase CLI 和本地自托管

    注意:创建一个强大的数据库密码,但最好使用密码短语,它在连接字符串中更容易使用(无需转义特殊字符)

    例如:my_strong_passphrase

  • 转到 https://app.supabase.io/project/{PROJECT}/settings/api 查找您的密钥

  • “项目 API 密钥”

  • 将您的 SUPABASE_URLSERVER_URLSUPABASE_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
    

这将在开发模式下启动您的应用程序,并在文件更改时重建资源。

数据库种子脚本会创建一个新用户,其中包含一些可用于入门的数据

相关代码

这是一个非常简单的笔记应用程序,但它是一个很好的示例,说明如何使用 Prisma、Supabase 和 Remix 构建一个全栈应用程序。主要功能是创建用户、登录和注销(处理访问和刷新令牌 + 在过期时刷新)以及创建和删除笔记。

部署

如果您是 Fly.io 专家,请执行您知道的操作。

此 Remix Stack 带有两个 GitHub Actions,用于处理自动将您的应用程序部署到生产和暂存环境。

在您首次部署之前,您需要做一些事情

  • 安装 Fly

  • 注册并登录 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_SECRETSUPABASE_URLSUPABASE_SERVICE_ROLESUPABASE_ANON_PUBLICSERVER_URLDATABASE_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_SECRETSUPABASE_URLSUPABASE_SERVICE_ROLESUPABASE_ANON_PUBLICSERVER_URLDATABASE_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 数据库

如果您的令牌在少于 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 添加一些配置。您需要添加站点 URL 以及本地、测试和实时应用程序的重定向 URL,这些 URL 将用于 oauth。为此,请导航到身份验证 > URL 配置并添加以下值