发布于 2026-01-06 1 阅读
0

构建复杂的 React/Redux 项目

构建复杂的 React/Redux 项目

Nylas 工程团队最近更新了Nylas 控制面板,让客户团队中的每个人——从开发人员到产品经理、销售工程师、客户成功代表和财务团队——都能访问他们的 Nylas API 帐户。

在我们发表了关于在 Nylas 控制面板改版过程中提高开发人员速度的博客文章后,我们收到了一些后续请求,包括:a) 我们编写的脚手架脚本(现在可以在这里找到),以及 b) 项目的总体结构。

我们的仪表盘前端代码是一个 React/Redux 应用程序,其总体结构大致如下:

src/
  appConstants/
  components/
    DropdownMenu/
      dropDownArrow.png
      index.js
      index.test.js
      stylesheet.js
    ...
  containers/
  higherOrderComponents/
  layouts/
  models/
  modules/
  screens/
  store/
    accounts/
      actions.js
      constants.js
      endpoints.js
      reducers.js
      selectors.js
    applications/
    ...
    actions.js
    api.js
    configureStore.js
    rootReducer.js
    selectors.js
  index.css
  index.js
  registerServiceWorker.js
  Routes.js
Enter fullscreen mode Exit fullscreen mode

🙀 这里的内容很多,所以我将简要地解释一下每个目录或文件的用途。

appConstants/这里存放着所有应用范围内的常量,例如第三方服务的 API 密钥。我们最初将其命名为 `constants` constants/,但后来发现项目中其他地方还有一个用于存放常量的 Node 模块,导致了命名冲突,所以我们将其重命名为 ` appConstants/constants`。

为了更好地管理,我们将 React 组件拆分到多个目录中。最初,我们只区分了展示型组件和容器。它们之间最重要的区别在于,展示型组件是无状态的,而容器则有状态。您可以阅读这篇文章了解更多关于展示型组件和容器之间区别的信息。然而,随着组件数量的不断增加,我们需要进一步细分。最终,我们得到的目录结构如下:

  • components/- 这是展示组件的原始目录。我们的大部分展示组件仍然存放在这里。
  • containers/- 容器的原始目录。(我打赌你肯定猜不到😜)
  • higherOrderComponents/高阶组件 (HOC)是一种特殊的容器,它们实际上是函数。这些函数封装了可重用的逻辑模式,并用于包装其他组件的逻辑。例如,我们的一个 HOC 是 LazyLoaded 组件。它会在加载必要数据之前显示加载指示器,并在加载时间过长时向我们反馈。我们将所有需要这种加载行为的屏幕都通过 LazyLoaded HOC 传递,而无需在每个屏幕中重新实现该行为!💥
  • layouts/这是唯一另一个存放展示组件的目录。这些展示组件专门负责应用程序中整个页面的布局。
  • screens/屏幕是容器,它包含了特定应用程序视图的所有展示组件和子容器。我们所有的屏幕都以布局组件为基础,并从那里添加子组件。

每个组件在各自的父目录中都有自己的子目录。每个子目录中的主文件是 `<component-file>` index.js,其中存放着组件的通用定义。`<test-file>`index.test.js是我们通过脚手架脚本自动添加的测试文件。我们还将组件的所有样式都保存在这个子目录中,包括组件所需的任何图像,以及一个单独的stylesheet.js样式文件(如果样式过于庞大而无法全部放在 `<component-file>` 中)index.js。我们使用Aphrodite 库来编写 JavaScript 样式,这有助于我们将样式限制在每个组件内部,而不是隐藏在庞大的 CSS 文件中。

/models我们在这里为每个 API 对象定义了类。每个类都定义了一个对象toJSON()和一个fromJSON()方法,这使得我们在应用程序内部处理 JSON 响应时,可以将 JSON 响应转换为对象实例,并在需要将数据发送回服务器时再转换回 JSON。该项目还使用Flow作为类型检查器,将 JSON 转换为更具体的数据结构使我们能够正确地为每个字段添加类型注解。

/modules基本上,它是一个存放实用工具或辅助代码的目录。我们将密切相关的代码分组到各自的文件中,最终得到了类似errorReporter.js和 这样的模块apiRequest.js

store/这是我们所有 Redux 代码的根目录。正如我在之前的博客文章中提到的,我们将 store 分成了多个子目录,每个子目录对应一个模型。每个子目录都包含传统的 Redux 文件,例如 `<model_name>` actions.jsreducers.js`<model_name>` 和 ` selectors.js<model_name>`。此外,我们还有一个constants.js文件用于存放与该模型 store 相关的常量,以及endpoints.js与后端 API 交互的函数。在store/根目录下,我们有一些文件用于导入所有对应子目录文件中的函数:

  • actions.js从所有子actions.js文件中导入
  • api.js从所有子endpoints.js文件中导入
  • rootReducer.js合并所有子reducers.js文件
  • selectors.js导入所有子selectors.js文件

我们还有configureStore.js一个程序,用于进行初始设置,实际创建存储并可能加载任何先前保存的状态。

index.css该文件包含我们所有全局 CSS 样式。我们的大部分样式都位于组件目录中,但也有少数bodyhtml类样式存放在此文件中。

index.js只是简单地渲染我们的根 React 组件。

registerServiceWorker.js设置服务工作线程,以便我们可以从本地缓存提供资源,从而使我们的应用程序运行得更快。

Routes.js它将我们每个屏幕组件连接到一个应用程序路由。例如,我们可以在这里注册我们的组件,以便在用户访问仪表盘中的路由RegisterScreen时加载。/register

总的来说,我们努力构建项目结构,确保在处理特定部分时所有相关代码都触手可及,同时保持关注点分离。将较小的文件按模型或组件分组确实极大地提升了开发体验。未来我们可能会继续优化结构,但目前为止,这种结构对我们来说非常有效!如果您有任何疑问,或者贵公司有不同的做法,欢迎随时联系我们。


本文最初发表于Nylas Engineering 博客。

文章来源:https://dev.to/nylas/structuring-a-complex-reactredux-project-4mbg