在本文中,Nirmalya 讨论了他在构建和维护大型 Next.js 应用程序时遇到的一些复杂问题。他总是解释如何使用各种工具来解决这些问题。

维护大型应用程序始终是一项艰巨的任务。它可能具有过时的依赖性,这可能会导致可维护性问题。它还可能进行一些不稳定且无法激发任何信心的测试。大型 JavaScript 和 CSS 捆绑包也可能存在问题,导致应用程序为最终用户提供非最佳用户体验。

但是,有几种方法可以使大型代码库易于维护。在本文中,我们将讨论其中一些技术以及一些我希望早点知道的事情,以帮助管理大型 Next.js 应用程序。

注意:虽然本文特定于 Next.js,但其中一些要点也适用于各种前端应用程序。

使用 TypeScript

TypeScript 是一种强类型编程语言,这意味着它在混合不同类型的数据时强制执行一定的严格性。根据2021 年 StackOverflow 开发者调查TypeScript是开发者最想使用的语言之一。

在处理大型代码库时,使用像 TypeScript 这样的强类型语言会很有帮助。它将帮助您了解发生更改时您的应用程序是否有可能中断。不保证 TypeScript 在有可能出现中断时总是会报错。然而,大多数时候,TypeScript甚至可以在构建应用程序之前帮助您消除错误。在某些情况下,如果代码中存在类型不匹配,那么构建将会失败,因为 Next.js 在构建期间会检查类型定义。

来自Next.js 文档

默认情况下,Next.js 将在下一个构建过程中进行类型检查。我们建议在开发过程中使用代码编辑器类型检查。

请注意,next build是创建 Next.js 应用程序的优化生产版本的脚本。从我个人的经验来看,当我尝试将我的一个应用程序的Next.js 更新到版本 11 时,它对我帮助很大。作为该更新的一部分,我还决定更新一些其他软件包。借助 TypeScript 和 VSCode,我甚至在构建应用程序之前就能够确定这些重大更改的时间。


使用 Lerna 或 Nx 使用 Mono-Repo 结构

假设您正在与主要的 Next.js 应用程序一起构建一个组件库。您可能希望将库保留在单独的存储库中以添加新组件、将它们构建并作为包发布。当您想在 library 工作时,这看起来很干净并且工作正常。但是,当您想要将该库集成到 Next.js 应用程序中时,开发体验就会受到影响。

这是因为当您将组件库与 Next.js 应用程序集成时,您可能必须返回库的存储库、进行更改、发布更新,然后在 Next.js 应用程序中安装新版本。只有在此之后,组件库中的新更改才会开始反映在 Next.js 应用程序中。想象一下您的整个团队多次这样做。单独构建和发布组件库所花费的时间加起来会是一大块。

如果您使用 mono-repo 结构(其中组件库与 Next.js 应用程序一起驻留), 则可以解决此问题。在这种情况下,您只需更新组件库即可,它将立即反映在您的 Next.js 应用程序中。无需单独构建和发布组件库。

您可以使用像 next-transpile-modules这样的包,这样您甚至不需要在 Next.js 应用程序使用它之前构建组件库。但是,如果您计划将组件库作为 npm 包发布,则可能需要一个构建步骤。

为了管理 mono-repo,您 可以使用LernaNxRushTurborepoyarn 工作空间npm 工作空间等工具。当我需要配置构建管道时,我喜欢将 Lerna 与 yarn 工作区一起使用。如果您更喜欢通过 CLI 自动执行大量操作的工具,您可以看看 Nx。我觉得它们都很好,但解决的问题略有不同。


使用 Hygen 等代码生成器生成样板代码

当许多开发人员开始为大型代码库做出贡献时,很可能会出现大量重复代码。发生这种情况主要是因为需要构建一个与现有页面、组件或实用功能类似但稍作修改的页面、组件或实用功能。

您可以考虑为组件或实用函数编写单元测试用例。 您可能希望尽可能多地复制样板代码并根据新文件进行某些修改。但是,这会在代码库中添加大量包含错误变量命名的代码。这可以通过适当的代码审查过程来减少。然而,有一种更好的方法可以通过自动生成样板代码来减少这种情况。

除非您使用Nx,否则您将需要一种可以自动生成大量代码的方法。我使用Hygen生成 Redux、React 组件和实用函数的样板代码。您可以查看文档以开始使用 Hygen。他们还有一个专门的部分用于生成 Redux 样板。您还可以使用Redux Toolkit来减少 Redux 应用程序所需的样板代码。我们接下来将讨论这个包。


通过 Redux 工具包使用 Redux 等完善的模式和较小的样板

许多开发人员会认为Redux增加了代码库的复杂性,或者React Context更容易维护。我认为这主要取决于您正在构建的应用程序的类型以及整个开发团队的专业知识。您可以选择您的团队最熟悉的任何状态管理解决方案,但尽量选择不需要大量样板的解决方案。

在本文中,我提到 Redux 是因为根据 npm 趋势,它仍然是最流行的状态管理解决方案。对于 Redux,您可以使用Redux Toolkit减少大量样板代码。这是一个非常固执且强大的库,您可以使用它来简化状态管理。查看他们有关如何开始使用 Redux Toolkit 的文档。

我在构建 Next.js 应用程序时使用了 Redux、Zustand和 Redux Toolkit。我感觉 Zustand 非常简单易懂。不过,我仍然使用 Redux,以防我需要构建复杂的东西。我没有使用过XState,但它也是一个流行的选择。


使用 React Query 或 SWR 获取异步数据

大多数前端应用程序将从后端服务器获取数据并将其呈现在页面上。在 Next.js 应用程序或任何 JavaScript 应用程序中,您可以使用 Fetch APIAxios或类似库来获取数据。然而,随着应用程序的增长,管理数据的这种异步状态变得非常困难。您可以使用 Fetch 或 Axios 周围的实用函数或包装器来创建抽象,但是当多个开发人员在同一个应用程序上工作时,这些实用函数或包装器很快就会变得难以管理。您的应用程序还可能遇到缓存和性能问题。

要解决此类问题,最好使用React QuerySWR等包。这些包提供了一组开箱即用的默认配置。它们处理很多事情,例如缓存和性能,这些事情很难单独管理。这两个包都提供了一些默认配置选项,您可以使用它们根据应用程序的要求自定义它们的行为。这些包将从您的后端 API 端点获取并缓存异步数据,并使您的应用程序状态更易于维护。

我在我的项目中同时使用了 React Query 和 SWR,而且我很喜欢它们。您可以查看它们的比较和功能来决定您应该使用哪一个。


与 Husky 一起使用 Commitizen 和语义发布

如果您经常部署和发布应用程序,那么您可能会遇到版本控制问题。当您开发大型应用程序并且有多个开发人员为其做出贡献时,管理版本变得更加困难。跟踪变更日志变得非常困难。手动更新变更日志变得非常困难,并且慢慢地您的变更日志会变得过时。

您可以组合 CommitizenSemantic Release等软件包来帮助您进行版本控制和维护变更日志。这些工具可以使变更日志与特定版本中部署的变更保持同步, 从而帮助您实现部分发布流程的自动化。您可以使用 Husky等工具来确保所有贡献者都遵循既定的模式来编写提交消息并帮助您管理变更日志。


使用 Storybook 可视化 UI 组件

在大型代码库中,您的应用程序很可能由许多组件组成。其中一些组件将过时、有缺陷或不再需要。然而,在大型应用程序中跟踪这种事情是非常困难的。开发人员可能会创建新组件,其行为可能与现有组件类似,因为他们不知道以前的组件是否存在。这种情况经常发生,因为无法跟踪应用程序当前拥有哪些组件以及它们如何相互交互。

像 Storybook这样的工具将帮助您跟踪代码库当前包含的所有组件设置 Storybook非常简单,并且可以与您现有的 Next.js 应用程序集成。Next.js 有一个示例,展示了如何使用您的应用程序设置 Storybook。

我一直喜欢使用 Storybook,因为它可以帮助我的开发团队了解每个组件的行为方式以及它公开的 API。它是每个开发人员的文档来源。Storybook 还可以帮助设计人员了解所有组件和交互的行为。您还可以将Chromatic与 Storybook 一起使用来进行视觉测试并捕获每个版本期间的回归问题。

推荐阅读Building React Apps With Storybook” by Abdulazeez Adeshina

开始时就编写可维护的测试

编写测试会消耗时间。所以,许多公司往往不会投入时间来编写任何类型的测试。因此,从长远来看,应用程序可能会受到影响。随着应用程序的增长,应用程序的复杂性也会增加。在复杂的应用程序中,重构变得很困难,因为很难理解哪些文件可能会因更改而损坏。

解决这个问题的一个方法是从一开始就编写尽可能多的测试。您可以遵循测试驱动开发(或 TDD)或任何其他适合您的类似概念。 Kent C. Dodds 撰写了一篇优秀的文章《测试奖杯和测试分类》,其中讨论了您可以编写不同类型的测试。

尽管编写可维护的测试需要时间。但我认为测试对于大型应用程序非常重要,因为它让开发人员有信心重构文件。一般来说,我使用 JestReact 测试库Cypress 在我的应用程序中编写测试。


使用 Dependabot 自动更新软件包

当多个功能团队为同一个应用程序做出贡献时,其中使用的包很可能会过时。发生这种情况是因为,如果在更新软件包时发生任何重大更改,则可能需要投入大量时间来执行该更新。这可能会导致错过交付功能的最后期限。然而,从长远来看,这种做法可能会有害。使用过时的软件包可能会导致很多问题,例如安全漏洞、性能问题等。

幸运的是,像 Dependabot这样的工具可以通过自动化更新过程来帮助您的团队。Dependabot 可以配置为检查过时的软件包并根据需要经常发送更新的拉取请求。使用像 Dependabot 这样的工具帮助我更新了应用程序的依赖项。

我希望我早点知道的事情

我希望在构建 Next.js 应用程序时早点知道很多事情。然而,最重要的是转到Next.js 文档的“生产”部分本节概述了在将 Next.js 应用程序部署到生产环境之前应该实现的一些最重要的事情。在阅读本节之前,我常常随意猜测在将任何应用程序部署到生产环境之前要做什么。

在将应用程序部署到生产环境并将其交付给客户之前,请务必检查您需要支持哪些浏览器。Next.js 支持多种浏览器。但是,有必要了解您要将应用程序交付给的用户类型以及他们使用的浏览器类型。


结论

这些是我在构建和维护大型 Next.js 应用程序时学到的一些东西。其中大部分要点适用于任何前端应用程序。对于任何前端应用程序来说,首要任务始终是交付具有良好用户体验、速度快且使用起来流畅的产品。

每当我开发任何应用程序时,我都会尽力记住所有这些要点。我希望它们对您也有用!