惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Hacker News: Front Page
S
Secure Thoughts
N
News | PayPal Newsroom
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Threatpost
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
A
Arctic Wolf
Cisco Talos Blog
Cisco Talos Blog
V2EX - 技术
V2EX - 技术
L
LINUX DO - 热门话题
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Proofpoint News Feed
TaoSecurity Blog
TaoSecurity Blog
N
News and Events Feed by Topic
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
NISL@THU
NISL@THU
H
Heimdal Security Blog
Webroot Blog
Webroot Blog
Martin Fowler
Martin Fowler
The Hacker News
The Hacker News
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
Stack Overflow Blog
Stack Overflow Blog
B
Blog RSS Feed
Vercel News
Vercel News
Blog — PlanetScale
Blog — PlanetScale
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
Cyberwarzone
Cyberwarzone
小众软件
小众软件
V
V2EX
K
Kaspersky official blog
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
Cisco Blogs
S
Schneier on Security
Recorded Future
Recorded Future
阮一峰的网络日志
阮一峰的网络日志
AI
AI
Microsoft Security Blog
Microsoft Security Blog
H
Help Net Security
Simon Willison's Weblog
Simon Willison's Weblog
I
InfoQ
G
Google Developers Blog
博客园_首页
Hugging Face - Blog
Hugging Face - Blog

Nx Blog

Sharing Tailwind CSS Styles Across Apps in a Monorepo | Nx Blog How SiriusXM Stays Competitive by Iterating and Getting to Market Fast | Nx Blog Agentic Experience Is the New Developer Experience | Nx Blog Nx Joins the Linux Foundation and the Agentic AI Foundation | Nx Blog A Monorepo Is NOT a Monolith | Nx Blog Why we deleted (most of) our MCP tools | Nx Blog Teach Your AI Agent How to Work in a Monorepo | Nx Blog How Broadcom stays efficient and nimble with monorepos | Nx Blog Why Monorepos are King in the Age of AI | Nx Blog Nx 2026 Roadmap: Expanding Agent Autonomy, Improving Performance, Better Polyglot and More | Nx Blog End to End Autonomous AI Agent Workflows with Nx | Nx Blog Autonomous Agents at Scale | Nx Blog Scaling 700+ Projects: How Nx Became a 'No-Brainer' for Caseware | Nx Blog Configure Tailwind v4 with Angular in an Nx Monorepo | Nx Blog The Missing Multiplier for AI Agent Productivity | Nx Blog A Year of Nx Webinars | Nx Blog Wrapping Up 2025 | Nx Blog Nx 22.3 Release: Angular 21 Support, tsgo Compiler, and Prettier v3 | Nx Blog Nx Cloud Release: Agent Resource Usage | Nx Blog Nx Platform Outperforms DIY Cache by 5x | Nx Blog An Nx Carol: Past, Present, and Future of Your Monorepo | Nx Blog Nx 22.1 Release: Terminal UI on Windows, Storybook 10, Vitest 4, and more! | Nx Blog The Compounding Effect: How Nx Features Multiply Performance Gains | Nx Blog 10 Monorepo Myths Debunked: Separating Fact from Fiction | Nx Blog Nx Cloud Release: Enterprise Task Analytics | Nx Blog Watch and Rebuild Storybook Dependencies with Nx | Nx Blog Book - React for Enterprise: Timeless Architecture for Enterprise Apps | Nx Blog Beyond Remote Cache: Unlock 70% More CI Performance | Nx Blog Nx 22 Release: Expanding the build platform | Nx Blog What's the Point of Generating All This Code If You Can't Merge It? | Nx Blog What's New in Nx Self-Healing CI | Nx Blog Nx Highlights: Smarter AI integration, all-new graph UI, and big new versions of your favorite tools | Nx Blog Making the Case for Smarter Monorepos, and How to Not Get Fooled by Myths | Nx Blog Integrating Biome in 20 Minutes | Nx Blog S1ngularity - What Happened, How We Responded, What We Learned | Nx Blog Stop Babysitting Your PRs: Self-Healing CI Cuts Time to Green by 50% | Nx Blog UKG Unifies Their Codebase and Eliminates CI Overhead to Focus on Customer Value | Nx Blog How Git Worktrees Changed My AI Agent Workflow | Nx Blog Nx Cloud Workspace Graph: See Your Organization's Code Structure Like Never Before | Nx Blog Seamless Java Deployment in Nx Using Docker | Nx Blog Getting Mobile Into Your Monorepo: Android + Nx | Nx Blog Polyglot Projects Made Easy: Integrating Spring Boot into an Nx Workspace | Nx Blog The Journey of the Nx Plugin for Gradle: From Prototype to Production | Nx Blog Combining Predictability and Intelligence With Nx Generators and AI | Nx Blog A New UI For The Humble Terminal | Nx Blog Continuous tasks are a huge DX improvement | Nx Blog New and Improved Module Federation Experience with Nx | Nx Blog A New UI for Nx Migration | Nx Blog Custom Task Runners and Self-Hosted Caching Changes | Nx Blog Enterprise Angular Monorepo Patterns | Nx Blog Using Rspack with Angular | Nx Blog Angular Architecture Guide To Building Maintainable Applications at Scale | Nx Blog Modern Angular Testing with Nx | Nx Blog Nx Update: 20.5 | Nx Blog Are Monorepos the Answer to Better AI-Assisted Development? | Nx Blog Making Cursor Smarter with an MCP Server For Nx Monorepos | Nx Blog React Development for 2025 | Nx Blog Using Apollo GraphQL in an Nx Workspace | Nx Blog Angular State Management for 2025 | Nx Blog Tailoring Nx for Your Organization | Nx Blog Nx Cloud Pipelines Come To Nx Console | Nx Blog Define the relationship with monorepos | Nx Blog See your affected project graph in Nx Cloud | Nx Blog Handling CORS In Your Workspace | Nx Blog Improve your architecture and CI pipeline times with Nx projects | Nx Blog Announcing Nx 20 | Nx Blog Introducing Nx Powerpack | Nx Blog Nx 19.5 is here! Stackblitz, Bun, Incremental Builds for Vite, Gradle Test Atomizer | Nx Blog Introducing Explain with AI | Nx Blog Nx Enterprise Podcast Episode 2: Tine Kondo | Nx Blog Monorepos and CI can be a Mess - Here's How Nx and Nx Cloud Fixed It | Nx Blog Nx Enterprise Podcast Episode 1: Hicham El Hammouchi | Nx Blog Nx 19.0 Release!! | Nx Blog Manage Your Gradle Project using Nx | Nx Blog Making the Argument for Monorepos | Nx Blog Reliable CI. A new execution model fixing both flakiness and slowness | Nx Blog Monorepos - Why Speed Matters | Nx Blog Nx Agents Walkthrough: Effortlessly Fast CI Built for Monorepos | Nx Blog Launch Nx Week Recap | Nx Blog Versioning and Releasing Packages in a Monorepo | Nx Blog Fast, Effortless CI | Nx Blog Introducing @nx/nuxt Enhanced Nuxt.js Support in Nx | Nx Blog What if Nx Plugins Were More Like VSCode Extensions | Nx Blog Monorepos: the Benefits, Challenges, and Importance of Tooling Support | Nx Blog Nx — Highlights of 2023 | Nx Blog Nx 17.2 Update | Nx Blog Unit Testing Expo Apps With Jest | Nx Blog Nx Docs AI Assistant | Nx Blog State Management Nx React Native/Expo Apps with TanStack Query and Redux | Nx Blog Nx 17 has Landed | Nx Blog Nx Conf 2023 — Recap | Nx Blog Nx Raises $16M Series A | Nx Blog Introducing Playwright Support for Nx | Nx Blog Nx 16.8 Release!!! | Nx Blog Step-by-Step Guide to Creating an Expo Monorepo with Nx | Nx Blog Qwikify your Development with Nx | Nx Blog Create Your Own create-react-app CLI | Nx Blog Storybook Interaction Tests in Nx | Nx Blog Evergreen Tooling — More than Just CodeMods | Nx Blog A Practical Guide on Effective AI Use - AI as Your Peer Programmer | Nx Blog
React, Vite and TypeScript: Get started in under 2 minutes | Nx Blog
Juri Strumpflohner · 2023-01-13 · via Nx Blog

Let's be honest. Dealing with tooling is not something enjoyable if you have to deliver code. It should just work and not be in the way. So let's explore how to kickstart your next React project using Vite, in under 2 minutes, without worrying about the setup.

Table of Contents

· How do I create a new project setup?
· Running, building and testing the app
· Building the app
· Testing the app
· Running integration tests with Cypress
· Linting
· Customize Vite and Vitest
· Hidden gem: Caching
· Hidden gem: Easily modularize your app
· Hidden gem: Visualize your architecture
· Hidden gem: Guard your boundaries
· Hidden gem: Just run what changed
· Hidden gem: A dedicated Editor extension
· Hidden gem: Automated Upgrades
· Using CRA? Automatically migrate to Vite + Nx
· Conclusion

Traditionally, you might lean towards Create-React-App (CRA) started to do precisely that. But what if I told you there's a better alternative, providing

  • not just scaffolding for the initial setup but helping you along the way to generate components, routing, etc
  • automatically sets you up with best practices tools for e2e testing, unit testing, code formatting, and linting
  • has built-in support for Vite and Vitest (alternatively Webpack & Jest)
  • caches your scripts to speed up things
  • helps you modularize your application
  • comes with automated upgrade features to keep your tooling evergreen

I'm talking about Nx. Nx comes with a set of plugins that come with code generation abilities and help abstract some of the lower-level tooling setups. And this can be really interesting for the use case we wanna tackle today.

Reader: "Wait a minute, I heard about Nx. Isn't that for monorepos?"Me: _"Yeah you're right. But in 15.3 they introduced something called 'standalone apps'"
Reader: "Standalone?"
Me: "Yeah, a fancy term for a setting up a single app and allows for some cool modularization. There's a video introducing that feature here: https://youtu.be/qEaVzh-oBBc"
_Reader: "ha, interesting 🤔"

So let's go and set up our React + Vite + TypeScript project.

How do I create a new project setup?

To set up a new project, just invoke the following command:

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

Note awesomereactapp is the name of the app and folder being created, and --preset=react-standalone tells Nx which template to use when scaffolding the initial setup. You can also invoke it like:

npx create-nx-workspace@latest awesomereactapp

And then choose the option you prefer in the terminal prompt:

In the end, what you'll get is the following structure:

Running, building and testing the app

First off, let's run our new, shiny application. Just invoke

And in a matter of milliseconds, your app should be served at http://localhost:4200/.

npm start just invokes the script defined in the package.json:

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

Internally this delegates to nx serve, where serve is the Nx target to be invoked. You can find those in the 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": []
}

This is where you can see all the targets available for a given project, and you can add your own! In a Nutshell, an Nx target contains

  • executor - a function (here dev-server) exposed by the plugin (here @nrwl/vite) to run the task at hand. Think of it as the wrapper of your usual Npm scripts
  • options - this is where you can pass options to the executor
  • configurations - allows you to create different versions of the options . You control which configuration is used by passing it via the --configuration=production flag to your commands. Also, note the defaultConfiguration.

You can go more in-depth if you want on the Nx docs.

Building the app

Just in the same way as serving our web app, we can build it with

This places an output into a dist folder. Now that we've seen the project.json targets, you probably guessed that you could customize that output folder directly in those settings.

Testing the app

This setup also comes with testing baked in using Vitest. And you probably guessed it, you can just run tests as follows:

Running integration tests with Cypress

You might have noticed the e2e folder. That's a fully-functioning setup of Cypress for doing integration-level or even full end-to-end tests.

This is excellent because you don't have to configure anything at all. No need to

  • Cypress configured to use Vite (instead of Webpack)
  • set up linting for the e2e project (yes writing good quality test code is just as important)
  • spinning up our development server manually first that serves our React app such that we can load it in our Cypress tests environment

All we need to do is to use

This might look weird initially, but basically, we run the e2e target (see e2e/project.json) on the e2e project.

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

By default, these tests run in headless mode, but you can pass --watch to run it interactively with the Cypress test runner such that the tests get re-executed whenever we change our source.

Want Cypress Component testing? There's an Nx generator that can help set that up. Check out the docs: /nx-api/react/generators/cypress-component-configuration

Linting

And similarly, linting can be triggered by running the following command:

There's a .eslintrc.json file already at the workspace's root that contains some best practices rules.

Customize Vite and Vitest

The project setup is made in a way that you can easily customize your Vite and Vitest setup. Just open the pre-generated vite.config.ts at the root of your workspace and add custom Vite plugins or fine-tune 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 is known for its caching that helps optimize the speed in monorepos. Caching takes the inputs (the command, source files, environment variables…) and computes a hash.

On every run, Nx compares that hash against a local cache folder. If the hash exists, Nx restores the command line output and potential artifacts (JS, CSS,… files) produced by a previous run. This helps speed up computation because you don't run it if you don't need to.

See Nx the docs for more info: /concepts/how-caching-works

While this obviously makes a lot of sense in a monorepo, it can also help speed up single-project workspaces. Most projects have multiple targets, such as build, test, lint. These can be cached! Imagine you have a PR where you change some *.spec.ts files because you add a test or fix some. Your CI script probably runs all the targets (build, test, lint) all the time. And it should totally do that. But you could avoid the build step because your spec file should not influence that outcome. As such, it could be restored from the cache. test needs to run and potentially also lint if you run linting also for spec files.

You can fine-tune what goes into the cache for each command. More on the Nx docs

Imagine a storefront application. You will probably have domain areas like

  • Product list — which would have facilities for listing all currently available products, their ratings, user reviews etc
  • Orders — for viewing your currently open orders as a user or browsing past orders. Things like placing a new order or triggering a refund on a previously acquired product
  • Payments — for handling the payment flow, asking for the credit card, triggering the payment, and starting the order placement process once the payment is successful
  • Authentication — which handles the whole signup/login flow and provides lower-level utilities for other domain areas in the app, like getting access to the current user.
  • User Profile — which manages everything user related. Think of it when you access Amazon and go to your account. Things like managing your addresses

We're just scratching the surface here. This can become big quickly. The only way to manage such a structure with the current tooling (including CRA) is to organize these domains in folders. So you'd have something like this in a CRA setup:

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

Most devtools (including CRA) force you into a monolithic structure, where you divide your features into folders. Folders are limited in terms of isolation, though; as your application grows, this might quickly go out of hand.

We can impose a different, stronger structure with Nx by extracting these areas into dedicated libraries or modules. These live side-by-side with your application. Let's say we have a folder named "domains" which contains these domain areas. Then you can easily generate a new library with the following command:

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

The above command creates a new " checkout " library in the domains/orders/ folder. Here's what it looks like:

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

Notice the domains/orders/checkout/src/index.ts: this is the public API of the checkout library where you can decide what to export and what should remain private within the library. This conscious process of selecting what to expose and what not leads to a much stronger encapsulation than just a folder structure. It also greatly helps with the maintainability aspect as your app grows.

When generating the library, a TypeScript path mapping is automatically created in the root-level tsconfig.base.json:

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

In this way, anything that's being exported from the checkout library can be consumed like

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

You can also just run linting or testing in isolation for these new libraries:

npx nx test domains-orders-checkout

And obviously, caching (as seen previously) would work on these new libraries as well.

Note, _domains-orders-checkout_ is the unique name of the project, composed by its file structure. You can change the name in the _domains/orders/checkout/project.json_ if you'd like.

Another side-effect of splitting up your codebase into libraries is that your code structure and architecture emerge and becomes visible. Nx comes with a graph command built-in, so you can even visualize it:

It becomes even more interesting if you select the "Group by folder" checkbox as the domains become visible at that point:

Note this is a hypothetical app to demo some of the features of the Nx graph visualization. Some of the connections might only make a little sense.

Scaling a software product is more than just the initial structuring and modularization. It consists of a constant ongoing process of ensuring modules stay in shape and don't contain any undesired cross-references or circular dependencies. You could leverage the Nx graph to verify that visually, but that doesn't scale.

To help with that, Nx has a built-in module boundary lint rule. Projects can be assigned "tags", like type:domain, type:utils, type:shared and domain:products, domain:orders, domain:auth. These tags can be assigned in the project.json, like

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

Note that _type:domain_ or _domain:products_ are really just strings. You can define them however you want.

In the .eslintrc.base.json you can then define the rules. Here for instance we're stating that a library of type:utils can only depend on other utility libraries, while a type:domain can depend on both, other domain libraries as well as utility libraries.

{
  "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"]
              }
            ]
          }
        ]
      }
    }
  ]
}

If some of these lint rules need to be followed, your editor will show it right in your code, and you can also run lint checks for each PR on CI.

If you're curious, you can read more here.

In such a modular structure (as shown above) where your code is organized in smaller modules/libraries, it is very common that a given team member just works within a single domain area. Hence, very often PRs just touch a subset of the entire set of libraries. Nx comes with a backed-in command that allows you to take advantage of that on CI, using the so-called "affected commands".

Let's say we make a change in the product-detail library of our application. This would affect all other libraries that depend on it. You can also visualize it by running

To run tasks only for the affected areas, use:

To make a concrete example, running just tests for those projects:

If you are not the "command line interface type" developer and you'd rather prefer something integrated within your IDE, then there's good news. The Nx core team also ships a dedicated VSCode extension: Nx Console.

It has a dedicated view within VSCode to trigger common commands, browse the workspace structure and even inline render the graph.

It also comes with contextual menus to quickly access most of the commonly used functionality:

Here's a walkthrough video showing some of the powerful capabilities of Nx Console:

To keep workspaces evergreen, Nx comes with automated code migrations that

  • upgrade your package.json packages to the next version
  • can automatically update your configuration files if necessary
  • can automatically update your source files if necessary (in case of breaking changes in the API)

This allows for smooth transitions even if there are breaking changes. Just run

Nx gathers the currently installed packages and updates them to the latest version. If a package comes with Nx migration scripts, Nx collects them in a migrations.json file. You can inspect and then run them. This dramatically helps to keep your project tooling up to date.

Read more about how Nx migrations work on the docs.

Using CRA? Automatically migrate to Vite + Nx

If you're currently on a CRA setup, you can easily migrate to an Nx + React + Vite-based setup by running the following command in your CRA project:

Read more on the Nx docs: /recipes/adopting-nx/adding-to-existing-project

If for some reason you cannot migrate to Vite just yet, you can pass _--vite=false_ to keep a Webpack-based setup for now.

Conclusion

Ready? Give it a try:

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

And let us know what you think :)

Learn more