带有 Turborepo 的 Remix Gospel Stack

The Remix Gospel Stack

Remix TypeScript monorepo,具有 Turborepo 管道、Prisma、PostgreSQL 或 SQLite (Litefs)、Docker 部署到 Fly.io、pnpm、shadcn/ui TailwindCSS。

pnpm create remix@latest --init-script --install --template https://github.com/PhilDL/remix-gospel-stack

:minidisc: 此仓库具有预设倾向

  • 仅限 TypeScript
  • 仅与 pnpm 包管理器兼容,用于处理 monorepo 工作区。
  • 使用 turborepo 管道 + 缓存来构建、lint、类型检查和测试 monorepo。

(替代方案) 克隆仓库

git clone git@github.com:PhilDL/remix-gospel-stack.git
cd remix-gospel-stack
pnpm add -w @remix-run/dev
pnpm remix init

技术栈包含什么

此技术栈是一个以 Remix 为导向的 Monorepo,由 turborepo 和 pnpm 工作区驱动。包含一个可以通过构建 Docker 容器在 fly.io 上部署的 Remix 应用。

此包使用 pnpm 作为首选的包管理器来管理工作区。如果您将工作区定义放在 package.json 文件中,它可能与 yarnnpm 一起工作,但不能保证。

Turborepo 和 pnpm 工作区驱动的 Monorepo 架构

  • apps 文件夹包含应用程序

  • packages 文件夹包含示例

    • ui: 一个由 shadcn/ui 驱动的 React UI 包示例。一些示例组件和 shadcn/ui Tailwind 配置作为 Tailwind 插件和预设导出。
    • database: 一个 Prisma 包装器,准备在其他包或应用程序中使用。与 tsup 捆绑在一起。可以根据您在安装期间的选择使用 PostgreSQL 或 SQLite // Litefs。
    • business: 一个示例包,使用 Prisma database 作为依赖项,并使用类似 _存储库模式_ 的示例。
    • internal-nobuild: 一个示例包,它是纯 TypeScript,没有构建步骤。该包的 main 入口点直接是 src/index.ts。Remix 负责使用其自己的构建步骤 (使用 esbuild) 进行编译。此包还包含使用 Vitest 的单元测试。Remix 使用 tsconfig.json 路径来引用该项目及其类型。当您不打算发布该包时,我建议使用这些类型的内部包。
  • config-packages:

    • 具有不同预设配置的 Eslint 包。
    • TS 配置,也具有不同的预设。
    • Tailwind 配置。

所有 Remix 未来标志均已激活

future: {
  unstable_optimizeDeps: true,
  v3_fetcherPersist: true,
  v3_lazyRouteDiscovery: true,
  v3_relativeSplatPath: true,
  v3_throwAbortReason: true,
  v3_singleFetch: true,
  v3_routeConfig: true,
},

还有什么?

警告 以下所有命令都应从 monorepo 根目录启动

开发

  • 安装依赖项。

    pnpm install
    

    您还必须复制示例 .env.example

    cp .env.example .env
    cp .env.example .env.docker
    
  • 启动 postgresql docker 容器

    pnpm run docker:db
    

    注意:当 Docker 在后台设置容器时,npm 脚本将完成。请确保 Docker 已完成并且您的容器正在运行,然后再继续。

  • 生成 prisma schema

    pnpm run generate
    
  • 将 Prisma 迁移运行到数据库

    pnpm run db:migrate:deploy
    
  • 运行第一个构建(通过 ... 选项包含依赖项)

    pnpm run build --filter=@remix-gospel-stack/remix-app...
    

    简单运行 pnpm run build 将构建所有内容,包括 NextJS 应用。

  • 运行 Remix 开发服务器

    pnpm run dev --filter=@remix-gospel-stack/remix-app
    

在 PostgreSQL 和 SQLite (Litefs) 之间切换

  • 要在 PostgreSQL 和 SQLite (Litefs) 之间切换,您可以使用存储库根目录中的 turbo 生成器。

    pnpm turbo gen scaffold-database
    

    然后按照提示进行操作。但请注意,prisma 迁移链接到特定数据库,因此您必须删除 migrations 文件夹。

    注意:切换到需要另一个包 (litefs-js) 的 SQLite (Litefs) 后,您必须再次运行 pnpm i --fix-lockfile。您可能还必须再次运行 pnpm run setup 才能生成第一次迁移。

创建包

内部包

turbo gen workspace --name @remix-gospel-stack/foobarbaz --type package --copy

然后按照提示进行操作

测试、类型检查、Lint、安装包...

查看 turbo.json 文件以查看可用的管道。

  • 运行 Cypress 测试和 Dev
    pnpm run test:e2e:dev --filter=@remix-gospel-stack/remix-app
    
  • Lint 所有内容
    pnpm run lint
    
  • 类型检查整个 monorepo
    pnpm run typecheck
    
  • 测试整个 monorepo
    pnpm run test
    or
    pnpm run test:dev
    
  • 如何在 Remix 应用中安装 npm 包?
    pnpm add dayjs --filter @remix-gospel-stack/remix-app
    
  • 调整 config-package 文件夹中的 tsconfigs、eslint 配置。然后,任何包或应用都将从这些配置扩展。

在 fly.io 上部署 – PostgreSQL

警告 以下所有命令都应从 monorepo 根目录启动

在首次部署之前,您需要执行一些操作

  • 首先注册 fly CLI

    fly auth signup
    
  • 在 Fly 上创建两个应用,一个用于预发布,一个用于生产

    fly apps create remix-gospel-stack
    fly apps create remix-gospel-stack-staging
    

    注意:成功创建应用后,请仔细检查 fly.toml 文件,确保 app 键是您创建的生产应用的名称。此 Stack 在初始化时会自动附加唯一后缀,这可能与您在 Fly 上创建的应用不匹配。如果出现此不匹配,您可能会在 Github Actions CI 日志中看到 404 错误

  • 初始化 Git。

    git init
    
  • 创建一个新的 GitHub 仓库,然后将其添加为项目的远程仓库。不要立即推送您的应用!

    git remote add origin <ORIGIN_URL>
    
  • FLY_API_TOKEN 添加到您的 GitHub 仓库。为此,请转到您在 Fly 上的用户设置并创建一个新的 令牌,然后将其以名称 FLY_API_TOKEN 添加到 您的仓库机密 中。

  • 为您的预发布和生产环境创建数据库

创建数据库

fly postgres create --name remix-gospel-stack-db
fly postgres attach --app remix-gospel-stack remix-gospel-stack-db

fly postgres create --name remix-gospel-stack-staging-db
fly postgres attach --app remix-gospel-stack-staging remix-gospel-stack-staging-db

注意:当您附加预发布数据库时,您将收到与上述 fly set secret 步骤中相同的原因的相同警告。不用担心。继续!

Fly 将负责为您设置 DATABASE_URL 机密。

在 fly.io 上部署 – SQLite Litefs

警告 以下所有命令都应从 monorepo 根目录启动

在首次部署之前,您需要执行一些操作

  • 首先注册 fly CLI

    fly auth signup
    
  • 在 Fly 上创建两个应用,一个用于预发布,一个用于生产

    fly apps create remix-gospel-stack
    fly apps create remix-gospel-stack-staging
    

    注意:成功创建应用后,请仔细检查 fly.toml 文件,确保 app 键是您创建的生产应用的名称。此 Stack 在初始化时会自动附加唯一后缀,这可能与您在 Fly 上创建的应用不匹配。如果出现此不匹配,您可能会在 Github Actions CI 日志中看到 404 错误

  • 初始化 Git。

    git init
    
  • 创建一个新的 GitHub 仓库,然后将其添加为项目的远程仓库。不要立即推送您的应用!

    git remote add origin <ORIGIN_URL>
    
  • FLY_API_TOKEN 添加到您的 GitHub 仓库。为此,请转到您在 Fly 上的用户设置并创建一个新的 令牌,然后将其以名称 FLY_API_TOKEN 添加到 您的仓库机密 中。

为您的预发布和生产环境的 sqlite 数据库创建一个持久卷。运行以下命令(可以根据您的需要和您选择的区域更改 GB 大小 ( https://fly.io/docs/reference/regions/)。如果您更改了区域,请确保同时更改 fly.toml 中的 primary_region)

fly volumes create data --region cdg --size 1 --app remix-gospel-stack
fly volumes create data --region cdg --size 1 --app remix-gospel-stack-staging

然后将卷附加到应用

fly consul attach --app remix-gospel-stack
fly consul attach --app remix-gospel-stack-staging

开始编码!

现在一切都已设置完毕,您可以提交并将更改推送到您的仓库。每次提交到您的 main 分支都会触发部署到您的生产环境,每次提交到您的 dev 分支都会触发部署到您的预发布环境。

如果您在部署到 Fly 时遇到任何问题,请确保您已按照上述所有步骤操作,如果您已按照操作,请将尽可能多的有关您部署的详细信息(包括您的应用名称)发布到 Fly 支持社区。他们通常在那里响应很快,希望可以帮助解决您的任何部署问题和疑问。

多区域部署

一旦你的网站和数据库在单个区域运行起来,你可以按照 Fly 的扩展多区域 PostgreSQL 文档中的说明添加更多区域。

请务必为你的应用设置一个 PRIMARY_REGION 环境变量。你可以在 fly.toml 中使用 [env] 配置将其设置为你想要用作应用和数据库主区域的区域。

在其他区域测试你的应用

安装 ModHeader 浏览器扩展程序(或类似的程序),并使用它加载你的应用,并将标头 fly-prefer-region 设置为你想要测试的区域名称。

你可以检查响应中的 x-fly-region 标头,以了解你的请求由哪个区域处理。

GitHub Actions

我们使用 GitHub Actions 进行持续集成和部署。任何进入 main 分支的内容都将在运行测试/构建等操作后部署到生产环境。任何在 dev 分支中的内容都将部署到暂存环境。

手动构建 Docker 镜像以使用 Fly.io 部署

  • 创建一个 Docker 网络
    docker network create app_network
    
  • 构建 Docker 镜像
    pnpm docker:build:remix-app
    
  • 运行 Docker 镜像
    pnpm docker:run:remix-app
    
  • (可选)如果你想手动部署到 fly.io
    DOCKER_DEFAULT_PLATFORM=linux/amd64 flyctl deploy --config ./apps/remix-app/fly.toml --dockerfile ./apps/remix-app/Dockerfile
    

了解有关 Turborepo 功能的更多信息

感谢

支持

如果你觉得这个模板有用,请考虑给它一个 Star ⭐。谢谢!

免责声明

我绝不是 Monorepo、Docker 或 CI 方面的专家。这里提出的设置只是众多设置中的一种,并且可能可以改进 10 倍,但我正在自己摸索学习,所以如果你看到任何可能的改进,请提交 PR。我将非常感谢!