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

推荐订阅源

The Hacker News
The Hacker News
F
Full Disclosure
Cloudbric
Cloudbric
Blog — PlanetScale
Blog — PlanetScale
W
WeLiveSecurity
N
News and Events Feed by Topic
T
Troy Hunt's Blog
V2EX - 技术
V2EX - 技术
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
B
Blog
GbyAI
GbyAI
C
Check Point Blog
B
Blog RSS Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Recorded Future
Recorded Future
The Last Watchdog
The Last Watchdog
N
News and Events Feed by Topic
T
The Blog of Author Tim Ferriss
O
OpenAI News
V
V2EX
人人都是产品经理
人人都是产品经理
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
WordPress大学
WordPress大学
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Security @ Cisco Blogs
C
Cisco Blogs
Security Latest
Security Latest
S
Security Affairs
V
Visual Studio Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Azure Blog
Microsoft Azure Blog
Last Week in AI
Last Week in AI
AWS News Blog
AWS News Blog
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
PCI Perspectives
PCI Perspectives
博客园_首页
U
Unit 42
Google DeepMind News
Google DeepMind News
Hugging Face - Blog
Hugging Face - Blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
The Register - Security
The Register - Security
N
Netflix TechBlog - Medium
L
LINUX DO - 热门话题
H
Hacker News: Front Page

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
A New Nx Experience for TypeScript Monorepos and Beyond | Nx Blog
Juri Strumpflohner · 2025-01-30 · via Nx Blog

TypeScript Project References Series

Today we're excited to release a brand new experience for Nx workspaces. Historically, Nx, and many other monorepo tools, have relied on TypeScript's path aliases to connect your many packages to one another. While this approach can work, it does come with some overhead. Apart from runtimes and bundlers requiring special handling, the main limitation is in large monorepos. We've seen larger organizations struggle with slowness, memory issues and editors not being able to properly resolve symbols.

This is why we're releasing a new NPM/Yarn/PNPM/Bun workspaces-based setup combined with TypeScript project references. The new setup is faster, more efficient in terms of memory use, and fixes common issues with TypeScript editor support for large monorepos.

For existing Nx users: Don't worry as we're not going to deprecate the current TypeScript alias based setup. We are going to have a migration guide and potentially tooling to automate some of it. More about that later in the article. Also, for now the new workspaces based setup is behind a --workspaces flag as we're gathering feedback and polishing it further.

Ready? Let's dive in!

Let's Check Out the New Experience

The workspaces experience is currently available behind the --workspaces flag. This allows us to gather your feedback and polish it further before rolling it out as the default.

To try it, you can create a new workspace with:

npx create-nx-workspace tsmono --preset=react --workspaces

The exception is if you use --preset=ts or if you use nx init to add Nx to an existing NPM/Yarn/PNPM/Bun workspaces monorepo. In those situations you are already in a NPM/Yarn/PNPM/Bun workspaces environment and you likely know what's going on.

Create a New Workspaces-based Monorepo

Let's start with a simple workspace setup without any framework or specific tech stack, just TypeScript support. This allows us to highlight how features can be incrementally added over time. Run the following command:

npx create-nx-workspace tsmono --preset=ts

This generates a NPM workspaces setup. The only traces of Nx are:

  • a nx.json at the root containing configuration about caching and task pipelines
  • a nx dependency in the root-level package.json
  • a @nx/js dependency in the root-level package.json; this is because we created a TypeScript monorepo setup which ships with support for creating and managing TS based packages.

Note if you want to create a PNPM/Yarn/Bun workspace use the --pm flag to specify your preferred package manager.

Creating a New Package

Using the @nx/js plugin generator to create a new TypeScript package

Nx has always shipped with code generators, allowing you to scaffold projects or integrate features into existing ones. These generators are part of Nx plugins and have been adapted to work seamlessly in NPM, Yarn, PNPM, or Bun workspaces.

While you could create a package manually, the generator simplifies the process by handling all the tedious setup. It automatically:

  1. Configures the package.json file, including proper exports.
  2. Sets up tsconfig files to work well with your editor and TypeScript project references for fast incremental type checking.

Run the following command to generate a new TypeScript package:

npx nx g @nx/js:lib packages/mytslib

During the setup, you can choose whether to include a bundler like tsc or leave it out if the package is intended for local use only. You can also configure optional features like linting or testing (with Vitest or Jest).

The generator configures the package.json file just as you would manually, ensuring it includes entries for type, main, types, and exports.

Where are the package.json scripts though? Although you could define package.json scripts and Nx would use them, this isn't required. Nx can automatically detect the underlying tool that is being used - in this case TypeScript - and infers a typecheck command. You can simply run the following and it would work:

If you selected additional features like a bundler, linter, or testing framework during generation, Nx would also infer corresponding commands, such as build, lint, or test.

Let's create an application next to use our package.

Generating a New Vite-based React Application

Using the @nx/react plugin generator to create a new Vite-based React application

While you could use the Vite CLI to generate a new Vite app in your monorepo, the Nx React plugin adds some valuable features. It configures TypeScript project references and ensures Vite works seamlessly within a monorepo setup.

To begin, install the Nx React plugin:

This command installs and configures the plugin. Once installed, you can use its application generator to scaffold a new React application:

npx nx g @nx/react:app apps/myviteapp

Importing Packages in our React Application

To use the mytslib package in the newly generated React application, simply import it as follows:

apps/myviteapp/src/app/app.tsx

import NxWelcome from './nx-welcome';

import { mytslib } from '@tsmono/mytslib';

export function App() {
  console.log(mytslib());
  return (
    <div>
      <NxWelcome title="@tsmono/myviteapp" />
    </div>
  );
}

export default App;

Thanks to the TypeScript project references created by Nx during project generation, your editor will fully support features like autocomplete and navigation. For instance, the root-level tsconfig.json references both the myviteapp and mytslib projects which allows the editor to correctly find all the available projects in your monorepo.

{
  "extends": "./tsconfig.base.json",
  "compileOnSave": false,
  "files": [],
  "references": [
    {
      "path": "./packages/mytslib"
    },
    {
      "path": "./apps/myviteapp"
    }
  ]
}

Referencing Dependencies in package.json

In an NPM-based monorepo, even though you reference mytslib from myviteapp, you don't have to add a dependency in myviteapp/package.json. You only need that if mytslib isn't buildable (i.e., you depend on the precompiled .js files).

However, if you're using PNPM, you must explicitly declare the dependency either in the consumer (myviteapp) or in the root-level package.json.

apps/myviteapp/package.json

{
  "name": "@tsmono/myviteapp",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "@tsmono/mytslib": "workspace:*"
  }
}

Note that the workspace: prefix is part of the "Workspaces Protocol" that PNPM, Yarn v2+ and Bun support.

Automatically Syncing TypeScript Project References

Nx automatically prompts to sync TypeScript project references if they are out of sync

TypeScript project references offer significant benefits for large-scale monorepos, particularly in terms of compilation speed and memory usage. However, their maintenance can become a challenge as your monorepo evolves. Every project's tsconfig.json needs to stay updated with the correct references to its dependencies, effectively requiring you to manually manage the TypeScript project graph.

To address this, Nx introduces the nx sync command, which automatically keeps your TypeScript project references in sync. Whenever you run commands like build, serve, or dev, Nx verifies whether the project references are accurate. If they are out of sync, it prompts you to update them.

For example, after importing mytslib into myviteapp, you'll notice that apps/myviteapp/tsconfig.json now includes a reference to mytslib, ensuring your project remains correctly configured:

Watching Dependencies

Automatically watching buildable libraries and rebuilding them.

In our current setup, the mytslib package is not "buildable". Notice it directly exports the TypeScript files. This means when myviteapp imports mytslib, it directly imports the TypeScript files and handles the transpilation. As a result, if we serve the application in dev mode, any changes to mytslib will automatically update the application because it depends on the source files directly.

However, in some cases, you may have buildable libraries. These are useful for caching, CI optimizations, or releasing packages outside the monorepo. When a buildable library changes, it must be recompiled to reflect the updates. To streamline this process, Nx introduces a watch-deps target, which automatically watches and rebuilds the dependencies of your applications.

To simulate this, let's create a buildable library:

npx nx g @nx/js:lib packages/buildablelib --bundler=tsc

Next, import it in our existing mytslib:

packages/mytslib/.../mytslib.ts

packages/mytslib/src/lib/mytslib.ts

import { buildablelib } from '@tsmono/buildablelib';

export function mytslib(): string {
  return buildablelib() + ' - mytslib';
}
packages/mytslib/package.json

packages/mytslib/package.json

{
  "name": "@tsmono/mytslib",
  ...
  "dependencies": {
    "@tsmono/buildablelib": "*"
  }
}

Now, open two terminal windows. In the first run the watch-deps command:

npx nx watch-deps myviteapp

In the second, serve the Vite application:

The watch-deps target takes care of automatically watching all dependencies of myviteapp and rebuilding them automatically when anything changes.

Key Highlight - Locality and Minimalism

Nx plugins have been essential for helping enterprises organize and scale monorepos, but their reliance on Nx-generated workspace structures made migrating existing setups difficult. To address this, we introduced inferred tasks, which allows plugins to read directly from underlying tool configurations, like vite.config.ts, enabling seamless integration with existing projects.

We further improved how plugins work by applying the locality principle. Originally, plugins made many assumptions about the workspace structure and relied heavily on global configuration files. We updated them to operate locally within the project whenever possible, minimizing changes to global configurations.

In addition, we are now focusing on creating a minimal setup that you can expand incrementally as needed. The idea is to keep the initial setup for new projects as simple as possible, closely mirroring what you would manually configure yourself. The generated code follows best practices:

  • Configuring package.json files correctly with exports
  • Setting up tsconfig files to work optimally in editors
  • Creating TypeScript project references and keeping them in sync

Nx is also much more versatile. It can directly run your package.json scripts or infer targets based on the tools you're using.

You still also have the option to create Nx's project.json files (see docs) for declaring more complex configurations. However, you only use them if needed.

The key idea here is that tooling shouldn't get in your way but should elevate your experience.

Key Highlight - Performance

We have already highlighted some raw metrics from benchmarking TypeScript project references compared to running type checking globally for the entire monorepo. Check out our first article in the series for more details.

The core difference to understand here is that traditionally, you might have a single task that combines building and type checking, or at least two separate ones (like for Vite applications): one for building and one for type checking. For large TypeScript monorepos, this approach can become problematic because type checking occurs at the application level for all projects in the repository. This means a single TypeScript program is responsible for the entire process.

This has two major implications:

  • It cannot be parallelized and distributed on CI, which makes it slow.
  • It is memory-intensive, requiring large CI machines (resulting in higher costs).

By leveraging the new Nx and TypeScript project references setup, we now have fine-grained, individual type checking tasks at the project level. This allows you to run tasks in parallel and potentially distribute them across different Nx Agents on CI.

Running type checking on different agents on CI

As such, the new approach:

  • Has fine-grained type checking tasks, which can be run in parallel.
  • Is distributable across multiple machines, resulting in faster CI runs.
  • Each individual type check requires less memory, allowing the use of smaller machines.
  • Each individual type check can be cached, significantly speeding up follow-up runs.
Moving from a single build + type check to fine-grained distributable type checks

We ran some benchmarks comparing the current Nx setup (not using TS project references) and the new TypeScript project references-based setup. TL;DR, here are some high-level numbers:

  • Setup without TS project references: ~8 min
  • New TypeScript project references setup: ~2 min

You're seeing a ~ in front because it might fluctuate slightly (within ~20 sec) depending on how many machines we use and the distribution of tasks. Let's break it down. I'll refer to "Old" as the setup without TypeScript project references and "New" as the setup using TypeScript project references.

3 Agents - Old: 8m 38s; New: 2m 49s

We just have two tasks running here: demo:build and demo:typecheck. Tasks are distributed across two agents, while one agent remains unused.

Without TypeScript project references - 3 Nx Agents

If we run the same setup but leverage the new fine-grained typecheck tasks, we can see how the distribution is much more optimal. Now, all three agents are utilized, reducing the runtime to approximately 3m 29s, which corresponds to the slowest agent.

With TypeScript project references - 3 Nx Agents

Let's explore whether increasing the number of agents further improves the overall CI runtime.

4 Agents

New setup, 4 Nx Agents - 3m 02s

With TypeScript project references - 4 Nx Agents

5 Agents

New setup, 5 Nx Agents - 2m 42s

With TypeScript project references - 5 Nx Agents

Beyond four agents, we won't be able to go any faster because the slowest, non-splittable, and thus non-distributable task (huge-lib:typecheck) takes approximately 2m 32s.

We cannot get faster than the slowest unsplittable task

And note, this is the worst-case scenario, relying solely on distributing type-checking tasks across different machines. Subsequent runs might hit the cache, making them even faster.

It's also important to emphasize that the main reason we can fully leverage these benefits from TypeScript project references is that we avoid the maintenance burden of setting them up manually, thanks to the automated Nx sync command.

Now, if your company struggles with these performance issues in large TypeScript monorepos, let us know. We've worked with many teams to solve similar challenges and would be happy to help. Reach out!

FAQ

Here are some common questions and corresponding answers.

Nx by default creates a TypeScript Path Aliases based Setup. Is that Deprecated?

No, it's not deprecated. When Nx was first introduced, workspaces-based setups weren't yet an option. TypeScript path aliases were the go-to solution for creating modular monorepos, offering a simple yet effective way to structure projects. Nx plugins handled the complexities behind the scenes, enabling incremental compilation by rewriting paths on the fly.

Going forward, the recommended approach is to use NPM, Yarn, PNPM, or Bun workspaces combined with TypeScript project references. This setup integrates more seamlessly with modern tooling and can potentially lead to a more performant setup.

In fact, Nx has supported running tasks and caching package.json scripts in workspace setups for years. The main limitation was the compatibility of Nx plugins, which has now been addressed. Plugins work equally well in both scenarios: the workspaces setup and the TypeScript path alias setup.

Will There be a Migration Path from the Current Nx Setup?

Yes, it's already possible to use Nx in a mixed setup that combines NPM, Yarn, or PNPM workspaces with TypeScript path aliases. However, doing so requires careful attention and an understanding of how package resolution works.

As we continue refining the new workspaces experience, we're also preparing detailed content and guidance to support an incremental migration, making the transition as smooth as possible.

What Are the Implications for a Single Version Policy?

We've consistently advocated for a single version policy in Nx monorepos and continue to believe it's the better approach in the long run.

The TypeScript path alias-based setup inherently enforces a single version policy, making it harder to opt out. In contrast, the workspaces-based monorepo configuration provides more flexibility. That said, you can still adopt a single version strategy with workspaces, and we may introduce tooling in the future to help enforce it.

What About Angular? Does the New Setup Work with Angular?

Currently, Angular and its underlying compiler don't support TypeScript project references. However, you can still use Nx and Angular within an NPM, Yarn, or PNPM workspaces-based setup. This can be especially useful when migrating multiple Angular applications into a single Nx monorepo.

For now, we continue to use the TypeScript path alias-based setup for pure Angular monorepos, as it offers a better developer experience in the current context. That said, we're actively working on improving this. Large Angular applications stand to benefit significantly from the performance and memory optimizations enabled by TypeScript project references.

Wrapping up

That's it! Try it out and let us know what you think. If you encounter any issues or have questions, don't hesitate to reach out. We want to catch all edge cases before making this the default for new Nx workspaces.

If you're working in a large monorepo and struggling with the performance issues we discussed, reach out. We've helped many teams tackle similar challenges and would be happy to assist.