反应,vite和打字稿:在不到2分钟的时间内开始
#javascript #react #nx #vite

说实话。如果您必须提供代码,那么处理工具就不会令人愉快。它应该只是工作,而不必妨碍您。因此,让我们探索如何在不到2分钟内使用Vite启动下一个React项目,而不必担心设置。

目录

1. How do I create a new project setup?
2. Running, building and testing the app
3. Building the app
4. Testing the app
5. Running integration tests with Cypress
6. Linting
7. Customize Vite and Vitest
8. Hidden gem: Caching
9. Hidden gem: Easily modularize your app
10. Hidden gem: Visualize your architecture
11. Hidden gem: Guard your boundaries
12. Hidden gem: Just run what changed
13. Hidden gem: A dedicated Editor extension
14. Hidden gem: Automated Upgrades
15. Using CRA? Automatically migrate to Vite + Nx
16. Conclusion
17. Learn more

传统上,您可能会倾向于Create-React-App (CRA)开始做到这一点。但是,如果我告诉你有更好的选择,提供

  • 不仅为初始设置进行脚手架,而且还可以帮助您生成组件,路由等
  • 自动为您提供了用于E2E测试,单元测试,代码格式和绒毛的最佳实践工具
  • 对Vite和Vitest(替代webpack&jest)有内置的支持
  • 缓存您的脚本以加快事物
  • 帮助您模块化应用程序
  • 具有自动升级功能,以保持工具常绿

我说的是Nx。 NX带有一组插件,这些插件具有代码生成能力,并帮助抽象一些低级工具设置。对于我们今天要解决的用例,这真的很有趣。

阅读器:“等一下,我听说过NX。不是Monorepos吗?”
我:“是的,你是对的。 阅读器:“独立?”
me:“是的,一个设置单个应用程序并允许一些酷模块化的奇特术语。在这里有一个视频介绍:https://youtu.be/qEaVzh-oBBchttps://youtu.be/qEaVzh-oBBc
阅读器:“哈,有趣ðÖ”

所以让我们开始设置我们的 react + vite + tyspript项目

如何创建一个新的项目设置?

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

npx create-nx-workspace@latest awesomereactapp --preset=react-standalone

Note awesomereactapp是要创建的应用程序和文件夹的名称,--preset=react-standalone告诉NX在脚手架初始设置时要使用的模板。您也可以像:
一样调用它

npx create-nx-workspace@latest awesomereactapp

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

New standalone app option when creating a new workspace

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

React + Vite setup structure

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

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

npm start

,在毫秒内,您的应用程序应在http://localhost:4200/中提供。

npm start只是调用package.json中定义的脚本:

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

在内部,这是nx serve的代表,其中serve是要调用的Nx target。您可以在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": []
}

这是您可以看到所有可用于给定项目的目标的地方,您可以add your own!简而言之,nx目标包含

  • executor-插件(@nrwl/vite)曝光的功能(dev-server)以运行手头的任务。将其视为您通常的NPM脚本的包装
  • options-这是您可以将选项传递给executor的地方
  • configurations-允许您创建options的不同版本。您可以通过通过--configuration=production标志传递到命令来控制哪种配置。另外,请注意defaultConfiguration

,如果您想在Nx docs上,您可以更深入地进行。

构建应用程序

与为我们的Web应用程序服务的方式相同,我们可以使用
构建它

npx nx build

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

测试应用程序

此设置还伴随着使用Vitest烘烤的测试。您可能猜到了,您只需按下以下测试:

npx nx test

与柏树一起运行集成测试

您可能已经注意到e2e文件夹。这是用于进行集成级别甚至完整端到端测试的Cypress的完整功能设置。

这很棒,因为您根本不必配置任何东西。无需

  • 柏树配置为使用vite(而不是webpack)
  • 为E2E项目设置绒毛(是的,写作高质量的测试代码同样重要)
  • 首先手动旋转我们的开发服务器,该服务器为我们的React应用程序提供服务,以便我们可以将其加载到柏树测试环境中

我们要做的就是使用

npx nx e2e e2e

最初可能看起来很奇怪,但是基本上,我们在e2e项目上运行e2e目标(请参见e2e/project.json)。

// 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"
        }
      }
    },
    ...
  }
}

默认情况下,这些测试以无头模式运行,但是您可以通过--watchâ与Cypress测试跑步者进行交互运行,以便每当我们更改源时测试都会重新执行。

想要柏树组件测试吗?有一个NX发电机可以帮助设置。查看文档:https://nx.dev/packages/react/generators/cypress-component-configuration

绒毛

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

npx nx lint

在工作区的根部已经有一个.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}'],
  },
});

隐藏的宝石:缓存

nx以其缓存而闻名,可帮助优化monorepos的速度。缓存获取输入(命令,源文件,环境变量...)并计算哈希。

How Caching works in Nx

在每次运行中,NX都将哈希与本地缓存文件夹进行比较。如果存在哈希,则NX将恢复命令行输出和潜在的工件(JS,CSS,...文件),由先前的运行产生。这有助于加快计算的速度,因为如果您不需要,则不运行。

有关更多信息,请参见nx文档:https://nx.dev/concepts/how-caching-works

这显然在MonorePo中很有意义,但它也可以帮助加快单个项目的工作区。大多数项目都有多个目标,例如buildtestlint。这些可以缓存!想象一下,您有一个PR,可以在其中更改一些*.spec.ts文件,因为您添加了测试或修复了一些文件。您的CI脚本可能一直运行所有目标(buildtestlint)。它应该完全这样做。但是您可以避免使用build步骤,因为您的规格文件不应影响该结果。因此,可以从缓存中恢复。 test需要运行,如果您还为Spec Files运行Linting,也可能会运行lint

您可以微调每个命令中的缓存中的内容。 More on the Nx docs

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

想象一个店面应用程序。您可能会有

之类的域名
  • 产品列表 - 它将具有列出所有当前可用产品,其评级,用户评论等的设施
  • 订单 - 用于查看当前打开的订单作为用户或浏览过去的订单。诸如下订单或触发先前获取产品的退款
  • 之类的事情
  • 付款 - 用于处理付款流,索取信用卡,触发付款以及一旦付款成功
  • 身份验证 - 处理整个注册/登录流并为应用程序中其他域区域提供较低级别的实用程序,例如访问当前用户。
  • 用户配置文件 - 管理与用户相关的所有内容。当您访问亚马逊并转到您的帐户时,请考虑一下。诸如管理您的地址
  • 之类的事情
  • ...

我们只是在这里刮擦表面。这可能会很快变得大。使用当前工具(包括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

大多数DevTools(包括CRA)都将您迫使您进入整体结构,将您的功能分为文件夹。但是,文件夹在隔离方面受到限制。随着您的应用程序的增长,这可能很快就失控了。

,我们可以通过将这些区域提取到专用的库或模块中来强加于NX。这些与您的申请并排生活。假设我们有一个名为“域”的文件夹,其中包含这些域区域。然后,您可以轻松地使用以下命令生成新库:

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

上面的命令在domains/orders/文件夹中创建了一个新的“结帐”库。这就是外观:

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

注意domains/orders/checkout/src/index.ts:这是checkout库的公共API,您可以在其中决定要导出什么以及应该在库中保留什么。选择要暴露的内容和什么不是导致更强的封装的意识过程,而不是仅仅是文件夹结构。随着应用程序的增长,它也极大地有助于可维护性方面。

生成库时,在根级tsconfig.base.json中自动创建了打字稿路径映射:

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

以这种方式,可以像
一样消耗从checkout库出口的任何东西

import { SomeComponent } from '@awesomereactapp/domains/orders/checkout';

您也可以孤立地对这些新库进行覆盖或测试:

npx nx test domains-orders-checkout

显然,缓存(如前所述)也将在这些新库中使用。

注意,domains-orders-checkout是该项目的唯一名称,由其文件结构组成。如果您愿意,可以更改domains/orders/checkout/project.json中的名称。

隐藏的宝石:可视化您的体系结构

将代码库分为库中的另一个副作用是,您的代码结构和体系结构出现并变得可见。 NX带有graph命​​令,因此您甚至可以将其可视化:

npx nx graph

Nx graph visualization of the app structure

,如果您选择“ by folder”复选框,那么域在此点可见时会变得更加有趣:

Folder grouping in Nx graph

注意,这是一个假设应用程序,用于演示NX图可视化的某些特征。其中一些连接可能只有一点意义。

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

缩放软件产品不仅仅是初始结构和模块化。它包括一个持续不断的过程,即确保模块保持形状,并且不包含任何不希望的交叉引用或循环依赖性。您可以利用NX图来视觉验证,但这不会扩展。

为此,NX具有内置的module boundary lint rule。项目可以分配“标签”,例如type:domaintype:utilstype:shareddomain:productsdomain:ordersdomain:auth。这些标签可以在project.json中分配,例如

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

请注意,type:domaindomain:products实际上只是字符串。您可以根据需要定义它们。

.eslintrc.base.json中,您可以定义规则。例如,我们在这里指出,type:utils的库只能取决于其他实用程序库,而type:domain可以依赖于两个域库,以及Ass Utility库。

// .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"]
              }
            ]
          }
        ]
      }
    }
  ]
}

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

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

隐藏的宝石:只需运行改变的东西

在这样的模块化结构(如上所示)中,您的代码在较小的模块/库中组织起来,很常见的是,给定的团队成员只能在单个域区域内工作。因此,通常PR只是触摸整个库中的一部分。 NX带有一个备份命令,该命令允许您使用所谓的“ affected commands”在CI上利用它。

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

npx nx affected:graph

Graph showing affected Nodes

仅针对受影响区域运行任务,请使用:

npx nx affected:<target>

做一个具体的示例,仅对这些项目进行测试:

npx nx affected:test

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

如果您不是“命令行界面类型”开发人员,并且您宁愿喜欢在IDE中集成的东西,那么就有好消息。 NX Core团队还发行了专用VSCODE扩展名:Nx Console

它在VSCODE中具有专用视图,用于触发通用命令,浏览工作区结构甚至在线渲染图。

NxConsole graph view

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

Nx Console context menu for generating a new things

这是一个演练视频,显示了NX控制台的一些强大功能:

隐藏的宝石:自动升级

保持工作空间常绿,荷兰语带有自动代码迁移

  • 将您的package.json软件包升级到下一个版本
  • 如有必要,可以自动更新您的配置文件
  • 如有必要,可以自动更新源文件(如果API中断更改)

,即使发生破裂的变化,这也可以平滑过渡。只是运行

npx nx migrate latest

nx收集当前安装的软件包,并将它们更新为最新版本。如果包含NX迁移脚本的软件包,则NX将其收集在migrations.json文件中。您可以检查然后运行它们。这极大地有助于使您的项目工具保持最新。

阅读更多有关文档中Nx migrations work的信息。

使用CRA?自动迁移到Vite + NX

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

npx nx init

在NX文档上阅读更多信息:https://nx.dev/recipes/adopting-nx/migration-cra

如果由于某种原因您无法迁移到Vite,则可以通过--vite=false来保持基于WebPack的设置。

结论

准备好了吗?尝试一下:

npx create-nx-workspace mycoolapp --preset=react-standalone

,让我们知道您的想法:)


了解更多

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

nx