用 Lerna 管理单仓库,一套 GraphQL + Relay 同时服务 Web 与 App 端
Relay 统一前后端数据层,React 与 React Native 共享业务逻辑,Lerna 统一管理多包
方案简介
Entria FullStack Playground 是一个以 Monorepo 形式组织的全栈演练场。仓库描述明确写道:"Monorepo Playground with GraphQL, React, React Native, Relay Modern, TypeScript and Jest"。它把 GraphQL 服务端、React Web 前端和 React Native 移动端放在同一个代码仓库中,使用 Lerna 与 Yarn Workspaces 管理多个包,用 Relay Modern 作为数据获取框架连接前端与 GraphQL 后端,TypeScript 提供类型系统,Jest 承担测试职责。
这套方案解决的核心问题是:前后端分离开发时接口联调繁琐、多端(Web/App)重复实现数据层的痛点。通过单仓库 + GraphQL + Relay 的组合,服务端 schema 变更可以即时反映到前端类型与查询中,Web 与 App 两端复用同一套数据查询代码。
该项目定位为开源 Playground(演练场),作者专门撰文说明为什么公司应该拥有开源 Playground("Read more about Playgrounds: https://medium.com/@sibelius/why-your-company-should-have-an-open-source-playground-4bb93068ce95")。适合希望在真实全栈环境中试验 GraphQL + Relay Modern + React Native 技术栈的团队与个人开发者,498 star 也说明其作为参考实现受到社区关注。
亮点与能力
- 单仓库(Monorepo)同时容纳 server、web、app 多个包,一次
yarn install安装全部依赖 - GraphQL 作为前后端统一数据协议,服务端为 Web 与 App 提供同一 API
- Relay Modern 作为声明式数据获取框架,分别面向 web 与 app 提供独立编译命令
- React 构建 Web 端,React Native 构建 App 端,双端共存于同一仓库
- TypeScript 提供静态类型支持(typescript ^4.0.3)
- Jest 承担单测职责(jest ^26.5.3),并配合 babel-jest 使用
- Babel 7 全家桶配置了大量实验性语法插件,支持最新 JS 语法
- 包含 husky、lint-staged、commitlint 等提交规范化工具链
组成与分工
- Lerna:Monorepo 多包管理器,编排 server/web/app 各包的依赖安装与脚本(Topics 中含 lerna、monorepo)
- GraphQL:后端 API 层协议,作为全栈数据交互中心
- Relay Modern:Facebook 的 GraphQL 客户端框架,web 与 app 各有独立编译命令(
yarn web:relay、yarn app:relay) - React:Web 前端 UI 框架
- React Native:移动端 UI 框架,复用同一数据层
- TypeScript:全仓静态类型系统
- Jest + babel-jest:测试框架,通过 babel 桥接编译
- Babel 7(preset-env / preset-typescript / preset-flow 等):语法编译层,涵盖大量 proposal 插件
- metro-config:React Native 打包器 metro 的配置依赖
前置要求
依赖 Node/Yarn 环境与 React Native 开发环境。
- 需要可用的 Yarn 包管理器,在仓库根目录执行安装:
yarn install
- 运行 App 包前,官方建议先阅读 React Native 官方入门文档:"We recommend that you read https://facebook.github.io/react-native/docs/getting-started before starting"
- 服务端使用 Mongoose(@types/mongoose ^5.7.36)等,暗示需要 MongoDB 数据库;使用了 dotenv-safe(@types/dotenv-safe ^8.1.1)管理环境变量。
实施步骤
按 README 的 Getting Started 顺序,从零跑通整套 Monorepo:
1. 安装依赖
在仓库根目录安装所有包的依赖:
yarn install
2. 启动服务端包
yarn start:server
服务端提供 GraphQL API,是 web 与 app 两个客户端包的数据来源。
3. 运行 Web 包
先编译 Relay(将前端 GraphQL 查询编译为 Relay 运行时代码):
yarn web:relay
然后启动 Web 包:
yarn web:start
4. 运行 App 包
先阅读 React Native 官方入门文档配置好移动端开发环境,然后编译 Relay:
yarn app:relay
启动 App 包:
yarn app:start
使用与配置要点
- 每次修改组件中的 GraphQL 查询(Relay fragment/query)后,需要重新执行对应端的 Relay 编译命令:web 用
yarn web:relay,app 用yarn app:relay,再启动对应包 - 日常开发流程:先
yarn start:server启动后端,再并行运行 web(yarn web:start)或 app(yarn app:start)进行联调 - 提交代码时 husky + commitlint 会校验提交信息规范(@commitlint/config-conventional ^11.0.0),lint-staged + prettier ^2.1.2 会在提交前格式化暂存文件
- 测试通过
jest ^26.5.3执行,配合 jest-runner-eslint ^0.10.0 可在 jest 进程中跑 lint
注意事项与常见问题
- Relay 需要单独编译步骤:无论 web 还是 app,启动前都要先执行各自的 relay 编译命令("Compile Relay"),否则 Relay 查询无法运行
- App 端对环境要求更高,README 特别提示需要先阅读 React Native 官方入门文档:"We recommend that you read https://facebook.github.io/react-native/docs/getting-started before starting"
- README 自身较薄,更多使用方式需参考作者关于 Playground 理念的 Medium 文章及仓库内代码
- 项目使用 Flow 与 TypeScript 并存的过渡配置(flow-bin ^0.136.0 与 preset-typescript 同时存在),迁移期可能存在两种类型体系
优缺点
- ✓ 前后端同仓开发联调快
- ✓ Web/App 共享 Relay 数据层
- ✕ Relay 编译步骤额外增加
- ✕ 需要阅读 React Native 官方
出处
本方案挖掘自开源项目 entria/entria-fullstack,方案内容与实施命令均来自其 README 原文。
本方案由真实开源项目挖掘整理,实施命令均来自其 README 原文,安装使用请遵循项目开源协议。