reactjs - 如何为 React SSR 和 API 构建 monorepo
问题描述
我正在尝试了解为 NodeJS/React 项目构建 monorepos 的最佳实践。
我需要:
React SPA 与服务器端渲染。
后端有 Express、MongoDB、mongoose 模块等。
一些实用功能、助手、枚举等的共享(公共)模块;
用 monorepo 构建这种架构的优雅方法是什么(我将使用 Lerna)?
- 我应该分离 API 和 SSR EXpress 服务器吗?
- 如果是,我应该将 React 前端代码与 SSR 服务器分开吗?
- 如何配置 webpack 开发环境,所以开发过程中的其他模块总是会得到“共享”模块的转译(Babel)版本(这个问题有点超出范围,可能解决方案很简单)
我知道答案主要是“视情况而定”,但我需要通用的方法,它适用于许多情况,即使它会有点过度设计。
谢谢
解决方案
好吧,是的,主要取决于:)。但是,我刚刚用自己的代码库完成了这个过渡,所以希望我能提供一些帮助。我最近使用 lerna 将 RMWC 从一个单一存储库转换为多个包。https://jamesmfriedman.github.io/rmwc/
我的回答将做出以下假设:
- 您正在单独发布您的包裹(因此 lerna)
- 正因为如此,您的各个包都被很好地组件化并且具有良好的关注点分离
- 您正在 npm 上的范围组织下发布您的包(我的是 @rmwc)。这不是必需的,但是这个特殊的设置让我完成了一些有趣的 webpack hack。如果您的公司使用私有 npm,这也是您所拥有的。
有一个 Base / Core / 或 Utils 模块
参考:https ://github.com/jamesmfriedman/rmwc/tree/master/src/base
这是一个包含所有或大部分其他模块将依赖的通用工具的单个模块。一般经验法则,如果有多个包需要它,请将其拉出到您的基本模块中,以便对其进行正确的版本控制和共享。这也将防止将来代码碎片化,因为当您更新基本模块代码时,您将需要使用它重构组件。
是的,将您的 SSR 代码分开
这只是很好的关注点分离。如果你仔细想想,React 是同构的,所以你的组件并不真正关心它们在哪里被渲染。如果没有更多关于您的代码库或您正在解决的问题的详细信息,我的直觉会告诉我只制作一个额外的 SSR / 服务器包。从依赖的角度来看,这也是有道理的。您的任何组件都不会依赖这些包,但这些包将依赖您的所有组件。
决定包装分离的一部分还与可能经常和不经常更改的内容有关。同样,高度依赖于您的问题,但是如果您的服务器或 ssr 包仅负责渲染和水合组件,则它们可能不会经常更改。
我对此没有 1:1 的参考,但我的项目中关闭的东西可能是重新导入我所有其他组件的根 rmwc 模块。https://github.com/jamesmfriedman/rmwc/tree/master/src/rmwc
Webpack 魔法
Lerna 包含一个名为“bootstrap”的方法,它神奇地安装所有依赖项并将一堆目录符号链接在一起。如果您使用的是 Typescript 或 Flow,则符号链接可能会导致问题或根本不起作用。对我来说,我创建了一个路径别名作为解决方法。
https://github.com/jamesmfriedman/rmwc/blob/master/config-overrides.js#L38
基本上,只要引用了@rmwc(我的 npm 范围),我就会将 webpack 重定向到我的 src 文件夹。这就是我受益于将它们全部置于同一范围内的地方。如果有不同的范围或包名称,您仍然可以使用以下技巧,只需指定多个别名。
我遇到的其他问题
释放!这不是直截了当的。每个包都有自己的 dist 文件,必须部署(构建 es5 代码)。解决方案,运行
lerna version
而不是lerna release
. 这使得 lerna 不会运行 npm 发布步骤。然后,您可以在每个包中都有一个自定义发布脚本。https://github.com/jamesmfriedman/rmwc/blob/master/config-overrides.js#L38版本控制:不要做独立版本。我只有轶事推理,但这让事情变得更加混乱,更难跟踪你的包的演变。毕竟,即使它是单独发布的,它仍然是一个项目,所以看到版本号一起移动是有意义的。
将您的主 package.json 文件与所有脚本一起保存在根目录中,尽可能减少其他包。根据我的项目规模,我所做的任何更改都会乘以 38 个组件。
狩猎愉快,希望对您有所帮助!
推荐阅读
- gmail-api - gmail api watch:客户端未授权使用此方法检索访问令牌,或者客户端未授权任何请求的范围
- aws-lambda - 由 SQS 触发 lambda,尝试重新排队,但未触发 lambda
- redis - 无法从 Redis 中删除密钥
- python - 无法运行具有“请求”模块的 python 脚本
- intellij-idea - Intellij 在 Linux 上以 root 身份运行配置
- python - 字典列表,比较 4 个字典值中的 3 个
- c# - 使用 ClosedXML 库将字典写入 Excel
- ruby - 在 Ruby 中使用 gnuplot 的正确方法
- sms - 使短信验证码易于复制
- javascript - 在格式化表格的脚本中编写另一个函数