SaaS-Boilerplate介绍

April 11, 2024

SaaS Boilerplate是一个全栈React应用开发框架,基于Next.js、Tailwind CSS、Shadcn UI、TypeScript构建,具备Auth、Multi-tenancy、Roles & Permissions、i18n、Landing Page、DB、Logging、Testing等功能。它还支持14+ Next.js版本、Tailwind CSS 3.4和TypeScript。开发环境包括:Prettier、Lint-Staged、Jest、Testing Library、Commitlint、VSCode、PostCSS、Clerk、DrizzleORM、Sentry、Log Management、Checkly、Storybook、Multi-language(i18n)等。它具有非常灵活的代码结构,并严格类型检查,支持多语言(i18n)和团队协作。此外,它还具备强大的身份验证和访问控制功能,并支持多因素Auth和多因素认证(如Google、Facebook、Twitter等)。最后,它还具备数据库管理和多语言支持,以及强大的Validation Library和Linter。

特性

authentication

使用Clerk实现用户认证、orgniztion管理的基础能力。

database

使用 DrizzleORM 操作DB。虽然官方推荐使用Turso + libSQL ,看代码貌似没有强制。理论上任意平台的SQLite, PostgreSQL, MySQL 都可以。也集成了drizzle studio,方便查看、管理DB。

注意项目中仅仅集成了其基础特性,并没有限制业务如何使用。

Translation (i18n)

使用了Crowdin的能力, src/locales/ 目录下有两个对应的本地化结果(默认支持英语和法语)。

  1. 如何更新? 利用Crowdin的能力,只需要更新一个源文件,就可以自动生成其他语言的翻译文件。Crowdin有两种使用方式,一种是直接去网站手工上传&下载。另外一种是通过官方提供的命令行工具,通过配置文件 crowdin.yml 自动生成。
    Loading...

    项目中推荐使用git action自动完成翻译工作。

    // The localisation files are synced with Crowdin using GitHub Actions. // By default, there are 3 ways to sync the message files: // 1. Automatically sync on push to the `main` branch // 2. Run manually the workflow on GitHub Actions // 3. Every 24 hours at 5am, the workflow will run automatically
  2. 如何新增其他语种? 除了使用Crowdin生成对应的翻译文件外,项目中也需要配置其他语言的切换入口。参看 AppConfig/locals 中的语言列表定义。

    多语言支持使用的是 next-intel 的能力,大致流程如下,详细流程参考官网:

    • 配置 next.config.mjs 以及定义 i18n.ts :目的是根据请求动态加载不同的翻译文件,供后续components中使用。
    • 中间件引入locales:指定 locales 相关定义,用于路由判断。注意中间件中需要考虑 @clerk/nextjs 鉴权的执行顺序。主要包括以下几个参数:
      • locales:支持的语言列表
      • localePrefix:路由的处理方式,可以控制在URL path中是否出现locale,详见文档。项目中使用的是 as-needed ,即默认locale时不需要出现在path中。
      • defaultLocale:默认locale
    • 全局layout中增加locale的处理:中间件会将locale转换为url参数,在layout中通常做以下几件事:
      • 判断locale合法性,异常请求拦截
      • 在输出的html中增加lang property,主要用于浏览器的拼写检查、SEO优化等。
        Loading...
    • 在服务、客户端组件中使用,在服务端和客户端的使用方式上有差异,具体使用方法详见文档。项目中的典型用法:
      Loading...
    • locales 切换入口:页面需要提供语言切换的入口。
      • dashboard/layout 中引入了LocaleSwitcher组件,提供语言切换的组件。
      • LocaleSwitch封装 next-intl/navigation 中更新locale的能力,当用户点击切换button时实现参数切换、路由跳转等。

next-sitemap

使用https://github.com/iamvishnusankar/next-sitemap来生成 sitemap.xmlrobots.txt 。貌似相比Next的原生方案可以更加灵活,比如支持 index sitempas

Commit Message Format

借助 cz 工具,要求所有commit message必须按照《约定式提交规范》的格式来生成commit message,相对自己裸写会commit message更加清晰。另外按照此规范,可以自动生成 CHANGELOG 文件(本项目使用semantic-release生成)。

为什么使用约定式提交
  • 自动化生成 CHANGELOG。
  • 基于提交的类型,自动决定语义化的版本变更。
  • 向同事、公众与其他利益关系者传达变化的性质。
  • 触发构建和部署流程。
  • 让人们探索一个更加结构化的提交历史,以便降低对你的项目做出贡献的难度。

Testing & Code Coverage

  • 项目支持使用jest进行单侧
  • 支持使用playwright进行自动化测试
  • 支持使用codecov来统计覆盖率【仅统计】—— 貌似jest也支持本地统计吧

Edge runtime

项目支持Edge runtime方式部署,不过由于Edge与自动迁移无法兼容,启用前需要先禁用掉db的自动迁移,db变更时改为手动执行 migrate 操作。

Logging

使用 Pino.js来作为本地日志库,pino在性能上有着不错的口碑。

在生产环境,支持使用Better Stack来管理远程日志。Better Statck支持日志记录、查询以及监控等能力。——感觉跟Sentry、Datadog等类似。

Error Monitoring

错误监控使用的是 Sentry,包含了日志收集、告警通知、性能监控等能力。类似的前端监控产品有Datalog等。

部署方式上,Sentry支持官方托管(支持免费、付费套餐)和Self-Hosting两种方式,看上去对开发更加友好。

Checkly监控

使用Checkly来实现生成环境的可用性监控。类似接口测试工具,Checkly支持远程API测试验证接口可用性,同时也支持远程对页面的e2e可用性测试。

源码解析

路由

项目采用 AppRoute 的方式,一级路由为 locale 用于区分语言,二级路由拆分了两个不同的目录,分别用于是否认证(auth / unauth)的场景【拆分无实际意义,只是为了管理方便】。

layout

  • 注入基础metadata:icons
  • 处理locale:写入html.lang, 增加NextIntlClientProvider父组件封装,供后续component使用。

 

(unauth)

  • 动态生成metadata(因为需要根据locale获取对应的 meta_title meta_description
  • page内容:内容由首页几个component组成,主要介绍产品features
Loading...

 

认证拦截

中间件中需要对部分路由设置认证保护,主要有几个选项需要设置:

  • publicRoutes:公共路由,目前是手工将unauth目录下的两个目录加入的,后续有新增path时也需要更新。
  • beforeAuth:在认证前处理的逻辑,会根据beforeAuth的处理结果决定是否需要进行认证校验。项目中将 next-intel 中间件放到了这里,因为请求可能会被redirect等。
  • afterAuth:自定义的 afterAuth 除了将登录和注册添加到公共路由外,完全取代了clerk的默认行为。项目的处理逻辑:
    • 未登录:跳转登录
    • 已登录无orgId,跳转 /onboarding/organization-selection

感觉Clerk的orgnization组织逻辑有点奇怪,注册后必须指定orgnization。为何不能默认?

 

(auth)

  • layout:主要包括以下几个部分
    • OrganizationSwitcher:clerk提供的orgnization切换组件(clerk还真是提供全套,页面组件都覆盖到了)
    • 各page入口,包括
      • /dashboard 登录后的首页
      • /dashboard/organization-profile members管理
      • /dashboard/organization-profile/organization-settings orgnization设置页
    • locale 切换和UserButton,UserButton也是直接使用Clerk的组件来展示用户信息以及log out入口。
  • pages
    • dashboard 登录后的首页,这里也是模板适用方来定制业务逻辑最合适的地方。
    • /dashboard/organization-profile orgnization member管理和setting,主要用来承载clerk的成员管理组件OrganizationProfile
    • /dashboard/organization-profile/organization-settings
  • sign-in/sign-up

    借助clerk的SignUp、SignIn组件,实现登入、登出的能力。

总结

优点

  • 特性集成比较丰富,重点包括
    • 基于Drizzle ORM实现DB存储能力
    • 基于Clerk的用户及orgnization管理能力
    • SEO:sitemap、robot等基础SEO特性
    • 可观测能力:基于Sentry、Checkly实现的可观测、监控能力。
    • 测试:单侧以及e2e测试
    • 工程化能力:包括eslint、commit message format规范化等
    • next.js等版本都比较新

不足

  • 覆盖的特性有点求多,比如监控就引入了好几个。感觉在选型上可以考虑更加简单些的方案。重点关注基础能力上,毕竟小型SaaS对单测、可观测的要求并没有那么高【ps: 个人意见】。
  • 用户认证(登入、登出、orgnization等)完全依赖Clerk,不确定是否是最优解。在我本地测试时发现响应也比较慢,可能在国外这个不是问题。
  • 个人觉得在一些Saas基础能力上可以做一些扩展,比如支付、文档化、文件存储、邮件能力等。

 

整体来说SaaS Boilerplate是个不错的模板选项,试用有一定开发能力且需要快速搭建Saas平台的场景。另外作者响应也比较迅速,提个issue能很快被响应。类似的产品还有https://github.com/wasp-lang/open-saas等。后续可以做个对比。

See all postsSee all posts