React、Vite 和 TypeScript:2 分钟内即可上手

2025-06-07

React、Vite 和 TypeScript:2 分钟内即可上手

说实话,如果你必须交付代码,处理工具并不是一件令人愉快的事情。它应该只是工作,而不是妨碍工作。所以,让我们探索如何在 2 分钟内使用 Vite 启动你的下一个 React 项目,而无需担心设置。

目录

 1.如何创建新的项目设置?
 2.运行、构建和测试应用程序
 3.构建应用程序
 4.测试应用程序
 5.使用 Cypress 运行集成测试
 6.代码检查
 7.自定义 Vite 和 Vitest
 8.隐藏的精华:缓存
 9.隐藏的精华:轻松模块化您的应用程序
 10.隐藏的精华:可视化您的架构
 11.隐藏的精华:守护您的边界
 12.隐藏的精华:只运行更改的内容
 13.隐藏的精华:专用的编辑器扩展
 14.隐藏的精华:自动升级
 15.使用 CRA?自动迁移到 Vite + Nx
 16.结论
 17.了解更多

传统上,你可能倾向于使用Create-React-App (CRA)来实现这一点。但如果我告诉你还有更好的选择,那就是提供

  • 不仅仅是初始设置的脚手架,还可以帮助您生成组件、路由等
  • 自动为你设置用于端到端测试、单元测试、代码格式化和 linting 的最佳实践工具
  • 内置对 Vite 和 Vitest 的支持(或者 Webpack 和 Jest)
  • 缓存脚本以加快速度
  • 帮助您模块化您的应用程序
  • 配备自动升级功能,让您的工具保持常青

我指的是Nx。Nx附带一组插件,这些插件具有代码生成功能,并有助于抽象一些底层工具的设置。这对于我们今天要处理的用例来说可能非常有趣。

读者: “等一下,我听说过 Nx。那不是 Monorepos 吗?”
我: “是的,你说得对。但在 15.3 版本中,他们引入了一种叫做‘独立应用’的功能。”
读者: “独立应用?”
我: “是啊,一个很花哨的术语,指的是设置单个应用,允许进行一些很酷的模块化。这里有一个介绍这个功能的视频:https://youtu.be/qEaVzh-oBBc
读者: “哈哈,有意思🤔”

那么让我们开始设置我们的React + Vite + TypeScript 项目

如何创建新的项目设置?

要建立一个新项目,只需调用以下命令:

npx create-nx-workspace@latest awesomereactapp --preset=react-standalone
Enter fullscreen mode Exit fullscreen mode

注意:awesomereactapp这是正在创建的应用程序和文件夹的名称,它--preset=react-standalone告诉 Nx 在构建初始设置时要使用哪个模板。您也可以像这样调用它:

npx create-nx-workspace@latest awesomereactapp
Enter fullscreen mode Exit fullscreen mode

然后在终端提示中选择您喜欢的选项:

创建新工作区时的新独立应用程序选项

最后,您将获得以下结构:

React + Vite 设置结构

运行、构建和测试应用程序

首先,让我们运行我们新的、闪亮的应用程序。只需调用

npm start
Enter fullscreen mode Exit fullscreen mode

只需几毫秒,您的应用程序就会在http://localhost:4200/上提供服务。

npm start仅调用以下定义的脚本package.json

// package.json
{
  "name": "awesomereactapp",
  ...
  "scripts": {
    "start": "nx serve",
    "build": "nx build",
    "test": "nx test"
  }
  ...
}
Enter fullscreen mode Exit fullscreen mode

在内部,它委托给nx serve,其中Nxserve要调用的目标project.json。您可以在 中找到它们:

// project.json
{
  "name": "awesomereactapp",
  "$schema": "node_modules/nx/schemas/project-schema.json",
  "sourceRoot": "./src",
  "projectType": "application",
  "targets": {
    "build":  {...},
    "serve": {
      "executor": "@nrwl/vite:dev-server",
      "defaultConfiguration": "development",
      "options": {
        "buildTarget": "awesomereactapp:build"
      },
      "configurations": {
        "development": {
          "buildTarget": "awesomereactapp:build:development",
          "hmr": true
        },
        "production": {
          "buildTarget": "awesomereactapp:build:production",
          "hmr": false
        }
      }
    },
    "test": {...},
    "lint": {...}
  },
  "tags": []
}
Enter fullscreen mode Exit fullscreen mode

在这里,您可以查看特定项目的所有可用目标,并可以添加您自己的目标!简而言之,Nx 目标包含

  • executordev-server-插件(此处)公开的函数(此处@nrwl/vite),用于运行当前任务。可以将其视为常用 Npm 脚本的包装器。
  • options- 您可以在此处将选项传递给executor
  • configurations- 允许您创建不同版本的options。您可以通过将标志传递--configuration=production给命令来控制使用哪个配置。另请注意defaultConfiguration

如果您愿意,可以更深入地了解Nx 文档

构建应用程序

就像服务我们的 Web 应用程序一样,我们可以使用

npx nx build
Enter fullscreen mode Exit fullscreen mode

这会将输出放入dist文件夹中。既然我们已经了解了project.json目标,您可能已经猜到可以直接在这些设置中自定义该输出文件夹。

测试应用程序

此设置还附带使用Vitest进行测试。您可能已经猜到了,您可以按如下方式运行测试:

npx nx test
Enter fullscreen mode Exit fullscreen mode

使用 Cypress 运行集成测试

你可能注意到了这个文件夹。里面是Cypresse2e的完整设置,可用于进行集成级甚至完整的端到端测试。

这非常好,因为你根本不需要配置任何东西。不需要

  • Cypress 配置为使用 Vite(而不是 Webpack)
  • 为 e2e 项目设置 linting(是的,编写高质量的测试代码同样重要)
  • 首先手动启动我们的开发服务器,为我们的 React 应用程序提供服务,以便我们可以将其加载到我们的 Cypress 测试环境中

我们需要做的就是使用

npx nx e2e e2e
Enter fullscreen mode Exit fullscreen mode

这乍一看可能很奇怪,但基本上,我们在项目上运行e2e目标(参见e2e/project.jsone2e

// e2e/project.json
{
  "name": "e2e",
  "$schema": "../node_modules/nx/schemas/project-schema.json",
  "sourceRoot": "e2e/src",
  "projectType": "application",
  "targets": {
    "e2e": {
      "executor": "@nrwl/cypress:cypress",
      "options": {
        "cypressConfig": "e2e/cypress.config.ts",
        "devServerTarget": "awesomereactapp:serve:development",
        "testingType": "e2e"
      },
      "configurations": {
        "production": {
          "devServerTarget": "awesomereactapp:serve:production"
        }
      }
    },
    ...
  }
}
Enter fullscreen mode Exit fullscreen mode

默认情况下,这些测试以无头模式运行,但您可以--watch 通过 Cypress 测试运行器以交互方式运行它,以便在我们更改源时重新执行测试。

想要测试 Cypress 组件?Nx 生成器可以帮助您完成设置。查看文档:https://nx.dev/packages/react/generators/cypress-component-configuration

代码检查

类似地,可以通过运行以下命令来触发 linting:

npx nx lint
Enter fullscreen mode Exit fullscreen mode

.eslintrc.json工作区的根目录中已经有一个文件,其中包含一些最佳实践规则。

定制 Vite 和 Vitest

项目设置方式让您可以轻松自定义ViteVitest 的设置。只需打开工作区根目录下的预生成文件vite.config.ts,添加自定义 Vite 插件或微调 Vitest 即可。

/// <reference types="vitest" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
  server: {
    port: 4200,
    host: 'localhost',
  },
  plugins: [
    react(),
    viteTsConfigPaths({
      root: './',
    }),
  ],

  // vitest config
  test: {
    globals: true,
    cache: {
      dir: './node_modules/.vitest',
    },
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
  },
});

Enter fullscreen mode Exit fullscreen mode

隐藏的宝石:缓存

Nx 以其缓存功能而闻名,这有助于优化 Monorepos 的速度。缓存功能接收输入(命令、源文件、环境变量……)并计算哈希值。

Nx 中的缓存工作原理

每次运行时,Nx 都会将该哈希值与本地缓存文件夹进行比较。如果哈希值存在,Nx 会恢复上次运行产生的命令行输出和潜在文件(JS、CSS 等)。这有助于加快计算速度,因为如果不需要,您可以不运行它。

有关详细信息,请参阅 Nx 文档:https://nx.dev/concepts/how-caching-works

虽然这在 monorepo 中显然很有意义,但它也可以帮助加快单项目工作区的速度。大多数项目都有多个目标,例如build、、testlint这些都可以缓存!想象一下,您有一个 PR,*.spec.ts因为您添加了测试或修复了某些文件而更改了某些文件。您的 CI 脚本可能一直运行所有目标(build、、)。它完全应该这样做。但您可以避免这一步test因为您的 spec 文件不应该影响该结果。因此,它可以从缓存中恢复。需要运行,并且如果您对 spec 文件运行 linting,也可能需要运行。lintbuildtestlint

您可以微调每个命令的缓存内容。更多信息请参阅 Nx 文档

隐藏的宝石:轻松模块化您的应用程序

想象一下一个店面应用程序。你可能会有如下域名区域:

  • 产品列表——可以列出所有当前可用的产品、其评级、用户评论等。
  • 订单 - 用于查看您当前未结订单或浏览过往订单。例如,下单或触发已购商品的退款。
  • 付款 - 用于处理付款流程、索取信用卡、触发付款以及在付款成功后启动订单流程
  • 身份验证 - 处理整个注册/登录流程并为应用程序中的其他域区域提供低级实用程序,例如获取当前用户的访问权限。
  • 用户资料 - 管理所有与用户相关的内容。当你访问亚马逊并进入你的账户时,可以想象一下它。例如管理你的地址
  • ...

我们只是触及了皮毛。它很快就会变得庞大。使用当前工具(包括 CRA)管理此类结构的唯一方法是将这些域组织到文件夹中。因此,在 CRA 设置中,您将看到类似以下内容:

cra-app
  ├─ public/
  ├─ src/
  │   ├─ authentication/
  │   │  ├─ current-user/
  │   │  │   ├─ ...
  │   │  │   └─ index.ts
  │   │  ├─ login/
  │   │  └─ signup/
  │   ├─ orders/
  │   │   ├─ checkout/
  │   │   ├─ place-order/
  │   │   ├─ refund/
  │   │   └─ order-list/
  │   ├─ payments/
  │   ├─ products/
  │   ├─ user-profile/
  │   │   ├─ addresses/
  │   │   └─ credit-cards/
  │   ├─ App.css
  │   ├─ App.tsx
  │   ...
  ├─ package-lock.json
  ├─ package.json 
  └─ README.md
Enter fullscreen mode Exit fullscreen mode

大多数开发者工具(包括 CRA)都会强制你使用单体架构,将功能划分到不同的文件夹中。然而,文件夹的隔离性有限;随着应用程序的增长,这种架构很快就会失控。

我们可以通过将这些领域提取到专用库或模块中,使用 Nx 构建一个不同的、更强大的结构。这些库或模块与您的应用程序并存。假设我们有一个名为“domains”的文件夹,其中包含这些领域区域。然后,您可以使用以下命令轻松生成一个新的库:

npx nx g @nrwl/react:lib checkout --directory=domains/orders/checkout --bundler=none
Enter fullscreen mode Exit fullscreen mode

上述命令会在domains/orders/文件夹中创建一个新的“checkout”库。它如下所示:

awesomereactapp
├─ public
│  └─ favicon.ico
├─ src
│  ├─ app
│  ├─ ...
├─ domains
│  └─ orders
│     └─ checkout
│        ├─ src
│        │  ├─ index.ts
│        │  └─ lib
│        │     ├─ domains-orders-checkout.module.css
│        │     ├─ domains-orders-checkout.spec.tsx
│        │     └─ domains-orders-checkout.tsx
│        ├─ tsconfig.json
│        ├─ tsconfig.lib.json
│        ├─ tsconfig.spec.json
│        └─ vite.config.ts
├─ ... 
├─ index.html
├─ package-lock.json
├─ package.json
├─ ...
├─ tsconfig.app.json
├─ tsconfig.base.json
├─ tsconfig.json
├─ tsconfig.spec.json
└─ vite.config.ts
Enter fullscreen mode Exit fullscreen mode

请注意domains/orders/checkout/src/index.ts:这是库的公共 API checkout,您可以决定哪些内容需要导出,哪些内容需要在库内保持私有。这种有意识地选择哪些内容需要公开、哪些内容需要隐藏的过程,比单纯的文件夹结构更能实现更强的封装性。随着应用规模的增长,它还能极大地提升可维护性。

生成库时,会在根级别自动创建 TypeScript 路径映射tsconfig.base.json

{
  "compileOnSave": false,
  "compilerOptions": {
    ...
    "paths": {
      "@awesomereactapp/domains/orders/checkout": [
        "domains/orders/checkout/src/index.ts"
      ]
    }
  },
  "exclude": ["node_modules", "tmp"]
}
Enter fullscreen mode Exit fullscreen mode

通过这种方式,从库中导出的任何东西都checkout可以被使用,就像

import { SomeComponent } from '@awesomereactapp/domains/orders/checkout';
Enter fullscreen mode Exit fullscreen mode

您还可以针对这些新库单独运行 linting 或测试:

npx nx test domains-orders-checkout
Enter fullscreen mode Exit fullscreen mode

显然,缓存(如前所述)也适用于这些新库。

注意,是项目的唯一名称,由其文件结构组成。您可以根据需要domains-orders-checkout更改名称。domains/orders/checkout/project.json

隐藏的宝石:可视化你的架构

将代码库拆分成库的另一个好处是,代码结构和架构会清晰可见。Nx 内置了一个graph命令,你甚至可以将其可视化:

npx nx graph
Enter fullscreen mode Exit fullscreen mode

应用程序结构的 Nx 图形可视化

如果您选中“按文件夹分组”复选框,事情就会变得更加有趣,因为此时域就会变得可见:

Nx 图中文件夹分组

请注意,这是一个假设的应用程序,用于演示 Nx 图形可视化的一些功能。其中一些关联可能难以理解。

隐藏的宝石:守护你的界限

软件产品的扩展不仅仅是最初的结构化和模块化。它包含一个持续不断的过程,确保模块保持良好状态,并且不包含任何不必要的交叉引用或循环依赖。您可以利用 Nx 图来直观地验证这一点,但这无法扩展。

为了解决这个问题,Nx 内置了模块边界 lint 规则。可以为项目分配“标签”,例如,,,和type:domain,,type:utils这些标签可以在 中分配,例如type:shareddomain:productsdomain:ordersdomain:authproject.json

// 
{
  // ... more project configuration here
  "tags": ["domain:products", "type:domain"]
}
Enter fullscreen mode Exit fullscreen mode

注意,type:domaindomain:products实际上只是字符串。你可以随意定义它们。

然后,您可以在 中.eslintrc.base.json定义规则。例如,我们在这里规定 的库type:utils只能依赖于其他实用程序库,而type:domain可以同时依赖于其他领域库和实用程序库。

// .eslintrc.base.json
{
  "overrides": [
    {
      "rules": {
        "@nrwl/nx/enforce-module-boundaries": [
          "error",
          {
            "depConstraints": [
              {
                "sourceTag": "type:utils",
                "onlyDependOnLibsWithTags": ["type:utils"]
              },
              {
                "sourceTag": "type:domain",
                "onlyDependOnLibsWithTags": ["type: domain", "type:utils"]
              },
              {
                "sourceTag": "domain:products",
                "onlyDependOnLibsWithTags": ["domain:products", "domain:orders"]
              }
            ]
          }
        ]
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

如果需要遵循其中一些 lint 规则,您的编辑器将在您的代码中正确显示它,并且您还可以在 CI 上为每个 PR 运行 lint 检查。

如果您感兴趣,可以在这里阅读更多内容:https://blog.nrwl.io/mastering-the-project-boundaries-in-nx-f095852f5bf4

隐藏的宝石:只需运行更改的内容

在这种模块化结构(如上所示)中,您的代码被组织成更小的模块/库,团队成员通常只在单个领域内工作。因此,PR 通常只涉及整个库集的一个子集。Nx 附带一个内置命令,允许您在 CI 中使用所谓的“受影响的命令”来利用此功能。

假设我们对product-detail应用程序的库进行了更改。这将影响所有依赖该库的其他库。您也可以通过运行以下命令来可视化它:

npx nx affected:graph
Enter fullscreen mode Exit fullscreen mode

显示受影响节点的图表

要仅为受影响的区域运行任务,请使用:

npx nx affected:<target>
Enter fullscreen mode Exit fullscreen mode

举一个具体的例子,只针对这些项目运行测试:

npx nx affected:test
Enter fullscreen mode Exit fullscreen mode

隐藏的宝石:专用的编辑器扩展

如果您不是“命令行界面类型”的开发人员,并且更喜欢在 IDE 中集成某些功能,那么有个好消息。Nx 核心团队还发布了一个专用的 VSCode 扩展:Nx Console

它在 VSCode 中有一个专用视图来触发常用命令、浏览工作区结构甚至内联渲染图形。

NxConsole 图形视图

它还带有上下文菜单,可以快速访问大多数常用功能:

Nx 控制台上下文菜单用于生成新事物

以下演示视频展示了 Nx Console 的一些强大功能:

隐藏的宝石:自动升级

为了保持工作空间的常青,Nx 配备了自动代码迁移功能,

  • 升级你的package.json软件包到下一个版本
  • 如果需要可以自动更新您的配置文件
  • 必要时可以自动更新源文件(如果 API 发生重大变化)

即使发生重大变更,也能实现平稳过渡。只需运行

npx nx migrate latest
Enter fullscreen mode Exit fullscreen mode

Nx 会收集当前安装的软件包并将其更新到最新版本。如果软件包附带 Nx 迁移脚本,Nx 会将它们收集到一个migrations.json文件中。您可以检查并运行这些脚本。这极大地有助于保持项目工具的更新。

阅读文档以了解有关Nx 迁移如何工作的更多信息。

使用 CRA?自动迁移至 Vite + Nx

如果您当前使用的是CRA设置,则可以通过在 CRA 项目中运行以下命令轻松迁移到基于 Nx + React + Vite 的设置:

npx nx init
Enter fullscreen mode Exit fullscreen mode

阅读更多 Nx 文档:https://nx.dev/recipes/adopting-nx/migration-cra

如果由于某种原因您暂时无法迁移到 Vite,您可以--vite=false暂时保留基于 Webpack 的设置。

结论

准备好了吗?尝试一下:

npx create-nx-workspace mycoolapp --preset=react-standalone
Enter fullscreen mode Exit fullscreen mode

让我们知道您的想法:)


了解更多

此外,如果您喜欢这个,请单击❤️并确保在 Twitter 上关注JuriNx以获取更多信息!

# nx

文章来源:https://dev.to/nx/react-vite-and-typescript-get-started-in-under-2-minutes-56f
PREV
RxJS Best Practices
NEXT
通过 HTTP/HTTPS 管道服务器在每个设备之间进行数据流传输