Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b05d5fee28 | |||
| 14c2d5ba3f | |||
| c43ee13eed | |||
| af07e75d58 | |||
| ac2ef1aaef | |||
| 191054d876 | |||
| b8b6ed8b85 | |||
| bdc61b5ad5 | |||
| 31dad4109b | |||
| c3643126ef | |||
| dcfc2134d4 | |||
| 77100fac5d | |||
| b1614d7504 | |||
| 0ae45cd445 | |||
| fcf4660389 | |||
| 221ea40462 | |||
| 12812dc994 | |||
| 4c3812f731 | |||
| 098a830e5d | |||
| f31e7a75be | |||
| 09c44a637a | |||
| dc81b8bbd6 | |||
| f7e46e33e9 | |||
| 5d64f726d6 | |||
| 1e1a8a7a40 | |||
| 872b9c9045 | |||
| 1e3f8e00f7 | |||
| 919907cf0f | |||
| d5cd6a1a56 | |||
| 700c98fcaf | |||
| df9eb0bf10 | |||
| 4e55f9aa32 | |||
| 127255aa96 | |||
| b46de60cd9 | |||
| 736551590a | |||
| e031d024ef | |||
| d042483a3f | |||
| 39f252df97 | |||
| 3f70561586 | |||
| b72a203ed7 | |||
| 1ecf0fb6a7 | |||
| c743313078 | |||
| 1bbe936513 | |||
| c966e20746 | |||
| f42976f852 | |||
| 6d90572257 | |||
| f84ec34cbd | |||
| 566a370375 | |||
| 4c1dd1e5ed | |||
| 8f64e844c9 | |||
| 7f7bba633d | |||
| 1a15ea183a | |||
| 8c0600225a | |||
| 832355081b | |||
| 1081c320ab | |||
| bdeeb036fb | |||
| 4b1bf5f7ba | |||
| f935d9a7bf | |||
| dd325d790a | |||
| ed786fb12c | |||
| cc5eeefde9 | |||
| cf53d15ae5 | |||
| 7351e21150 | |||
| c5ab66152a | |||
| 1805301941 | |||
| e8633e0299 | |||
| 6bcaa46864 | |||
| d545472da8 | |||
| 025db33a75 | |||
| 731db47fd7 | |||
| 4b6aea9f5e | |||
| 0568059fb8 | |||
| 3e5df300ab | |||
| 221ed882fa | |||
| df8a2c43f4 | |||
| 391d23c65e | |||
| 092cea6073 | |||
| de2dc7ca13 | |||
| 5236e02308 | |||
| 8e1d873edc |
@@ -1,3 +1,6 @@
|
||||
[env]
|
||||
JEMALLOC_SYS_WITH_MALLOC_CONF = "dirty_decay_ms:1000,muzzy_decay_ms:0"
|
||||
|
||||
[build]
|
||||
target-dir = 'dist/target'
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ jobs:
|
||||
NX_CLOUD_USE_NEW_TASK_APIS: 'true'
|
||||
NX_CLOUD_USE_NEW_STREAM_OUTPUT: 'true'
|
||||
NX_CLOUD_EXPERIMENTAL_POLLING: 'true'
|
||||
NX_CLOUD_CONTINUOUS_ASSIGNMENT: 'true'
|
||||
NX_CLOUD_CONTINUOUS_ASSIGNMENT: 'false'
|
||||
NX_CLOUD_VERBOSE_LOGGING: 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -77,7 +78,7 @@ jobs:
|
||||
pnpm playwright install --with-deps
|
||||
|
||||
- name: Nx Report
|
||||
run:
|
||||
run:
|
||||
pnpm nx report
|
||||
|
||||
- name: Run Checks/Lint/Test/Build
|
||||
@@ -96,7 +97,7 @@ jobs:
|
||||
pnpm nx run-many -t check-imports check-lock-files check-codeowners --parallel=1 --no-dte &
|
||||
pids+=($!)
|
||||
|
||||
pnpm nx affected --targets=lint,test,test-kt,build,e2e,e2e-ci,format-native,lint-native &
|
||||
pnpm nx affected --targets=lint,test,build,e2e,e2e-ci,format-native,lint-native,gradle:build-ci &
|
||||
pids+=($!)
|
||||
|
||||
for pid in "${pids[@]}"; do
|
||||
|
||||
@@ -174,7 +174,7 @@ jobs:
|
||||
bash -c "
|
||||
set -e
|
||||
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
|
||||
apk add --no-cache curl xz openjdk21
|
||||
apk add --no-cache curl xz openjdk21 build-base lld
|
||||
|
||||
# Set up Java 21
|
||||
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
|
||||
@@ -194,6 +194,10 @@ jobs:
|
||||
npm i -g pnpm@${PNPM_VERSION} --force
|
||||
pnpm --version
|
||||
|
||||
# Help clang find GCC runtime (crtbeginS.o, libgcc) and use lld for jemalloc build
|
||||
GCC_DIR=\$(dirname \$(find /usr/lib/gcc -name crtbeginS.o | head -1))
|
||||
export CFLAGS=\"\${CFLAGS} -fuse-ld=lld --gcc-install-dir=\${GCC_DIR}\"
|
||||
|
||||
# Install deps and run native build
|
||||
pnpm install --frozen-lockfile
|
||||
rustup target add x86_64-unknown-linux-musl
|
||||
@@ -230,6 +234,9 @@ jobs:
|
||||
node --version
|
||||
npm --version
|
||||
|
||||
# Help clang find GCC runtime (crtbeginS.o, libgcc) and use lld for jemalloc build
|
||||
export CFLAGS="${CFLAGS} -fuse-ld=lld --gcc-toolchain=/usr/aarch64-unknown-linux-gnu"
|
||||
|
||||
npm i -g pnpm@${PNPM_VERSION} --force
|
||||
pnpm --version
|
||||
|
||||
@@ -260,7 +267,7 @@ jobs:
|
||||
bash -c "
|
||||
set -e
|
||||
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
|
||||
apk add --no-cache curl xz openjdk21
|
||||
apk add --no-cache curl xz openjdk21 build-base lld
|
||||
|
||||
# Set up Java 21
|
||||
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
|
||||
@@ -280,6 +287,10 @@ jobs:
|
||||
npm i -g pnpm@${PNPM_VERSION} --force
|
||||
pnpm --version
|
||||
|
||||
# Help clang find GCC runtime (crtbeginS.o, libgcc) and use lld for jemalloc build
|
||||
GCC_DIR=\$(dirname \$(find /aarch64-linux-musl-cross/lib/gcc -name crtbeginS.o | head -1))
|
||||
export CFLAGS=\"\${CFLAGS} -fuse-ld=lld --gcc-install-dir=\${GCC_DIR}\"
|
||||
|
||||
# Install deps and run native build
|
||||
pnpm install --frozen-lockfile
|
||||
rustup target add aarch64-unknown-linux-musl
|
||||
|
||||
@@ -29,7 +29,7 @@ jest.debug.config.js
|
||||
# Banner JSON files are generated during static builds
|
||||
/nx-dev/nx-dev/lib/banner.json
|
||||
/astro-docs/src/content/banner.json
|
||||
**/tests/temp-db
|
||||
**/tests/temp-db*
|
||||
|
||||
# Issues scraper creates these files, stored by github's cache
|
||||
/scripts/issues-scraper/cached
|
||||
@@ -71,7 +71,7 @@ dependency-reduced-pom.xml
|
||||
*.wasm
|
||||
/wasi-sdk*
|
||||
|
||||
vite.config.*.timestamp*
|
||||
*.config.timestamp*
|
||||
|
||||
storybook-static
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ common-env-vars: &common-env-vars
|
||||
# These are need for build and link validation for next.js and astro apps
|
||||
NEXT_PUBLIC_ASTRO_URL: 'https://master--nx-docs.netlify.app'
|
||||
NX_DEV_URL: 'https://canary.nx.dev'
|
||||
NX_CLOUD_IO_TRACING_DIRECTORY: '~/io-tracing'
|
||||
|
||||
common-init-steps: &common-init-steps
|
||||
- name: Checkout
|
||||
|
||||
@@ -7,6 +7,12 @@ distribute-on:
|
||||
assignment-rules:
|
||||
- projects:
|
||||
- e2e-gradle
|
||||
targets:
|
||||
- e2e-ci**
|
||||
run-on:
|
||||
- agent: linux-extra-large
|
||||
parallelism: 1
|
||||
- projects:
|
||||
- e2e-next
|
||||
- e2e-plugin
|
||||
targets:
|
||||
@@ -94,6 +100,15 @@ assignment-rules:
|
||||
- agent: linux-extra-large
|
||||
parallelism: 6
|
||||
|
||||
# TODO(altan): remove when scheduling issue resolved
|
||||
- projects:
|
||||
- nx-dev
|
||||
targets:
|
||||
- prebuild-banner
|
||||
run-on:
|
||||
- agent: linux-extra-large
|
||||
parallelism: 6
|
||||
|
||||
- targets:
|
||||
- "*"
|
||||
run-on:
|
||||
|
||||
@@ -3,3 +3,10 @@ nx-dev/**/jest.config.js
|
||||
_files
|
||||
_solution
|
||||
nx-dev/tutorial/**/templates
|
||||
|
||||
# Generated by napi-rs (outputs of build-native)
|
||||
packages/nx/src/native/index.d.ts
|
||||
packages/nx/src/native/native-bindings.js
|
||||
|
||||
# Workaround for ignore-files crate bug with prefix matching
|
||||
**/target/
|
||||
|
||||
@@ -2214,6 +2214,7 @@ dependencies = [
|
||||
"tempfile",
|
||||
"terminal-colorsaurus",
|
||||
"thiserror 1.0.69",
|
||||
"tikv-jemallocator",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
@@ -3832,6 +3833,26 @@ dependencies = [
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemalloc-sys"
|
||||
version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemallocator"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tikv-jemalloc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.44"
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
# Nx Documentation Style Guide
|
||||
|
||||
This document defines the standards for Nx documentation on nx.dev, including voice, grammar, formatting, and terminology.
|
||||
|
||||
For automated enforcement, see the [Vale configuration](#vale-configuration) section.
|
||||
|
||||
## Information architecture
|
||||
|
||||
When creating or reorganizing documentation, follow these five principles to determine where content belongs.
|
||||
|
||||
### 1. Progressive disclosure (the "journey" rule)
|
||||
|
||||
Don't overwhelm the user. Reveal complexity only as they advance in their journey.
|
||||
|
||||
**The test:** Is this for the first 30 minutes (Getting Started), the first 30 days (Features), or forever (Reference)?
|
||||
|
||||
### 2. Category homogeneity (the "scan" rule)
|
||||
|
||||
Items in a list must be of the same "type" (noun, verb, or concept) to reduce cognitive load.
|
||||
|
||||
**The test:** Does this list mix concepts (mental model), tasks (update Nx), and products (React)? If yes, split it.
|
||||
|
||||
### 3. Type-based navigation (the "intent" rule)
|
||||
|
||||
Separate learning (narrative/guides) from looking up (reference/API).
|
||||
|
||||
**The test:** Is the user here to learn a workflow (guide) or look up a flag syntax (reference)?
|
||||
|
||||
### 4. The pen and paper test (the "theory" rule)
|
||||
|
||||
Distinguish architecture from features to keep "core concepts" pure.
|
||||
|
||||
**The test:** Can I explain this using only a pen and paper?
|
||||
|
||||
- Yes: It goes in **How Nx Works** (architecture).
|
||||
- No (I need a terminal): It goes in **Platform Features** (feature).
|
||||
|
||||
### 5. Universal vs. specific (the "placement" rule)
|
||||
|
||||
Distinguish platform features from ecosystem tools to prevent "Features" from becoming a junk drawer.
|
||||
|
||||
**The test:** Does this feature apply to every user (e.g., caching, Nx Agents)?
|
||||
|
||||
- Yes: **Platform Features**.
|
||||
- No (only React users): **Technologies**.
|
||||
|
||||
### Sidebar structure
|
||||
|
||||
The sidebar has four top-level sections that follow the user journey:
|
||||
|
||||
1. **Getting Started** - Essential setup, tutorials, and core concepts (How Nx Works, Platform Features)
|
||||
2. **Technologies** - Framework and tool-specific guides (React, Angular, Node, build tools, test tools)
|
||||
3. **Knowledge Base** - Recipes, troubleshooting, and topic-specific guides
|
||||
4. **Reference** - Exhaustive facts, no narrative (CLI commands, configuration, API docs)
|
||||
|
||||
## The Nx voice
|
||||
|
||||
Nx documentation is **direct, practical, and confident**. We write like a knowledgeable colleague pairing with you — not like a textbook, not like a marketing page, and not like a chatbot.
|
||||
|
||||
The voice should be:
|
||||
|
||||
- **Conversational but efficient.** Use contractions. Get to the point. Don't pad sentences.
|
||||
- **Second person.** Write "you" — address the reader directly.
|
||||
- **Action-oriented.** Lead with what the reader can _do_, not what Nx _is_.
|
||||
- **Honest about tradeoffs.** Don't oversell. If something has limitations, say so.
|
||||
|
||||
### Voice do's and don'ts
|
||||
|
||||
| Do | Don't |
|
||||
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
|
||||
| "You can speed up builds by enabling remote caching." | "Nx allows you to speed up builds." |
|
||||
| "Run `nx build` to build your project." | "In order to build your project, you can run the `nx build` command." |
|
||||
| "This works best with fewer than 50 projects." | "This feature can easily scale to any number of projects." |
|
||||
| "Nx reads your `vite.config.ts` and infers build targets automatically." | "Nx provides a robust and comprehensive mechanism for inferring build targets." |
|
||||
| "If the cache is stale, delete `.nx/cache` and retry." | "Should you encounter issues with caching, you may want to consider clearing your cache directory." |
|
||||
|
||||
### Anti-AI language
|
||||
|
||||
Documentation must not read like it was generated by an AI assistant. Even when AI tools are used in the writing process, the output must be edited to sound like a human wrote it.
|
||||
|
||||
**Never use these phrases:**
|
||||
|
||||
- "It's important to note that..."
|
||||
- "It's worth noting that..." / "It should be noted that..."
|
||||
- "In this section, we will explore..."
|
||||
- "Let's dive into..." / "Let's take a closer look at..."
|
||||
- "Whether you're a beginner or an experienced developer..."
|
||||
- "In today's fast-paced development environment..."
|
||||
- "Unlock the power of..." / "Harness the power of..."
|
||||
- "Take your workspace to the next level"
|
||||
- "Streamline your workflow" (as a generic claim without specifics)
|
||||
- "This comprehensive guide will..."
|
||||
- "Without further ado..."
|
||||
- "In conclusion..." / "To summarize..." / "As we've seen..."
|
||||
- "Game-changer" / "Cutting-edge" / "Groundbreaking"
|
||||
- "Seamless" / "Seamlessly" (unless describing an actual integration)
|
||||
|
||||
**Avoid hedging words unless genuinely needed:**
|
||||
|
||||
- "Essentially" / "Basically" / "Effectively"
|
||||
- "Generally speaking"
|
||||
- "It is worth mentioning"
|
||||
- "Arguably"
|
||||
- "Needless to say"
|
||||
- "As a matter of fact"
|
||||
|
||||
**Watch for AI-style sentence patterns:**
|
||||
|
||||
- Sentences that start with "This allows you to..." or "This enables you to..." — rewrite to lead with the reader's action.
|
||||
- Paragraphs that start with a general claim and then restate it slightly differently. Say it once.
|
||||
- Excessive use of "robust", "leverage", "utilize", "facilitate", "comprehensive", "aforementioned."
|
||||
- Lists where every item starts with the same grammatical structure repeated 5+ times with slight variation. Vary your phrasing.
|
||||
|
||||
### Self-referential writing
|
||||
|
||||
Don't write about the document itself.
|
||||
|
||||
Do:
|
||||
|
||||
- "Nx uses a project graph to determine task dependencies."
|
||||
|
||||
Don't:
|
||||
|
||||
- "This page explains how Nx uses a project graph."
|
||||
- "In this guide, we'll walk through..."
|
||||
- "This document covers..."
|
||||
|
||||
Get right to the point. The reader already knows they're on a page — they want the information.
|
||||
|
||||
### Building trust
|
||||
|
||||
Don't use filler words that undermine the reader's trust.
|
||||
|
||||
- Don't use "easily", "simply", "just", or "straightforward" — if something were truly simple, you wouldn't need to document it. These words also make readers feel bad when they struggle.
|
||||
- Don't use marketing language: "This feature will save you hours" or "Nx makes CI effortless."
|
||||
- Be specific instead: "Remote caching can reduce CI times from 45 minutes to under 5 minutes for cache-hit builds."
|
||||
|
||||
### Customer perspective
|
||||
|
||||
Focus on what the reader can do, not what Nx does.
|
||||
|
||||
Do:
|
||||
|
||||
- "Use `nx affected` to run tasks only for projects impacted by your changes."
|
||||
|
||||
Don't:
|
||||
|
||||
- "Nx allows you to run affected tasks."
|
||||
- "Nx provides the ability to run tasks selectively."
|
||||
|
||||
Words like "allow" and "enable" are signals you're writing from the product's perspective instead of the reader's.
|
||||
|
||||
## Language
|
||||
|
||||
Write in US English.
|
||||
|
||||
### Active voice
|
||||
|
||||
Use active voice in most cases.
|
||||
|
||||
Do: "Nx caches the build output."
|
||||
Don't: "The build output is cached by Nx."
|
||||
|
||||
Exception: When "Nx" as the subject sounds awkward, passive voice is fine. "The output is stored in `.nx/cache`" is better than "Nx stores the output in `.nx/cache`" if Nx isn't the focus of the sentence.
|
||||
|
||||
### Contractions
|
||||
|
||||
Use contractions. They make the text feel natural.
|
||||
|
||||
- "You'll need to configure..." not "You will need to configure..."
|
||||
- "It doesn't support..." not "It does not support..."
|
||||
|
||||
Don't contract for emphasis in warnings or error descriptions:
|
||||
|
||||
- "**Do not** delete the `nx.json` file."
|
||||
- "Requests to localhost **are not** allowed."
|
||||
|
||||
Don't contract proper nouns: "the Vite plugin is..." not "Vite's a plugin..."
|
||||
|
||||
### Capitalization
|
||||
|
||||
Use sentence case for headings. Capitalize proper nouns only.
|
||||
|
||||
- `# Use remote caching to speed up CI`
|
||||
- `## Configure the Vite plugin`
|
||||
|
||||
Feature names are lowercase unless they are a proper product name:
|
||||
|
||||
| Correct | Incorrect |
|
||||
| -------------- | -------------- |
|
||||
| remote caching | Remote Caching |
|
||||
| task pipeline | Task Pipeline |
|
||||
| project graph | Project Graph |
|
||||
| Nx Cloud | nx cloud |
|
||||
| Nx Console | nx console |
|
||||
| Nx Agents | nx agents |
|
||||
| Nx Replay | nx replay |
|
||||
|
||||
### Acronyms
|
||||
|
||||
Spell out acronyms on first use per page. Don't spell out widely-known ones: CI, CD, API, URL, CLI, PR, IDE.
|
||||
|
||||
Don't make acronyms plural with apostrophes. Use `APIs`, not `API's`.
|
||||
|
||||
### Numbers
|
||||
|
||||
Spell out zero through nine. Use numerals for 10 and above. Always use numerals with units: "5 minutes", "3 projects."
|
||||
|
||||
### Possessives
|
||||
|
||||
Don't use possessives on product names. "the Docker CLI", not "Docker's CLI." "the Nx configuration", not "Nx's configuration."
|
||||
|
||||
## Text
|
||||
|
||||
### Headings
|
||||
|
||||
- Don't skip heading levels (e.g., `##` to `####`).
|
||||
- Don't use code in headings unless it's essential (like a CLI command).
|
||||
- Don't use bold text in headings.
|
||||
- Keep headings short and scannable. Lead with keywords.
|
||||
|
||||
### Line length
|
||||
|
||||
- Wrap lines at approximately 100 characters for readability in diffs.
|
||||
- Start each new sentence on a new line.
|
||||
- Exception: Don't break links across lines.
|
||||
|
||||
### Punctuation
|
||||
|
||||
- Use serial (Oxford) commas: "React, Angular, and Vue."
|
||||
- Use one space between sentences.
|
||||
- Don't use semicolons. Use two sentences instead.
|
||||
- Don't use em dashes or en dashes. Use commas or separate sentences.
|
||||
|
||||
### Placeholder text
|
||||
|
||||
Use `<` and `>` for values the reader must replace:
|
||||
|
||||
```shell
|
||||
nx run <project-name>:build
|
||||
```
|
||||
|
||||
If the placeholder is inline, wrap it in a single backtick: `<your-project>`.
|
||||
|
||||
### Bold
|
||||
|
||||
Use bold for:
|
||||
|
||||
- UI elements: "Select **Add Connection**."
|
||||
- Navigation paths: "Go to **Settings** > **Workspace**."
|
||||
|
||||
Don't use bold for emphasis or keywords. If you need emphasis, rewrite the sentence to be clearer.
|
||||
|
||||
### Inline code
|
||||
|
||||
Use inline code (single backticks) for:
|
||||
|
||||
- Commands and CLI arguments: `nx build`, `--parallel`
|
||||
- File names and paths: `nx.json`, `.nx/cache`
|
||||
- Configuration keys: `targetDefaults`, `namedInputs`
|
||||
- Short outputs and values: `true`, `false`, `success`
|
||||
|
||||
### Code blocks
|
||||
|
||||
Use triple backticks with a language identifier:
|
||||
|
||||
````markdown
|
||||
```json
|
||||
{
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"cache": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
- Always specify a syntax language. Use `plaintext` if nothing else fits.
|
||||
- Add a blank line before and after code blocks.
|
||||
- For long config files, show only the relevant section and use comments to indicate omitted parts:
|
||||
|
||||
```json
|
||||
{
|
||||
// ... other config
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"cache": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
Links help readers find related information, but too many links make text hard to read.
|
||||
|
||||
### General rules
|
||||
|
||||
- Don't duplicate links. If you link to a page once, don't link to it again on the same page.
|
||||
- Don't use links in headings.
|
||||
- Avoid more than 15 links to other pages on any single page.
|
||||
- Avoid multiple links in a single paragraph when possible.
|
||||
|
||||
### Link text
|
||||
|
||||
Use descriptive text, not "here" or "this page."
|
||||
|
||||
Do:
|
||||
|
||||
- "For more information, see [remote caching](/features/cache)."
|
||||
- "To configure task pipelines, see [task pipeline configuration](/concepts/task-pipeline-configuration)."
|
||||
|
||||
Don't:
|
||||
|
||||
- "For more information, see [this page](/features/cache)."
|
||||
- "Click [here](/features/cache) to learn more."
|
||||
- "For more information, see the [Remote Caching](/features/cache) documentation."
|
||||
|
||||
Standard patterns:
|
||||
|
||||
- `For more information, see [link text](url).`
|
||||
- `To <do this thing>, see [link text](url).`
|
||||
|
||||
### External links
|
||||
|
||||
Minimize external links. They break over time and are hard to maintain. When you must link externally, prefer official documentation (e.g., Vite docs, Webpack docs) over blog posts or third-party guides.
|
||||
|
||||
## Lists
|
||||
|
||||
- Use ordered lists for sequences of steps.
|
||||
- Use unordered lists when order doesn't matter.
|
||||
- Use dashes (`-`) for unordered lists.
|
||||
- Start ordered list items with `1.` (Markdown auto-increments).
|
||||
- Make list items parallel in structure.
|
||||
- Add a colon after the introductory phrase.
|
||||
- Don't use list items to complete an introductory sentence.
|
||||
|
||||
Do:
|
||||
|
||||
```markdown
|
||||
You can clear the cache in the following ways:
|
||||
|
||||
- Delete the `.nx/cache` directory manually.
|
||||
- Run `nx reset` to clear all cached results.
|
||||
```
|
||||
|
||||
Don't:
|
||||
|
||||
```markdown
|
||||
You can clear the cache by:
|
||||
|
||||
- Deleting the `.nx/cache` directory manually.
|
||||
- Running `nx reset`.
|
||||
```
|
||||
|
||||
## Tables
|
||||
|
||||
Use tables for structured data that benefits from a matrix layout. For simple lists of items with descriptions, use a regular list instead.
|
||||
|
||||
- Don't leave cells empty. Use "N/A" or "None."
|
||||
- Use sentence case for headers.
|
||||
- Keep the header and delimiter rows the same length.
|
||||
|
||||
## Nx-specific terminology
|
||||
|
||||
Use these terms consistently. When writing about Nx concepts, use the exact term from this list.
|
||||
|
||||
| Term | Usage notes |
|
||||
| -------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| workspace | The root directory managed by Nx. Not "repo" or "monorepo" when referring to Nx's context. |
|
||||
| project | An app or library within the workspace. |
|
||||
| target | A task that can be run for a project (e.g., `build`, `test`, `lint`). |
|
||||
| executor | The implementation behind a target. Not "builder." |
|
||||
| generator | Code scaffolding tool. Not "schematic." |
|
||||
| plugin | An Nx plugin that provides executors, generators, or graph inference. |
|
||||
| task | A specific invocation of a target for a project (e.g., `myapp:build`). |
|
||||
| task pipeline | The dependency graph between tasks. Not "task orchestration" or "task graph" in user-facing docs. |
|
||||
| project graph | The dependency graph between projects. |
|
||||
| affected | Projects impacted by a code change. |
|
||||
| cache / cached | Not "memoized" or "stored results." |
|
||||
| remote caching | Sharing cached results across machines. Specific product: "Nx Replay." |
|
||||
| Nx Cloud | The hosted CI/CD product. Always capitalized. |
|
||||
| Nx Console | The IDE extension. Always capitalized. |
|
||||
| Nx Agents | Distributed task execution product. Always capitalized. |
|
||||
| Nx Replay | Remote caching product. Always capitalized. |
|
||||
| `nx.json` | Always in code style. |
|
||||
| `project.json` | Always in code style. |
|
||||
@@ -0,0 +1,129 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('CLI sub-command formatting', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/docs/reference/nx-commands');
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Nx Commands' })
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('parent commands render as h2 and sub-commands as h3', async ({
|
||||
page,
|
||||
}) => {
|
||||
const mainContent = page.getByTestId('main-pane');
|
||||
|
||||
// "nx show" should be an h2 (top-level parent command)
|
||||
const showHeading = mainContent.getByRole('heading', {
|
||||
name: 'nx show',
|
||||
level: 2,
|
||||
exact: true,
|
||||
});
|
||||
await expect(showHeading).toBeVisible();
|
||||
|
||||
// "nx show projects" should be an h3 (sub-command nested under parent)
|
||||
const showProjectsHeading = mainContent.getByRole('heading', {
|
||||
name: 'nx show projects',
|
||||
level: 3,
|
||||
exact: true,
|
||||
});
|
||||
await expect(showProjectsHeading).toBeVisible();
|
||||
|
||||
// "nx show project" should also be an h3
|
||||
const showProjectHeading = mainContent.getByRole('heading', {
|
||||
name: 'nx show project',
|
||||
level: 3,
|
||||
exact: true,
|
||||
});
|
||||
await expect(showProjectHeading).toBeVisible();
|
||||
});
|
||||
|
||||
test('sub-command usage blocks show the full command name', async ({
|
||||
page,
|
||||
}) => {
|
||||
const mainContent = page.getByTestId('main-pane');
|
||||
|
||||
// Find the "nx show projects" section and verify its usage block
|
||||
// The usage code block should contain "nx show projects", not "nx projects"
|
||||
const showProjectsHeading = mainContent.getByRole('heading', {
|
||||
name: 'nx show projects',
|
||||
level: 3,
|
||||
exact: true,
|
||||
});
|
||||
await expect(showProjectsHeading).toBeVisible();
|
||||
|
||||
// Get the section between "nx show projects" heading and the next heading.
|
||||
// We look for a code block containing the correct usage pattern.
|
||||
const codeBlocks = mainContent.locator('pre code');
|
||||
const allCodeTexts = await codeBlocks.allTextContents();
|
||||
|
||||
// There should be a usage block with "nx show projects" (full sub-command name)
|
||||
expect(allCodeTexts.some((text) => text.includes('nx show projects'))).toBe(
|
||||
true
|
||||
);
|
||||
|
||||
// There should NOT be a usage block with just "nx projects" (missing parent)
|
||||
expect(
|
||||
allCodeTexts.some(
|
||||
(text) => text.match(/^nx projects/) || text.match(/\nnx projects/)
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('release sub-commands use correct heading and usage format', async ({
|
||||
page,
|
||||
}) => {
|
||||
const mainContent = page.getByTestId('main-pane');
|
||||
|
||||
// "nx release" should be h2
|
||||
const releaseHeading = mainContent.getByRole('heading', {
|
||||
name: 'nx release',
|
||||
level: 2,
|
||||
exact: true,
|
||||
});
|
||||
await expect(releaseHeading).toBeVisible();
|
||||
|
||||
// "nx release version" should be h3
|
||||
const releaseVersionHeading = mainContent.getByRole('heading', {
|
||||
name: 'nx release version',
|
||||
level: 3,
|
||||
exact: true,
|
||||
});
|
||||
await expect(releaseVersionHeading).toBeVisible();
|
||||
|
||||
// Verify usage block includes the full command
|
||||
const codeBlocks = mainContent.locator('pre code');
|
||||
const allCodeTexts = await codeBlocks.allTextContents();
|
||||
|
||||
expect(
|
||||
allCodeTexts.some((text) => text.includes('nx release version'))
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('options and examples are h4 headings excluded from the TOC', async ({
|
||||
page,
|
||||
}) => {
|
||||
const mainContent = page.getByTestId('main-pane');
|
||||
|
||||
// Options/Examples should be h4 headings — linkable but below the TOC threshold (h2-h3)
|
||||
const sharedOptionsHeading = mainContent.getByRole('heading', {
|
||||
name: 'Shared Options',
|
||||
level: 4,
|
||||
});
|
||||
await expect(sharedOptionsHeading.first()).toBeVisible();
|
||||
|
||||
const optionsHeading = mainContent.getByRole('heading', {
|
||||
name: 'Options',
|
||||
level: 4,
|
||||
});
|
||||
await expect(optionsHeading.first()).toBeVisible();
|
||||
|
||||
// They should NOT appear as h2 or h3 (which would put them in the TOC)
|
||||
await expect(
|
||||
mainContent.getByRole('heading', { name: 'Options', level: 2 })
|
||||
).toHaveCount(0);
|
||||
await expect(
|
||||
mainContent.getByRole('heading', { name: 'Options', level: 3 })
|
||||
).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
@@ -93,6 +93,10 @@ const learnGroups: SidebarItems = [
|
||||
link: 'concepts/ci-concepts/parallelization-distribution',
|
||||
},
|
||||
{ label: 'Nx Daemon', link: 'concepts/nx-daemon' },
|
||||
{
|
||||
label: 'Synthetic Monorepos',
|
||||
link: 'concepts/synthetic-monorepos',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -100,6 +104,10 @@ const learnGroups: SidebarItems = [
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ label: 'Run Tasks', link: 'features/run-tasks' },
|
||||
{
|
||||
label: 'Cache Task Results',
|
||||
link: 'features/cache-task-results',
|
||||
},
|
||||
{ label: 'Enhance Your LLM', link: 'features/enhance-ai' },
|
||||
{
|
||||
label: 'Code Organization',
|
||||
@@ -394,7 +402,7 @@ const technologiesGroups: SidebarItems = [
|
||||
},
|
||||
{
|
||||
label: 'Angular Rsbuild',
|
||||
link: 'technologies/angular/angular-rsbuild/create-config',
|
||||
link: 'technologies/angular/angular-rsbuild/introduction',
|
||||
},
|
||||
{ label: 'React', link: 'technologies/react/introduction' },
|
||||
{
|
||||
@@ -891,6 +899,10 @@ const knowledgeBaseGroups: SidebarItems = [
|
||||
label: 'TypeScript',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
label: 'Maintain TypeScript Monorepos',
|
||||
link: 'features/maintain-typescript-monorepos',
|
||||
},
|
||||
...getTechnologyKBItems('typescript'),
|
||||
{
|
||||
label: 'Buildable and Publishable Libraries',
|
||||
@@ -900,10 +912,6 @@ const knowledgeBaseGroups: SidebarItems = [
|
||||
label: 'TypeScript Project Linking',
|
||||
link: 'concepts/typescript-project-linking',
|
||||
},
|
||||
{
|
||||
label: 'Maintain TypeScript Monorepos',
|
||||
link: 'features/maintain-typescript-monorepos',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -1002,10 +1010,6 @@ const referenceGroups: SidebarItems = [
|
||||
{ label: 'nxignore', link: 'reference/nxignore' },
|
||||
{ label: 'Glossary', link: 'reference/glossary' },
|
||||
{ label: 'Releases', link: 'reference/releases' },
|
||||
{
|
||||
label: 'Node/TypeScript Compatibility',
|
||||
link: 'reference/nodejs-typescript-compatibility',
|
||||
},
|
||||
{ label: 'Nx MCP', link: 'reference/nx-mcp' },
|
||||
{ label: 'Nx Console Settings', link: 'reference/nx-console-settings' },
|
||||
{ label: 'Nx Cloud CLI', link: 'reference/nx-cloud-cli' },
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<svg width="980" height="720" viewBox="0 0 980 720" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Defs: arrow markers -->
|
||||
<defs>
|
||||
<marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto" markerUnits="strokeWidth">
|
||||
<polygon points="0 0, 10 3.5, 0 7" fill="#476088"/>
|
||||
</marker>
|
||||
<marker id="arrowGreen" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto" markerUnits="strokeWidth">
|
||||
<polygon points="0 0, 10 3.5, 0 7" fill="#70AF40"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- Outer dotted border: Synthetic Monorepo boundary -->
|
||||
<rect x="40" y="40" width="900" height="590" rx="24" ry="24"
|
||||
stroke="#94A3B8" stroke-width="3" stroke-dasharray="12 6" fill="none"/>
|
||||
|
||||
<!-- "Synthetic Monorepo" label at bottom inside box -->
|
||||
<text x="490" y="665" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="26" font-weight="700" fill="#94A3B8">Synthetic Monorepo</text>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Monorepo A (top-left): a rounded rect with 3 internal projects -->
|
||||
<!-- ============================================ -->
|
||||
<rect x="80" y="70" width="260" height="200" rx="16" ry="16"
|
||||
stroke="#9CA3AF" stroke-width="2" fill="none"/>
|
||||
<text x="210" y="100" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="14" font-weight="600" fill="#9CA3AF">Monorepo A</text>
|
||||
|
||||
<!-- App 1 (blue) -->
|
||||
<circle cx="140" cy="165" r="38" fill="#476088"/>
|
||||
<text x="140" y="161" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">App 1</text>
|
||||
<text x="140" y="178" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#CBD5E1">frontend</text>
|
||||
|
||||
<!-- Lib A (green) -->
|
||||
<circle cx="270" cy="145" r="32" fill="#70AF40"/>
|
||||
<text x="270" y="141" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">Lib A</text>
|
||||
<text x="270" y="157" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#E8F5E9">utils</text>
|
||||
|
||||
<!-- Lib B (green) -->
|
||||
<circle cx="248" cy="222" r="28" fill="#70AF40"/>
|
||||
<text x="248" y="218" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="12" font-weight="600" fill="white">Lib B</text>
|
||||
<text x="248" y="233" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="10" fill="#E8F5E9">ui</text>
|
||||
|
||||
<!-- Internal arrows within Monorepo A -->
|
||||
<line x1="175" y1="155" x2="238" y2="143" stroke="#9CA3AF" stroke-width="1.5" marker-end="url(#arrowBlue)" opacity="0.4"/>
|
||||
<line x1="165" y1="190" x2="225" y2="212" stroke="#9CA3AF" stroke-width="1.5" marker-end="url(#arrowBlue)" opacity="0.4"/>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Monorepo B (right): a rounded rect with 2 internal projects -->
|
||||
<!-- ============================================ -->
|
||||
<rect x="640" y="70" width="260" height="200" rx="16" ry="16"
|
||||
stroke="#9CA3AF" stroke-width="2" fill="none"/>
|
||||
<text x="770" y="100" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="14" font-weight="600" fill="#9CA3AF">Monorepo B</text>
|
||||
|
||||
<!-- App 2 (blue) -->
|
||||
<circle cx="710" cy="170" r="38" fill="#476088"/>
|
||||
<text x="710" y="166" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">App 2</text>
|
||||
<text x="710" y="183" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#CBD5E1">backend</text>
|
||||
|
||||
<!-- Lib C (green) -->
|
||||
<circle cx="840" cy="185" r="32" fill="#70AF40"/>
|
||||
<text x="840" y="181" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">Lib C</text>
|
||||
<text x="840" y="197" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#E8F5E9">auth</text>
|
||||
|
||||
<!-- Internal arrow within Monorepo B -->
|
||||
<line x1="745" y1="175" x2="808" y2="182" stroke="#9CA3AF" stroke-width="1.5" marker-end="url(#arrowBlue)" opacity="0.4"/>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Standalone repos -->
|
||||
<!-- ============================================ -->
|
||||
|
||||
<!-- Lib D (green, standalone, CENTER - pushed down to middle row) -->
|
||||
<circle cx="490" cy="340" r="38" fill="#70AF40"/>
|
||||
<text x="490" y="336" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">Lib D</text>
|
||||
<text x="490" y="352" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#E8F5E9">shared</text>
|
||||
<text x="490" y="390" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" font-weight="500" fill="#9CA3AF">standalone repo</text>
|
||||
|
||||
<!-- App 3 (blue, standalone, bottom-left) -->
|
||||
<circle cx="200" cy="500" r="42" fill="#476088"/>
|
||||
<text x="200" y="496" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">App 3</text>
|
||||
<text x="200" y="513" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#CBD5E1">mobile</text>
|
||||
<text x="200" y="554" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" font-weight="500" fill="#9CA3AF">standalone repo</text>
|
||||
|
||||
<!-- Lib E (green, standalone, bottom-center) -->
|
||||
<circle cx="490" cy="520" r="32" fill="#70AF40"/>
|
||||
<text x="490" y="516" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">Lib E</text>
|
||||
<text x="490" y="532" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#E8F5E9">design</text>
|
||||
<text x="490" y="564" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" font-weight="500" fill="#9CA3AF">standalone repo</text>
|
||||
|
||||
<!-- App 4 (blue, standalone, bottom-right) -->
|
||||
<circle cx="770" cy="500" r="42" fill="#476088"/>
|
||||
<text x="770" y="496" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="13" font-weight="600" fill="white">App 4</text>
|
||||
<text x="770" y="513" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" fill="#CBD5E1">API</text>
|
||||
<text x="770" y="554" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="11" font-weight="500" fill="#9CA3AF">standalone repo</text>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- Cross-repo dependency arrows -->
|
||||
<!-- ============================================ -->
|
||||
|
||||
<!-- App 2 → Lib D (shared): curve down-left -->
|
||||
<path d="M 675 185 C 620 240, 560 280, 525 325" stroke="#476088" stroke-width="2.5" fill="none" marker-end="url(#arrowBlue)"/>
|
||||
|
||||
<!-- Lib A → Lib D: gentle arc down -->
|
||||
<path d="M 300 155 C 370 200, 420 260, 458 322" stroke="#70AF40" stroke-width="2" fill="none" marker-end="url(#arrowGreen)"/>
|
||||
|
||||
<!-- App 3 → Lib B (in Monorepo A): straight up -->
|
||||
<path d="M 210 458 C 220 380, 230 320, 242 252" stroke="#476088" stroke-width="2.5" fill="none" marker-end="url(#arrowBlue)"/>
|
||||
|
||||
<!-- App 3 → Lib E (design): horizontal -->
|
||||
<path d="M 242 500 C 320 490, 400 500, 458 515" stroke="#476088" stroke-width="2.5" fill="none" marker-end="url(#arrowBlue)"/>
|
||||
|
||||
<!-- App 4 → Lib C (in Monorepo B): straight up -->
|
||||
<path d="M 790 458 C 805 380, 820 310, 835 217" stroke="#476088" stroke-width="2.5" fill="none" marker-end="url(#arrowBlue)"/>
|
||||
|
||||
<!-- App 4 → Lib D (shared): arc up-left -->
|
||||
<path d="M 730 490 C 650 460, 570 410, 525 358" stroke="#476088" stroke-width="2.5" fill="none" marker-end="url(#arrowBlue)"/>
|
||||
|
||||
<!-- App 4 → Lib E (design): horizontal left -->
|
||||
<path d="M 728 505 C 660 510, 580 515, 522 518" stroke="#476088" stroke-width="2" fill="none" marker-end="url(#arrowBlue)"/>
|
||||
|
||||
<!-- Lib D → Lib C (cross-repo lib dependency): arc up-right -->
|
||||
<path d="M 525 330 C 620 300, 740 260, 812 200" stroke="#70AF40" stroke-width="2" fill="none" marker-end="url(#arrowGreen)"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
@@ -548,5 +548,10 @@
|
||||
"name": "@berenddeboer/nx-biome",
|
||||
"description": "A self-inferring Nx plugin for using biome to format and lint projects. Supports --batch",
|
||||
"url": "https://github.com/berenddeboer/nx-plugins/tree/main/packages/nx-biome"
|
||||
},
|
||||
{
|
||||
"name": "@berenddeboer/nx-knip",
|
||||
"description": "A self-inferring Nx plugin for using knip to find and fix unused dependencies, exports and files",
|
||||
"url": "https://github.com/berenddeboer/nx-plugins/tree/main/packages/nx-knip"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -24,7 +24,7 @@ By default, the computation hash for something like `nx test remixapp` includes:
|
||||
|
||||
After Nx computes the hash for a task, it then checks if it ran this exact computation before. First, it checks locally, and then if it is missing, and if a remote cache is configured, it checks remotely. If a matching computation is found, Nx retrieves and replays it. This includes restoring files.
|
||||
|
||||
Nx places the right files in the right folders and prints the terminal output. From the user's point of view, the command ran the same, just a lot faster.
|
||||
Nx places the right files in the right folders and prints the terminal output. From the user's point of view, the command ran the same, only a lot faster.
|
||||
|
||||

|
||||
|
||||
@@ -32,7 +32,7 @@ If Nx doesn't find a corresponding computation hash, Nx runs the task, and after
|
||||
|
||||
## Optimizations
|
||||
|
||||
Although conceptually this is fairly straightforward, Nx optimizes the experience for you. For instance, Nx:
|
||||
Nx optimizes the caching experience in several ways. For instance, Nx:
|
||||
|
||||
- Captures stdout and stderr to make sure the replayed output looks the same, including on Windows.
|
||||
- Minimizes the IO by remembering what files are replayed where.
|
||||
@@ -46,7 +46,7 @@ As your workspace grows, the task graph looks more like this:
|
||||
All of these optimizations are crucial for making Nx usable for any non-trivial workspace. Only the minimum amount of
|
||||
work happens. The rest is either left as is or restored from the cache.
|
||||
|
||||
## Fine-tuning Nx's Cache
|
||||
## Fine-tuning the Nx cache
|
||||
|
||||
Each cacheable task defines a set of inputs and outputs. Inputs are factors Nx considers when calculating the computation hash.
|
||||
Outputs are files that will be cached and restored when the computation hash matches.
|
||||
|
||||
@@ -6,9 +6,7 @@ sidebar:
|
||||
filter: 'type:Concepts'
|
||||
---
|
||||
|
||||
Nx is a VSCode of build tools, with a powerful core, driven by metadata, and extensible through [plugins](/docs/concepts/nx-plugins). Nx works with a
|
||||
few concepts to drive your monorepo efficiently, and effectively. This guide covers the mental model around how Nx works
|
||||
with project graphs, task graphs, affected commands, computation hashing and caching.
|
||||
Nx is a VSCode of build tools, with a powerful core, driven by metadata, and extensible through [plugins](/docs/concepts/nx-plugins). Nx works with a few core concepts to drive your monorepo efficiently: project graphs, task graphs, affected commands, computation hashing, and caching.
|
||||
|
||||
## The project graph
|
||||
|
||||
@@ -267,7 +265,7 @@ With this, running the same test command creates the following task graph:
|
||||
|
||||
This often makes more sense for builds, where to build `app1`, you want to build `lib` first. You can also define
|
||||
similar
|
||||
relationships between targets of the same project, including a test target that depends on the build.
|
||||
relationships between targets of the same project, including a test target that depends on the build. Learn more about configuring task pipelines in [Task Pipeline Configuration](/docs/concepts/task-pipeline-configuration).
|
||||
|
||||
A task graph can contain different targets, and those can run in parallel. For instance, as Nx is building `app2`, it
|
||||
can be testing `app1` at the same time.
|
||||
@@ -287,7 +285,7 @@ and `lib:test`.
|
||||
|
||||
When you run `nx run-many -t test`, you are telling Nx to do this for all the projects.
|
||||
|
||||
As your workspace grows, retesting all projects becomes too slow. To address this Nx implements code change analysis to
|
||||
As your workspace grows, retesting all projects becomes too slow. To address this Nx implements code change analysis via the [`affected` command](/docs/features/ci-features/affected) to
|
||||
get the min set of projects that need to be retested. How does it work?
|
||||
|
||||
When you run `nx affected -t test`, Nx looks at the files you changed in your PR, it will look at the nature of
|
||||
@@ -304,104 +302,19 @@ that `app2` cannot be affected by it, so it only retests `app1`.
|
||||
|
||||
## Computation hashing and caching
|
||||
|
||||
Nx runs the tasks in the task graph in the right order. Before running the task, Nx computes its computation hash. As
|
||||
long as the computation hash is the same, the output of running the task is the same.
|
||||
|
||||
How does Nx do it?
|
||||
|
||||
By default, the computation hash for say `nx test app1` includes:
|
||||
|
||||
- All the source files of `app1` and `lib`
|
||||
- Relevant global configuration
|
||||
- Versions of external dependencies
|
||||
- [Runtime values provisioned by the user](/docs/reference/inputs#runtime-inputs)
|
||||
- CLI Command flags
|
||||
Before running a task, Nx computes a hash based on source files, configuration, dependencies, and other inputs. If the hash matches a previous run, the cached result is replayed — including terminal output and file artifacts. If not, Nx runs the task and stores the result for next time.
|
||||
|
||||

|
||||
|
||||
This behavior is customizable. For instance, lint checks may only depend on the source code of the project and global
|
||||
configs. Builds can depend on the `.d.ts` files of the compiled libs instead of their source.
|
||||
|
||||
After Nx computes the hash for a task, it then checks if it ran this exact computation before. First, it checks locally,
|
||||
and then if it is missing, and if a remote cache is configured, it checks remotely.
|
||||
|
||||
If Nx finds the computation, Nx retrieves it and replays it. Nx places the right files in the right folders and prints
|
||||
the terminal output. So from the user's point of view, the command ran the same, just a lot faster.
|
||||
Nx checks the local cache first, then the [remote cache](/docs/features/ci-features/remote-cache) if configured. From the user's point of view, the command ran the same, only a lot faster.
|
||||
|
||||

|
||||
|
||||
If Nx doesn't find this computation, Nx runs the task, and after it completes, it takes the outputs and the terminal
|
||||
output and stores it locally (and if configured remotely). All of this happens transparently, so you don't have to worry
|
||||
about it.
|
||||
|
||||
Although conceptually this is fairly straightforward, Nx optimizes this to make this experience good for you. For
|
||||
instance, Nx:
|
||||
|
||||
- Captures stdout and stderr to make sure the replayed output looks the same, including on Windows.
|
||||
- Minimizes the IO by remembering what files are replayed where.
|
||||
- Only shows relevant output when processing a large task graph.
|
||||
- Provides affordances for troubleshooting cache misses. And many other optimizations.
|
||||
|
||||
As your workspace grows, the task graph looks more like this:
|
||||
|
||||
{% graph height="200px" type="task"%}
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskIds": ["lib:test"],
|
||||
"taskGraph": {
|
||||
"roots": ["lib:test"],
|
||||
"tasks": {
|
||||
"lib:test": {
|
||||
"id": "lib:test",
|
||||
"target": {
|
||||
"project": "lib",
|
||||
"target": "test"
|
||||
},
|
||||
"projectRoot": "libs/lib",
|
||||
"overrides": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% /graph %}
|
||||
|
||||
All of these optimizations are crucial for making Nx usable for any non-trivial workspace. Only the minimum amount of
|
||||
work happens. The rest is either left as is or restored from the cache.
|
||||
See [How Caching Works](/docs/concepts/how-caching-works) for the complete list of hash inputs, cache configuration options, and optimization details.
|
||||
|
||||
## Distributed task execution
|
||||
|
||||
Nx supports running commands across multiple machines. You can either set it up by hand or use Nx Cloud. [Read the comparison of the two approaches.](https://nx.dev/blog/distributing-ci-binning-and-distributed-task-execution)
|
||||
|
||||
When using the distributed task execution, Nx is able to run any task graph on many agents instead of locally.
|
||||
|
||||
For instance, `nx affected --build` won't run the build locally (which can take hours for large workspaces). Instead,
|
||||
it will send the Task Graph to Nx Cloud. Nx Cloud Agents will then pick up the tasks they can run and execute them.
|
||||
|
||||
Note that this happens transparently. If an agent builds `app1`, it will fetch the outputs for `lib` if it doesn't have
|
||||
them
|
||||
already.
|
||||
|
||||
As agents complete tasks, the main job where you invoked `nx affected --build` will start receiving created files and
|
||||
terminal outputs.
|
||||
|
||||
After `nx affected --build` completes, the machine will have the build files and all the terminal outputs as if it ran
|
||||
it locally.
|
||||
For large workspaces, even with caching, running all tasks on a single machine can be slow. [Nx Agents](/docs/features/ci-features/distribute-task-execution) can distribute the task graph across multiple machines, running tasks in parallel while using [remote caching](/docs/features/ci-features/remote-cache) to share artifacts between agents. From your CI's perspective, the results appear as if everything ran on a single machine.
|
||||
|
||||

|
||||
|
||||
@@ -410,5 +323,5 @@ it locally.
|
||||
- Nx is able to analyze your source code to create a Project Graph.
|
||||
- Nx can use the project graph and information about projects' targets to create a Task Graph.
|
||||
- Nx is able to perform code-change analysis to create the smallest task graph for your PR.
|
||||
- Nx supports computation caching to never execute the same computation twice. This computation cache is pluggable and
|
||||
- Nx supports [computation caching](/docs/features/cache-task-results) to never execute the same computation twice. This computation cache is pluggable and
|
||||
can be distributed.
|
||||
|
||||
@@ -49,7 +49,7 @@ To see information about the running Nx Daemon (such as its background process I
|
||||
## Customizing the socket location
|
||||
|
||||
The Nx Daemon uses a unix socket to communicate between the daemon and the Nx processes. By default this socket gets placed in a temp directory. If you are using Nx in a docker-compose environment, however, you may want to run the daemon manually
|
||||
and control its location to enable sharing the daemon among your docker containers. To do so, simply set the NX_DAEMON_SOCKET_DIR environment variable to a shared directory.
|
||||
and control its location to enable sharing the daemon among your docker containers. To do so, set the `NX_DAEMON_SOCKET_DIR` environment variable to a shared directory.
|
||||
|
||||
## Daemon Behavior in Containers
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ For example, plugins can accomplish the following:
|
||||
- [Configure Nx cache settings](/docs/concepts/inferred-tasks) for a tool. The [`@nx/webpack`](/docs/technologies/build-tools/webpack/introduction) plugin can automatically configure the [inputs](/docs/guides/tasks--caching/configure-inputs) and [outputs](/docs/guides/tasks--caching/configure-outputs) for a `build` task based on the settings in the `webpack.config.js` file it uses.
|
||||
- [Update tooling configuration](/docs/features/automate-updating-dependencies) when upgrading the tool version. When Storybook 7 introduced a [new format](https://storybook.js.org/blog/storybook-csf3-is-here) for their configuration files, anyone using the [`@nx/storybook`](/docs/technologies/test-tools/storybook/introduction) plugin could automatically apply those changes to their repository when upgrading.
|
||||
- [Set up a tool](/docs/features/generate-code) for the first time. With the [`@nx/playwright`](/docs/technologies/test-tools/playwright/introduction) plugin installed, you can use the `@nx/playwright:configuration` code generator to set up Playwright tests in an existing project.
|
||||
- [Run a tool in an advanced way](/docs/concepts/executors-and-configurations). The [`@nx/js`](/docs/technologies/typescript/introduction) plugin's [`@nx/js:tsc` executor](/docs/technologies/typescript/executors#tsc) combines Nx's understanding of your repository with Typescript's native batch mode feature to make your builds [even more performant](/docs/technologies/typescript/guides/enable-tsc-batch-mode).
|
||||
- [Run a tool in an advanced way](/docs/concepts/executors-and-configurations). The [`@nx/js`](/docs/technologies/typescript/introduction) plugin's [`@nx/js:tsc` executor](/docs/technologies/typescript/executors#tsc) combines the Nx understanding of your repository with Typescript's native batch mode feature to make your builds [even more performant](/docs/technologies/typescript/guides/enable-tsc-batch-mode).
|
||||
|
||||
## Plugin Features
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: Synthetic Monorepos
|
||||
description: Learn how synthetic monorepos connect separate repositories into a unified dependency graph, giving you monorepo intelligence without moving code.
|
||||
---
|
||||
|
||||
Most organizations don't have a single giant monorepo. They have a handful of monorepos per team or domain, plus dozens of standalone repos. Consolidating everything into one repository is not just a technical challenge. The organizational side (bringing teams along, changing workflows, ensuring adoption) is often harder than the code migration itself.
|
||||
|
||||
Synthetic monorepos let you get monorepo benefits without that consolidation.
|
||||
|
||||
## What is a synthetic monorepo?
|
||||
|
||||
A synthetic monorepo connects separate repositories into a unified dependency graph without moving any code. Which repo depends on which, what a change affects downstream, how projects relate across teams: all of that becomes visible automatically.
|
||||
|
||||

|
||||
|
||||
Unlike a traditional monorepo where all code lives in one repository, a synthetic monorepo leaves each repository where it is. Instead, it builds a cross-repo graph that tooling can reason about, just as if the code were in one place.
|
||||
|
||||
## What synthetic monorepos enable
|
||||
|
||||
A synthetic monorepo addresses several downsides of a polyrepo setup:
|
||||
|
||||
**Visibility** — An automatic cross-repo dependency graph shows which repo depends on which and what a change affects downstream. Always up to date, discovered from actual code — not a manually maintained spreadsheet or catalog. Nx implements this through the [Workspace Graph](/docs/enterprise/polygraph).
|
||||
|
||||
**Coordination** — Cross-repo changes no longer require manually sequencing PRs, managing compatibility, and coordinating release order. Tooling on top of the graph enables impact analysis, coordinated changes, and conformance checking across repo boundaries.
|
||||
|
||||
**Governance** — Organizational standards apply across every connected repo through [conformance rules](/docs/enterprise/conformance). Scheduled [custom workflows](/docs/enterprise/custom-workflows) check repos continuously — even ones nobody has touched in months. Detection and enforcement happen automatically, not through tickets and follow-ups.
|
||||
|
||||
**CI intelligence** — [Affected detection](/docs/concepts/mental-model#affected-commands), [remote caching](/docs/concepts/how-caching-works), and [distributed task execution](/docs/concepts/ci-concepts/parallelization-distribution) work across the full graph, not just within a single repo.
|
||||
|
||||
**AI agents** — AI coding agents are [dramatically less effective in polyrepos](https://youtu.be/alIto5fqrfk) — they can only see one repo at a time, so cross-repo features require you to manually shuttle context between sessions. A synthetic monorepo gives agents cross-repo visibility, enabling coordinated changes, parallel execution, and automatic PR creation across boundaries. [Self-healing CI](/docs/features/ci-features/self-healing-ci) catches failures automatically.
|
||||
|
||||
## When to use a synthetic monorepo vs. a real monorepo
|
||||
|
||||
A real monorepo is the best option when you can consolidate. It gives you atomic commits, a single toolchain, and the simplest mental model.
|
||||
|
||||
A synthetic monorepo is the better starting point when:
|
||||
|
||||
- **Consolidation isn't feasible yet:** team autonomy concerns, divergent CI setups, or hundreds of repos make migration impractical.
|
||||
- **You need cross-repo visibility now:** you can't wait months for a migration to see how projects relate across teams.
|
||||
- **Teams need to stay autonomous:** each team keeps their repo, workflow, and release cadence while still participating in a unified graph.
|
||||
|
||||
The two aren't mutually exclusive. Start synthetic for org-wide visibility, then consolidate tightly coupled teams into real monorepos where it makes sense.
|
||||
|
||||
## Synthetic monorepos with Nx Polygraph
|
||||
|
||||
Nx implements synthetic monorepos through [Nx Polygraph](/docs/enterprise/polygraph). Polygraph connects existing repositories into a unified, intelligent graph that powers the visibility, coordination, and CI features described above. It works with any repo, even those that don't use Nx, and requires zero changes to target repos.
|
||||
|
||||
Learn more about [getting started with Nx Polygraph](/docs/enterprise/polygraph).
|
||||
@@ -65,7 +65,7 @@ This becomes even more evident when you run tasks in parallel. You cannot just n
|
||||
|
||||

|
||||
|
||||
Nx allows you to define task dependencies in the form of "rules", which are then followed when running tasks. There's a [detailed recipe](/docs/guides/tasks--caching/defining-task-pipeline) but here's the high-level overview:
|
||||
Define task dependencies in the form of "rules", which are then followed when running tasks. There's a [detailed recipe](/docs/guides/tasks--caching/defining-task-pipeline) but here's the high-level overview:
|
||||
|
||||
```jsonc title="nx.json"
|
||||
{
|
||||
|
||||
@@ -187,7 +187,7 @@ Each project's `tsconfig.json` file should extend the `tsconfig.base.json` file
|
||||
}
|
||||
```
|
||||
|
||||
Each project's `tsconfig.lib.json` file extends the project's `tsconfig.json` file and adds `references` to the `tsconfig.lib.json` files of project dependencies.
|
||||
Each project's `tsconfig.lib.json` file extends the `tsconfig.base.json` file and adds `references` to the `tsconfig.lib.json` files of project dependencies.
|
||||
|
||||
```jsonc title="packages/cart/tsconfig.lib.json"
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Create and publish custom Nx Conformance rules to your Nx Cloud org
|
||||
filter: 'type:Guides'
|
||||
---
|
||||
|
||||
[Nx Cloud Enterprise](https://nx.dev/enterprise) allows you to publish your organization's [Nx Conformance](/docs/enterprise/conformance) rules to your Nx Cloud Organization, and consume them in any of your other Nx Workspaces without having to deal with the complexity and friction of dealing with a private NPM registry or similar. Authentication is handled automatically through your Nx Cloud connection and rules are downloaded and applied based on your preferences configured in the Nx Cloud UI.
|
||||
[Nx Cloud Enterprise](https://nx.dev/enterprise) lets you publish custom [Nx Conformance](/docs/enterprise/conformance) rules to your Nx Cloud Organization and consume them across workspaces — no private NPM registry needed. See [Configure Conformance Rules in Nx Cloud](/docs/enterprise/configure-conformance-rules-in-nx-cloud) for how to manage published rules in the UI.
|
||||
|
||||
Let's create a custom rule which we can then publish to Nx Cloud. We will first create a new library project to contain our rule (and any others we might create in the future):
|
||||
|
||||
|
||||
@@ -128,6 +128,184 @@ Nx uses the paths from `tsconfig.base.json` when running plugins locally, but us
|
||||
|
||||

|
||||
|
||||
## Generator Schema Properties
|
||||
|
||||
Beyond the standard [JSON Schema](https://json-schema.org/) properties like `type`, `description`, `enum`, and `default`, Nx recognizes several custom properties in your `schema.json` that control CLI prompting behavior and how [Nx Console](/docs/getting-started/editor-setup) renders the generator form.
|
||||
|
||||
### `$default`
|
||||
|
||||
Provides a dynamic default value from a runtime source. Used to map positional CLI arguments and other context to schema properties.
|
||||
|
||||
```json
|
||||
// schema.json
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Source | Description |
|
||||
| ----------------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| `{ "$source": "argv", "index": 0 }` | Uses the positional CLI argument at the given index |
|
||||
| `{ "$source": "projectName" }` | Uses the current project name. Also triggers project autocomplete in the CLI and Nx Console |
|
||||
| `{ "$source": "workingDirectory" }` | Uses the current working directory relative to the workspace root |
|
||||
| `{ "$source": "unparsed" }` | Collects any extra arguments not matched by other schema properties |
|
||||
|
||||
### `x-prompt`
|
||||
|
||||
Defines an interactive prompt shown when the option is not provided on the command line. Can be a simple string or a structured object for more control.
|
||||
|
||||
```json
|
||||
// schema.json
|
||||
{
|
||||
"properties": {
|
||||
"style": {
|
||||
"type": "string",
|
||||
"description": "The file extension to be used for style files.",
|
||||
"x-prompt": {
|
||||
"message": "Which stylesheet format would you like to use?",
|
||||
"type": "list",
|
||||
"items": [
|
||||
{ "value": "css", "label": "CSS" },
|
||||
{ "value": "scss", "label": "SASS (.scss)" },
|
||||
{ "value": "less", "label": "LESS" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Short form:** `"x-prompt": "What name would you like to use?"` — displays a simple text prompt.
|
||||
|
||||
**Long form object properties:**
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------- | ------------------------------------------------ | ----------------------------------------------------- |
|
||||
| `message` | `string` | The prompt text displayed to the user |
|
||||
| `type` | `string` | Prompt type: `"input"`, `"list"`, or `"confirmation"` |
|
||||
| `multiselect` | `boolean` | Allow selecting multiple items (for `"list"` type) |
|
||||
| `items` | `(string \| { label: string, value: string })[]` | Choices for `"list"` type prompts |
|
||||
|
||||
In Nx Console, the `message` is shown as a tooltip on the field and `items` labels are shown as option descriptions.
|
||||
|
||||
### `x-priority`
|
||||
|
||||
Controls the visibility and ordering of an option in the Nx Console Generate form.
|
||||
|
||||
```json
|
||||
// schema.json
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"x-priority": "important"
|
||||
},
|
||||
"skipFormat": {
|
||||
"type": "boolean",
|
||||
"x-priority": "internal"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Value | Effect |
|
||||
| ------------- | ------------------------------------------------------------- |
|
||||
| `"important"` | Field appears near the top of the form, after required fields |
|
||||
| `"internal"` | Field is hidden from the form by default |
|
||||
|
||||
Options in the Nx Console form are sorted: **required** > **important** > **regular** > **deprecated** > **internal**.
|
||||
|
||||
### `x-deprecated`
|
||||
|
||||
Marks an option as deprecated. Deprecated options are sorted to the bottom of the form in Nx Console and display a warning.
|
||||
|
||||
```json
|
||||
// schema.json
|
||||
{
|
||||
"properties": {
|
||||
"oldOption": {
|
||||
"type": "string",
|
||||
"x-deprecated": "Use 'newOption' instead."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The value can be `true` (boolean) or a string with the deprecation reason/migration guidance.
|
||||
|
||||
### `x-dropdown`
|
||||
|
||||
Tells both the CLI and Nx Console to present a dropdown populated with workspace data.
|
||||
|
||||
```json
|
||||
// schema.json
|
||||
{
|
||||
"properties": {
|
||||
"projectName": {
|
||||
"type": "string",
|
||||
"x-dropdown": "projects"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Currently only `"projects"` is supported, which shows all projects in the workspace.
|
||||
|
||||
{% aside type="note" title="Automatic project autocomplete" %}
|
||||
The CLI and Nx Console also automatically provide project autocomplete for any property named `project` or `projectName`, or that has `$default` set to `{ "$source": "projectName" }` — even without `x-dropdown`.
|
||||
{% /aside %}
|
||||
|
||||
### `x-hint`
|
||||
|
||||
Displays a hint popover next to the field label in the Nx Console Generate form. Use this for brief contextual guidance that doesn't belong in the main `description`.
|
||||
|
||||
```json
|
||||
// schema.json
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"x-hint": "You can provide a nested path like my-dir/my-lib"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `x-completion-type` and `x-completion-glob`
|
||||
|
||||
These properties are used by Nx Console's language server to provide autocomplete suggestions when editing configuration files like `project.json` or `nx.json`.
|
||||
|
||||
```json
|
||||
// schema.json
|
||||
{
|
||||
"properties": {
|
||||
"tsConfig": {
|
||||
"type": "string",
|
||||
"x-completion-type": "file",
|
||||
"x-completion-glob": "tsconfig*.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| `x-completion-type` value | Description |
|
||||
| ------------------------- | ------------------------------------------------------------------------- |
|
||||
| `"file"` | Autocomplete with file paths (optionally filtered by `x-completion-glob`) |
|
||||
| `"directory"` | Autocomplete with directory paths |
|
||||
| `"projects"` | Autocomplete with workspace project names |
|
||||
| `"targets"` | Autocomplete with available target names |
|
||||
| `"targetsWithDeps"` | Autocomplete targets, including `^target` syntax for dependencies |
|
||||
| `"tags"` | Autocomplete with project tags |
|
||||
| `"projectTarget"` | Autocomplete with `project:target` format |
|
||||
|
||||
## Generator Utilities
|
||||
|
||||
The [`@nx/devkit` package](/docs/reference/devkit) provides many utility functions that can be used in generators to help with modifying files, reading and updating configuration files, and working with an Abstract Syntax Tree (AST).
|
||||
|
||||
@@ -11,12 +11,10 @@ src="https://youtu.be/NF1__N_snog"
|
||||
title="Remote Caching with Nx Replay"
|
||||
/%}
|
||||
|
||||
Repeatedly rebuilding and retesting the same code is costly — not just in terms of wasted resources, but also in terms of developer time. To solve this, Nx includes a sophisticated computation caching system that ensures **code is never rebuilt twice**, saving you both time and resources.
|
||||
Nx [caches task results locally](/docs/features/cache-task-results) to avoid rebuilding the same code twice. Remote caching extends this by **sharing the cache across your team and CI**.
|
||||
|
||||

|
||||
|
||||
By default, Nx [caches task computations locally](/docs/features/cache-task-results), but the biggest benefit comes from **sharing this cache across your team and in CI**.
|
||||
|
||||
- **Zero config** and **secure** by default
|
||||
- Drastically **speeds up task execution times** during local development, and more critically in CI
|
||||
- **Saves money on CI/CD costs** by reducing the number of tasks that need to be executed (we observed 30-70% faster CI & half the cost)
|
||||
|
||||
@@ -16,7 +16,7 @@ Nx Cloud Self-Healing CI is an **AI-powered system that automatically detects, a
|
||||
|
||||
- **Improves Time to Green (TTG):** Automatically proposes fixes when tasks fail, significantly reducing the time to get your PR merge-ready. No more babysitting PRs.
|
||||
- **Keeps You in the Flow:** Get notified about failed PRs and proposed fixes via PR/MR comments or directly in your editor with Nx Console (VS Code, Cursor, or WebStorm). Review, approve, and keep working while AI handles the rest.
|
||||
- **Leverages Deep Context:** AI agents understand your workspace structure, project relationships, and build configurations through Nx's project graph and metadata.
|
||||
- **Leverages Deep Context:** AI agents understand your workspace structure, project relationships, and build configurations through the Nx [project graph](/docs/features/explore-graph) and metadata.
|
||||
- **Non-Invasive Integration:** Works with your existing CI provider without overhauling your current setup.
|
||||
|
||||
## Enable Self-Healing CI
|
||||
|
||||
@@ -83,12 +83,10 @@ If your repository is using package manager workspaces, Nx will use those settin
|
||||
|
||||
### Inferred Tasks with Tooling Plugins
|
||||
|
||||
Nx provides [plugins](/docs/concepts/nx-plugins) for tools that run tasks, like Vite, TypeScript, Playwright or Jest. These plugins can automatically [infer the Nx-specific task configuration](/docs/concepts/inferred-tasks) based on the tooling configuration files that already exist.
|
||||
Nx [plugins](/docs/concepts/nx-plugins) for tools like Vite, TypeScript, Playwright, and Jest automatically [infer task configuration](/docs/concepts/inferred-tasks) from your existing tooling config files — keeping them as the single source of truth.
|
||||
|
||||
In the example below, because the `/apps/cart/vite.config.ts` file exists, Nx knows that the `cart` project can run a `build` task using Vite. If you expand the `build` task, you can also see that Nx configured the output directory for the [cache](/docs/features/cache-task-results) to match the `build.outDir` provided in the Vite configuration file.
|
||||
|
||||
With inferred tasks, you can keep your tooling configuration file as the one source of truth for that tool's configuration, instead of adding an extra layer of configuration on top.
|
||||
|
||||
```ts
|
||||
// /apps/cart/vite.config.ts
|
||||
/// <reference types='vitest' />
|
||||
|
||||
@@ -9,7 +9,7 @@ filter: 'type:Features'
|
||||
|
||||
AI coding assistants often hallucinate outdated Nx commands and lack context about your workspace structure. Without workspace awareness, they suggest commands that don't exist or miss project relationships entirely.
|
||||
|
||||
Nx's AI integration gives assistants accurate, real-time information about your workspace, projects, and available commands—making them smarter when working in an Nx monorepo and more autonomous when iterating on CI failures.
|
||||
The Nx AI integration gives assistants accurate, real-time information about your workspace, projects, and available commands, making them smarter when working in an Nx monorepo and more autonomous when iterating on CI failures.
|
||||
|
||||
## Configure Nx AI Integration
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ sidebar:
|
||||
pagefind: false
|
||||
---
|
||||
|
||||
Start your journey with Nx. Whether you're creating a new project or adding Nx to an existing codebase, we've got you covered.
|
||||
Create a new workspace or add Nx to an existing project.
|
||||
|
||||
Choose your path based on your current setup and requirements. Nx works with any technology stack and can be adopted incrementally.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Nx is a build system for monorepos. It helps you **develop faster** and **keep C
|
||||
Monorepos have many advantages and are especially powerful for AI-assisted development. But as teams and codebases grow, monorepos are hard to scale:
|
||||
|
||||
- **Slow builds and tests** - Hundreds or thousands of tasks compete for CI resources.
|
||||
- **Complex task pipelines** - Projects depend on each other, so tasks need to run in the right order — and that's hard to manage by hand.
|
||||
- **Complex task pipelines** - Projects depend on each other, so tasks need to run in the right order, and that's hard to manage by hand.
|
||||
- **Flaky CI** - Longer pipelines lead to random failures and inconsistent results between local and CI environments.
|
||||
- **Architectural erosion** - Without clear boundaries, unwanted dependencies creep in and projects become tightly coupled.
|
||||
|
||||
@@ -40,7 +40,7 @@ nx run-many -t build test # Run across all projects
|
||||
|
||||
{% callout type="deepdive" title="How does Nx run tasks?" %}
|
||||
|
||||
At the very core, Nx is a super fast, intelligent task runner. Let's take the example of an NPM workspace. This could be a project's `package.json`:
|
||||
At its core, Nx is a fast, intelligent task runner. Take the example of an NPM workspace. This could be a project's `package.json`:
|
||||
|
||||
```json
|
||||
// package.json
|
||||
@@ -53,7 +53,7 @@ At the very core, Nx is a super fast, intelligent task runner. Let's take the ex
|
||||
}
|
||||
```
|
||||
|
||||
Then you can simply add Nx to your root `package.json`:
|
||||
Then add Nx to your root `package.json`:
|
||||
|
||||
```json
|
||||
// package.json
|
||||
@@ -72,7 +72,7 @@ nx build my-project
|
||||
|
||||
This will execute the `build` script from `my-project`'s `package.json`, equivalent to running `npm run build` in that project directory.
|
||||
|
||||
Similarly you [can run tasks across all projects](/docs/features/run-tasks), just specific ones or just those from projects you touched.
|
||||
Similarly you [can run tasks across all projects](/docs/features/run-tasks), specific ones, or only those from projects you touched.
|
||||
|
||||
From there, you can gradually enhance your setup by adding features like [task caching](/docs/features/cache-task-results), adding [plugins](/docs/plugin-registry), optimizing your CI via [task distribution](/docs/features/ci-features/distribute-task-execution), and many more powerful capabilities as your needs grow.
|
||||
|
||||
@@ -80,7 +80,7 @@ From there, you can gradually enhance your setup by adding features like [task c
|
||||
|
||||
## Start Small, Grow as Needed
|
||||
|
||||
Nx is modular. Start with just the CLI and add capabilities as your needs grow.
|
||||
Nx is modular. Start with the CLI and add capabilities as your needs grow.
|
||||
|
||||
| Component | What It Does |
|
||||
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -115,7 +115,7 @@ Nx can also connect multiple repositories into a synthetic monorepo, letting you
|
||||
|
||||
{% linkcard title="Concepts" description="Improve your understanding of how Nx works under the hood." href="/docs/concepts" /%}
|
||||
|
||||
{% linkcard title="Features" description="Discover all the powerful features that Nx provides to streamline your workflow." href="/docs/features" /%}
|
||||
{% linkcard title="Features" description="Explore Nx features like caching, task orchestration, and CI optimization." href="/docs/features" /%}
|
||||
|
||||
{% /cardgrid %}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ filter: 'type:Features'
|
||||
|
||||
{% youtube src="https://www.youtube.com/watch?v=cDBihpB3SbI" title="Nx and Nx Cloud" width="100%" /%}
|
||||
|
||||
CI is challenging and it's **not your fault**. It's a fundamental issue with how the current, traditional CI execution model works. Nx Cloud adopts a new **task-based** CI model which allows you to overcome slowness and unreliability of the current VM-based CI model.
|
||||
CI is challenging and it's **not your fault**. It's a fundamental issue with how the current, traditional CI execution model works. Nx Cloud adopts a new **task-based** CI model that overcomes slowness and unreliability of the current VM-based CI model.
|
||||
_(Dive deeper into the [task based CI execution model](https://nx.dev/blog/reliable-ci-a-new-execution-model-fixing-both-flakiness-and-slowness))_
|
||||
|
||||
Nx Cloud improves many aspects of the CI/CD process:
|
||||
@@ -17,7 +17,7 @@ Nx Cloud improves many aspects of the CI/CD process:
|
||||
|
||||
## Connect your workspace to Nx Cloud
|
||||
|
||||
The most straightforward way to connect your Nx workspace with Nx Cloud is via the web application:
|
||||
To connect your Nx workspace with Nx Cloud, use the web application:
|
||||
|
||||
{% call_to_action variant="default" title="Create a new or connect an existing repo" url="https://cloud.nx.app/get-started?utm_source=nx-dev&utm_medium=nx-cloud_intro&utm_campaign=try-nx-cloud" description="Setup takes less than 2 minutes" /%}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ filter: 'type:Guides'
|
||||
|
||||
{% course_video src="https://youtu.be/3hW53b1IJ84" courseTitle="From PNPM Workspaces to Distributed CI" courseUrl="https://nx.dev/courses/pnpm-nx-next/lessons-01-nx-init" /%}
|
||||
|
||||
Nx is designed for incremental adoption. Start with just task running and [caching](/docs/features/cache-task-results), then add [plugins](/docs/technologies), [CI integrations](/docs/guides/nx-cloud/setup-ci), or other capabilities as your needs grow.
|
||||
Nx is designed for incremental adoption. Start with task running and [caching](/docs/features/cache-task-results), then add [plugins](/docs/technologies), [CI integrations](/docs/guides/nx-cloud/setup-ci), or other capabilities as your needs grow.
|
||||
|
||||
Add Nx to any existing project with a single command:
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ This plugin system helps teams scale organizationally by:
|
||||
|
||||
Nx has been battle-tested since 2016:
|
||||
|
||||
- ~5 million downloads per week
|
||||
- ~9 million downloads per week
|
||||
- Nearly 2 million unique [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console) installations
|
||||
- Rich ecosystem of [third-party plugins](/docs/plugin-registry), many with millions of downloads in their own right
|
||||
- Used by over half of Fortune 500 companies in production
|
||||
|
||||
@@ -12,6 +12,10 @@ Nx errs on the side of caution when using inputs. Ideally, the "perfect" configu
|
||||
|
||||
For an overview of all the possible [types of inputs](/docs/reference/inputs) and how to reuse sets of inputs as [named inputs](/docs/reference/inputs#named-inputs), see the reference documentation.
|
||||
|
||||
{% aside type="caution" title="Directory Paths Require Trailing Slash or Glob" %}
|
||||
When specifying a directory as an input, you must use a trailing slash (`/`) or a glob pattern. For example, `{projectRoot}/src/` or `{projectRoot}/src/**/*` will match all files in the `src` directory, but `{projectRoot}/src` (without trailing slash) will not match any files. This differs from `outputs`, which support naked directory paths.
|
||||
{% /aside %}
|
||||
|
||||
Throughout this recipe, the following project structure of a simple workspace will be used as an example to help understand inputs better.
|
||||
|
||||
{% graph height="450px" %}
|
||||
|
||||
@@ -4,6 +4,10 @@ description: 'Learn how to generate package.json and pruned lock files for your
|
||||
filter: 'type:Guides'
|
||||
---
|
||||
|
||||
{% aside type="note" title="Using TS Solution Setup?" %}
|
||||
If your workspace uses TS project references (the default in Nx 20+), use the [prune workflow](/docs/technologies/node/guides/deploying-node-projects) instead. The `generatePackageJson` approach below applies to workspaces without TS Solution Setup.
|
||||
{% /aside %}
|
||||
|
||||
A common approach to deploying applications is via docker containers. Some applications can be built into bundles that are environment agnostic, while others depend on OS-specific packages being installed. For these situations, having just bundled code is not enough, we also need to have `package.json`.
|
||||
|
||||
Nx supports the generation of the project's `package.json` by identifying all the project's dependencies. The generated `package.json` is created next to the built artifacts (usually at `dist/apps/name-of-the-app`).
|
||||
|
||||
@@ -50,6 +50,25 @@ Alternatively, you can use the object format with the `fileset` property:
|
||||
}
|
||||
```
|
||||
|
||||
#### Directory Paths
|
||||
|
||||
When specifying a directory as an input, you must use a trailing slash or a glob pattern. A path without a trailing slash or glob pattern will be treated as a file path and will not match any files within the directory.
|
||||
|
||||
```jsonc
|
||||
// nx.json
|
||||
{
|
||||
"inputs": [
|
||||
"{projectRoot}/src/", // ✓ Matches all files in src (note the trailing slash)
|
||||
"{projectRoot}/src/**/*", // ✓ Matches all files in src using glob
|
||||
"{projectRoot}/src", // ✗ Does NOT match files - treated as a file path
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
{% aside type="note" title="Difference from Outputs" %}
|
||||
This behavior differs from `outputs`, which support naked directory paths without a trailing slash. For example, `{projectRoot}/dist` works as an output but would not work as an input.
|
||||
{% /aside %}
|
||||
|
||||
#### Token Behavior with Nested Projects
|
||||
|
||||
These tokens behave differently when dealing with nested projects:
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
title: Node.js and TypeScript Compatibility
|
||||
description: A reference outlining Nx's support policy and current compatibility matrix for Node.js and TypeScript.
|
||||
filter: 'type:References'
|
||||
---
|
||||
|
||||
## Node.js Compatibility Matrix
|
||||
|
||||
Below is a reference table that matches the most recent major versions of Nx to the versions of Node.js that they officially support, and are tested against.
|
||||
|
||||
Nx's policy is to support the LTS versions (i.e. actively maintained even numbered versions) of Node.js, but we will only remove support for older versions in a major version of Nx to avoid unexpected disruption. We may add support for newer LTS versions in a minor version of Nx as long as it would not break existing projects.
|
||||
|
||||
> _Note: Other versions of Node.js **may** still work without issue for these versions of Nx. Those include versions which are already EOL, or odd version numbers (e.g. 23), which Node.js actively
|
||||
> discourages using in production._
|
||||
|
||||
| Nx Version | Node Version |
|
||||
| --------------- | ------------------------ |
|
||||
| 22.x (current) | 24.x, ^22.12.0, ^20.19.0 |
|
||||
| 21.x (previous) | 24.x, ^22.12.0, ^20.19.0 |
|
||||
| 20.x | 22.x, 20.x, 18.x |
|
||||
| 19.x | 22.x, 20.x, 18.x |
|
||||
| 18.x | 20.x, 18.x |
|
||||
|
||||
We intentionally do not include an `"engines"` field in the `package.json` file for Nx in order to allow for user flexibility, but this page should be considered the official compatibility matrix.
|
||||
|
||||
## TypeScript Compatibility
|
||||
|
||||
Unlike Node.js, TypeScript's policy is not to follow semver conventions around breaking changes only coming in major versions, despite using version numbers that are semver-like. Just like with Node.js, though, we will only remove support for older versions of TypeScript in a major version of Nx to avoid unexpected disruption. We may add support for newer versions in a minor version of Nx as long as it would not break existing projects.
|
||||
|
||||
| Nx Version | TypeScript Version |
|
||||
| --------------- | ------------------ |
|
||||
| 22.x (current) | >= 5.4.2 < 5.10.0 |
|
||||
| 21.x (previous) | >= 5.4.2 < 5.10.0 |
|
||||
| 20.x | ~5.4.2 |
|
||||
| 19.x | ~5.4.2 |
|
||||
| 18.x | ~5.4.2 |
|
||||
|
||||
This page will be updated from time to time to reflect the latest versions of Node.js and TypeScript that are supported. If you encounter issues with Nx, please make sure you are using a supported version of Node.js and TypeScript before filing an issue.
|
||||
@@ -464,13 +464,27 @@ Release tag configuration now uses a nested `releaseTag` object. Old flat proper
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
| Property | Type | Default | Description |
|
||||
| ------------------------ | ------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| **pattern** | string | `v{version}` for fixed, `{projectName}@{version}` for independent | The git tag pattern to use. Supports interpolation of `{version}`, `{projectName}`, and `{releaseGroupName}` |
|
||||
| **requireSemver** | boolean | `false` | Whether to require that all tags match semantic versioning |
|
||||
| **strictPreid** | boolean | `false` for independent, `true` for fixed release groups | Whether to ensure prerelease IDs are consistent across packages |
|
||||
| **preferDockerVersion** | boolean | `false` | Whether to prefer Docker-compatible version format in git tags |
|
||||
| **checkAllBranchesWhen** | string | undefined | Branch to check when resolving current versions from git tags |
|
||||
| Property | Type | Default | Description |
|
||||
| ------------------------ | ------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **pattern** | string | `v{version}` for fixed, `{projectName}@{version}` for independent | The git tag pattern to use. Supports interpolation of `{version}`, `{projectName}`, and `{releaseGroupName}` |
|
||||
| **requireSemver** | boolean | `false` | Whether to require that all tags match semantic versioning |
|
||||
| **strictPreid** | boolean | `false` for independent, `true` for fixed release groups | Whether to ensure prerelease IDs are consistent across packages |
|
||||
| **preferDockerVersion** | boolean | `false` | Whether to prefer Docker-compatible version format in git tags |
|
||||
| **checkAllBranchesWhen** | boolean \| string[] | undefined | Controls whether to check all branches or only merged branches when resolving current versions from git tags. `true` = always check all branches, `false` = only check the current branch, `string[]` = check all branches when the current branch matches any of the provided names or glob patterns |
|
||||
|
||||
#### Branch Resolution for Git Tags
|
||||
|
||||
The `checkAllBranchesWhen` option controls how Nx resolves existing git tags to determine the current version of your projects.
|
||||
|
||||
By default, Nx checks for matching tags on the current branch. If no tags are found, it falls back to checking all branches.
|
||||
|
||||
| Value | Behavior |
|
||||
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `true` | Always check all branches for the latest matching tag |
|
||||
| `false` | Only check the current branch (no fallback to all branches) |
|
||||
| `string[]` | Check all branches when the current branch matches any of the provided names or [glob patterns](https://github.com/isaacs/minimatch). Otherwise, use the default behavior |
|
||||
|
||||
This option is useful when release tags may exist on multiple branches. Setting `checkAllBranchesWhen` to `true` or to a list of branch patterns ensures Nx finds the latest tag regardless of which branch it was created on.
|
||||
|
||||
#### Tag Pattern Syntax
|
||||
|
||||
@@ -501,7 +515,7 @@ Example patterns and their results:
|
||||
"requireSemver": true,
|
||||
"strictPreid": true,
|
||||
"preferDockerVersion": false,
|
||||
"checkAllBranchesWhen": "main",
|
||||
"checkAllBranchesWhen": ["main", "release/*"],
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -518,7 +532,7 @@ Example patterns and their results:
|
||||
"releaseTagPatternRequireSemver": true,
|
||||
"releaseTagPatternStrictPreid": true,
|
||||
"releaseTagPatternPreferDockerVersion": false,
|
||||
"releaseTagPatternCheckAllBranchesWhen": "main",
|
||||
"releaseTagPatternCheckAllBranchesWhen": ["main", "release/*"],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -20,6 +20,7 @@ We provide a recommended version, and it is usually the latest minor version of
|
||||
|
||||
| Angular Version | **Nx Version _(recommended)_** | Nx Version _(range)_ |
|
||||
| --------------- | ------------------------------ | ---------------------------------------- |
|
||||
| ~21.2.0 | **latest** | >=22.6.0 <=latest |
|
||||
| ~21.1.0 | **latest** | >=22.4.0 <=latest |
|
||||
| ~21.0.0 | **latest** | >=22.3.0 <=latest |
|
||||
| ~20.3.0 | **latest** | >=21.6.1 <=latest |
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
---
|
||||
title: 'createConfig - @nx/angular-rsbuild'
|
||||
description: 'API Reference for createConfig from @nx/angular-rsbuild'
|
||||
title: 'Angular Rsbuild Plugin for Nx'
|
||||
description: 'Use Rsbuild as the build tool for Angular applications in your Nx workspace with the @nx/angular-rsbuild plugin.'
|
||||
sidebar:
|
||||
label: 'Create Config'
|
||||
label: 'Introduction'
|
||||
filter: 'type:References'
|
||||
---
|
||||
|
||||
The `@nx/angular-rsbuild` package provides configuration utilities for building Angular applications with [Rsbuild](https://rsbuild.dev). Rsbuild is built on top of Rspack and offers a streamlined development experience with fast builds and hot module replacement.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/angular-rsbuild` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `@rsbuild/core` | ^1.1.0 |
|
||||
| `@angular/core` | See [Angular version matrix](/docs/technologies/angular/guides/angular-nx-version-matrix) |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Usage
|
||||
|
||||
```shell
|
||||
import { createConfig } from '@nx/angular-rsbuild';
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Introduction - Angular Rspack Compiler'
|
||||
title: 'Angular Rspack Compiler'
|
||||
description: 'Compilation utilities for Angular with Rspack and Rsbuild.'
|
||||
sidebar:
|
||||
label: 'Introduction'
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
---
|
||||
title: 'Introduction - Angular Rspack'
|
||||
title: 'Angular Rspack Plugin for Nx'
|
||||
description: 'Learn how Rspack can help you speed up your Angular applications.'
|
||||
sidebar:
|
||||
label: 'Introduction'
|
||||
filter: 'type:References'
|
||||
---
|
||||
|
||||
Angular's compilation has always been a black box hidden behind layers of abstraction and configuration, exposed via the Angular Builders from the Angular CLI packages.
|
||||
## Requirements
|
||||
|
||||
The `@angular-rspack/nx` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `@rspack/core` | >=1.3.5 <1.7.0 |
|
||||
| `@angular/core` | See [Angular version matrix](/docs/technologies/angular/guides/angular-nx-version-matrix) |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
Angular compilation has always been a black box hidden behind layers of abstraction and configuration, exposed via the Angular Builders from the Angular CLI packages.
|
||||
|
||||
Originally, the underlying tool that bundled the Angular application was [Webpack](https://webpack.js.org). This was great as teams were able to extend their builds by leveraging the vast Webpack ecosystem and plugins that are available.
|
||||
|
||||
Over time, it became clear that the inherit slowness with Webpack build speeds was becoming more and more of an issue for Angular developers.
|
||||
|
||||
The Angular Team decided to address this build speed issue by building out a new build pipeline that leveraged [Esbuild](https://esbuild.github.io/).
|
||||
The Angular Team decided to address this build speed issue by building out a new build pipeline that used [Esbuild](https://esbuild.github.io/).
|
||||
|
||||
This succeeded in reducing the build times for Angular applications, however, it made one crucial mistake. It left the existing Angular applications that relied on the Webpack ecosystem behind, with either a difficult migration path or none at all.
|
||||
|
||||
@@ -20,15 +31,15 @@ This succeeded in reducing the build times for Angular applications, however, it
|
||||
|
||||
## Rspack
|
||||
|
||||
The solution to this problem was to create a new build pipeline that would be able to leverage the existing Webpack ecosystem and plugins, while also providing faster builds for Angular applications.
|
||||
The solution to this problem was to create a new build pipeline that could use the existing Webpack ecosystem and plugins while also providing faster builds for Angular applications.
|
||||
|
||||
This is where [Rspack](https://rspack.dev) come into play.
|
||||
|
||||
Rspack is a high performance JavaScript bundler written in Rust. It offers strong compatibility with the Webpack ecosystem, allowing for almost seamless replacement of webpack, and provides lightning fast build speeds.
|
||||
Rspack is a high performance JavaScript bundler written in Rust. It offers strong compatibility with the Webpack ecosystem, and can serve as a near drop-in replacement for webpack with significantly faster build speeds.
|
||||
|
||||
Because it supports the existing Webpack ecosystem, it provides an answer to teams that maintain Angular applications using Webpack and want to migrate to a faster build pipeline.
|
||||
|
||||
This makes it a great solution for teams that want to migrate to a faster build pipeline, but still want the ability to easily extend their builds and use [Module Federation](https://module-federation.io).
|
||||
This makes it a great solution for teams that want to migrate to a faster build pipeline, but still want the ability to extend their builds and use [Module Federation](https://module-federation.io).
|
||||
|
||||
{% aside type="caution" title="Angular Rspack Status" %}
|
||||
|
||||
|
||||
@@ -12,7 +12,17 @@ filter: 'type:References'
|
||||
The `@nx/angular` plugin adds [generators](#local-development), Angular CLI builder integration (executors) and migrations so you can run Angular tasks through Nx. With Nx, each project has its own configuration instead of a single `angular.json` file, making it more scalable for monorepos.
|
||||
You can use Angular with Nx without the plugin and still get [task caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph).
|
||||
|
||||
See the [Nx and Angular versions matrix](/docs/technologies/angular/guides/angular-nx-version-matrix) to know which Nx version supports a given Angular version.
|
||||
## Requirements
|
||||
|
||||
The `@nx/angular` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------------- | ------------------ |
|
||||
| `@angular/core` | >= 19.0.0 < 22.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
For older Nx versions, see the full [Nx and Angular versions matrix](/docs/technologies/angular/guides/angular-nx-version-matrix).
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Docker Plugin
|
||||
title: Docker Plugin for Nx
|
||||
description: The Nx Plugin for Docker contains executors and utilities for building and publishing docker images within an Nx workspace.
|
||||
keywords: [docker]
|
||||
sidebar:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview of the Nx esbuild Plugin
|
||||
description: The Nx Plugin for esbuild contains executors and generators that support building applications using esbuild. This page also explains how to configure esbuild on your Nx workspace.
|
||||
title: esbuild Plugin for Nx
|
||||
description: The Nx Plugin for esbuild contains executors and generators that support building applications using esbuild, including setup and configuration for your Nx workspace.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
@@ -8,6 +8,16 @@ filter: 'type:References'
|
||||
|
||||
The Nx Plugin for [esbuild](https://esbuild.github.io/api/), an extremely fast JavaScript bundler.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/esbuild` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------- | ------------------ |
|
||||
| `esbuild` | >=0.19.2 <1.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
Why should you use this plugin?
|
||||
|
||||
- _Fast_ builds using esbuild.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Rollup Plugin
|
||||
title: Rollup Plugin for Nx
|
||||
description: The Nx Plugin for Rollup contains executors and generators that support building applications using Rollup.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
@@ -8,6 +8,16 @@ filter: 'type:References'
|
||||
|
||||
The Nx Plugin for Rollup contains executors and generators that support building applications using Rollup.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/rollup` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| -------- | ------------------ |
|
||||
| `rollup` | ^4.14.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/rollup
|
||||
|
||||
### Installation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Rsbuild Plugin
|
||||
title: Rsbuild Plugin for Nx
|
||||
description: The Nx Plugin for Rsbuild contains executors and generators that support building applications using Rsbuild.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
@@ -8,6 +8,16 @@ filter: 'type:References'
|
||||
|
||||
The Nx Plugin for Rsbuild contains executors and generators that support building applications using Rsbuild.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/rsbuild` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------------- | ------------------ |
|
||||
| `@rsbuild/core` | ^1.1.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/rsbuild
|
||||
|
||||
### Installation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Rspack Plugin
|
||||
title: Rspack Plugin for Nx
|
||||
description: The Nx Plugin for Rspack contains executors, generators, and utilities for managing Rspack projects in an Nx Workspace.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
@@ -8,6 +8,16 @@ filter: 'type:References'
|
||||
|
||||
The Nx Plugin for Rspack contains executors, generators, and utilities for managing Rspack projects in an Nx Workspace.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/rspack` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| -------------- | ------------------ |
|
||||
| `@rspack/core` | ^1.6.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/rspack
|
||||
|
||||
### Installation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Vite Plugin
|
||||
title: Vite Plugin for Nx
|
||||
description: Use Vite with Nx for inferred dev/build tasks, generators, and CI-friendly workflows.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
@@ -16,6 +16,16 @@ Starting with Nx v22, Vitest support has moved to the dedicated [`@nx/vitest` pl
|
||||
|
||||
You can use Vite with Nx without the plugin and still get [task caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph).
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/vite` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------- | ------------------------------ |
|
||||
| `vite` | ^5.0.0 \|\| ^6.0.0 \|\| ^7.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setup
|
||||
|
||||
### Add to an existing workspace
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Webpack Plugin
|
||||
title: Webpack Plugin for Nx
|
||||
description: The Nx Plugin for Webpack contains executors and generators that support building applications using Webpack.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
@@ -10,7 +10,17 @@ The Nx plugin for [webpack](https://webpack.js.org/).
|
||||
|
||||
[Webpack](https://webpack.js.org/) is a static module bundler for modern JavaScript applications. The `@nx/webpack` plugin provides executors that allow you to build and serve your projects using webpack, plus an executor for SSR.
|
||||
|
||||
Nx now allows you to [customize your webpack configuration](/docs/technologies/build-tools/webpack/guides/webpack-config-setup) for your projects. And we also offer [a number of webpack plugins](/docs/technologies/build-tools/webpack/guides/webpack-plugins) for supporting Nx and other frameworks.
|
||||
You can [customize your webpack configuration](/docs/technologies/build-tools/webpack/guides/webpack-config-setup) for your projects. Nx also provides [a number of webpack plugins](/docs/technologies/build-tools/webpack/guides/webpack-plugins) for supporting Nx and other frameworks.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/webpack` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------- | ------------------ |
|
||||
| `webpack` | >=5.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting up a new Nx workspace with Webpack
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Plugin for .NET
|
||||
title: .NET Plugin for Nx
|
||||
description: This plugin allows .NET projects to be run through Nx.
|
||||
sidebar:
|
||||
label: 'Introduction'
|
||||
|
||||
@@ -6,7 +6,17 @@ sidebar:
|
||||
filter: 'type:References'
|
||||
---
|
||||
|
||||
The ESLint plugin integrates [ESLint](https://eslint.org/) with Nx. It allows you to run ESLint through Nx with caching enabled. It also includes code generators to help you set up ESLint in your workspace.
|
||||
The ESLint plugin integrates [ESLint](https://eslint.org/) with Nx. Run ESLint through Nx with caching enabled, and use the included code generators to set up ESLint in your workspace.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/eslint` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| -------- | ------------------ |
|
||||
| `eslint` | ^8.0.0 \|\| ^9.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/eslint
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Plugin for Gradle
|
||||
title: Gradle Plugin for Nx
|
||||
description: Run Gradle tasks through Nx with caching, graph insights, and CI optimization.
|
||||
sidebar:
|
||||
label: 'Introduction'
|
||||
@@ -12,12 +12,17 @@ The `@nx/gradle` plugin registers Gradle projects in the Nx graph so you can [se
|
||||
|
||||
You can use Gradle with Nx without the plugin and still get [task caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph).
|
||||
|
||||
## Requirements
|
||||
|
||||
| Dependency | Supported Versions |
|
||||
| ---------- | ------------------ |
|
||||
| Java | >= 17 |
|
||||
| Gradle | >= 8.0 |
|
||||
|
||||
Using older Java versions is unsupported and may lead to issues. If you need support for an older version, please create an issue on [GitHub](https://github.com/nrwl/nx).
|
||||
|
||||
## Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Java 17 or newer
|
||||
|
||||
### Install Nx
|
||||
|
||||
Install Nx with your preferred package manager:
|
||||
|
||||
@@ -10,9 +10,11 @@ Nx provides powerful tooling for Java projects, supporting both Gradle and Maven
|
||||
|
||||
## Requirements
|
||||
|
||||
{% aside type="note" title="Java Compatibility" %}
|
||||
Both Nx plugins require Java 17 or newer. Using older Java versions is unsupported and may lead to issues. If you need support for an older version, please create an issue on [Github](https://github.com/nrwl/nx)!
|
||||
{% /aside %}
|
||||
| Dependency | Supported Versions |
|
||||
| ---------- | ------------------ |
|
||||
| Java | >= 17 |
|
||||
|
||||
Using older Java versions is unsupported and may lead to issues. If you need support for an older version, please create an issue on [GitHub](https://github.com/nrwl/nx).
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview of the Nx Plugin for Maven
|
||||
title: Maven Plugin for Nx
|
||||
description: This plugin allows Maven tasks to be run through Nx.
|
||||
sidebar:
|
||||
label: 'Introduction'
|
||||
@@ -16,13 +16,17 @@ The `@nx/maven` plugin registers Maven modules as Nx projects so you can [set up
|
||||
|
||||
You can use Maven with Nx without the plugin and still get [task caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph).
|
||||
|
||||
## Requirements
|
||||
|
||||
| Dependency | Supported Versions |
|
||||
| ---------- | ------------------ |
|
||||
| Java | >= 17 |
|
||||
| Maven | >= 3.6.0 |
|
||||
|
||||
Using older Java versions is unsupported and may lead to issues. If you need support for an older version, please create an issue on [GitHub](https://github.com/nrwl/nx).
|
||||
|
||||
## Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Java 17 or newer**
|
||||
- **Maven 3.6.0 or newer**
|
||||
|
||||
### Install Nx
|
||||
|
||||
You can install Nx globally. Depending on your package manager, use one of the following commands:
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
---
|
||||
title: NxModuleFederationPlugin
|
||||
title: Module Federation Plugin for Nx
|
||||
description: Details about the NxModuleFederationPlugin
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
---
|
||||
|
||||
The `NxModuleFederationPlugin` is a [Rspack](https://rspack.dev) plugin that handles module federation in Nx Workspaces. It aims to provide the same Developer Experience(DX) that you would normally receive from using Nx's `withModuleFederation` function.
|
||||
The `NxModuleFederationPlugin` is a [Rspack](https://rspack.dev) plugin that handles module federation in Nx Workspaces. It aims to provide the same Developer Experience (DX) that you would normally get from using the Nx `withModuleFederation` function.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/module-federation` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| -------------- | ------------------ |
|
||||
| `webpack` | ^5.0.0 |
|
||||
| `@rspack/core` | ^1.6.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
---
|
||||
title: Bundling Node.js Applications and Libraries
|
||||
description: Learn how to configure bundling for Node.js applications and libraries in an Nx monorepo using Webpack, esbuild, and Vite.
|
||||
title: Bundling Projects for Deployment
|
||||
description: Bundle your Node.js application into a single file with no node_modules needed. Deploy without a package.json install step.
|
||||
sidebar:
|
||||
label: Understand Bundling with Node
|
||||
label: Bundling for Deployment
|
||||
filter: 'type:Guides'
|
||||
---
|
||||
|
||||
When building Node.js projects, you have two main approaches to distribute your projects final artifact from the monorepo, **bundled** or **not bundled**. Depending on your deployment strategy and tooling preferences, one approach may be more suitable than the other.
|
||||
Bundling compiles your code and all its dependencies into a single file (e.g. `main.js`).
|
||||
The output is self-contained, so you don't need `node_modules` or an install step at deploy time.
|
||||
|
||||
## Bundled vs Non-Bundled Builds
|
||||
If your app has native dependencies or you want Docker layer caching for `node_modules`,
|
||||
see [pruning projects for deployment](/docs/technologies/node/guides/deploying-node-projects) instead.
|
||||
|
||||
## When to bundle instead of prune
|
||||
|
||||
| Approach | Best for | Trade-off |
|
||||
| ----------------------------------------------------------------- | --------------------------------------- | --------------------------------------------- |
|
||||
| Bundling | Serverless functions, simple APIs | Single file output, no `node_modules` needed |
|
||||
| [Pruning](/docs/technologies/node/guides/deploying-node-projects) | Docker deployments, native dependencies | Keeps `node_modules` but only production deps |
|
||||
|
||||
Use bundling when:
|
||||
|
||||
- Your app has no native dependencies that require OS-level installation
|
||||
- You want a single deployable artifact with no install step
|
||||
- You're targeting serverless platforms or lightweight containers
|
||||
|
||||
**Bundled builds** compile your code and all its dependencies into a single file, e.g. `main.js` This approach:
|
||||
{% aside type="note" title="Lazy loaded chunks" %}
|
||||
If you're using lazy loaded chunks in your node application, bundling will produce more than a single file. Instead, you'll have a file per chunks entrypoint file. You'll want to make sure all the files are handled correctly for your deployment needs.
|
||||
If you use lazy loaded chunks, bundling produces more than a single file.
|
||||
You'll have one file per chunk entrypoint.
|
||||
Make sure all files are handled correctly for your deployment needs.
|
||||
{% /aside %}
|
||||
|
||||
- Produces a self-contained artifact that doesn't require `node_modules`
|
||||
- Simplifies deployment since you only need to copy a single file
|
||||
- Works well for serverless functions and containerized applications
|
||||
|
||||
**Non-bundled builds** preserve your module structure and require `node_modules` at runtime. This approach:
|
||||
|
||||
- Requires installing dependencies before running
|
||||
- Maintains separate files for each module
|
||||
- Can improve container rebuilds speeds when paired with Docker Layer Caching
|
||||
|
||||
## Bundling Node.js Applications
|
||||
## Bundling Node.js applications
|
||||
|
||||
{% tabs syncKey="bundler" %}
|
||||
|
||||
@@ -130,18 +136,22 @@ nx build my-app
|
||||
# Deploy dist/my-app/main.js - no node_modules needed
|
||||
```
|
||||
|
||||
## When NOT to Bundle
|
||||
## When not to bundle
|
||||
|
||||
If you're publishing a library package to npm, avoid bundling dependencies. Instead, declare them in `package.json` so package managers can handle versioning and deduplication.
|
||||
If you're publishing a library package to npm, avoid bundling dependencies.
|
||||
Declare them in `package.json` so package managers can handle versioning and deduplication.
|
||||
|
||||
For Docker based deployments, non-bundled builds can improve build times through layer caching. When dependencies don't change, Docker reuses the cached `node_modules` layer, only rebuilding your application code.
|
||||
For Docker-based deployments, non-bundled builds can improve build times through layer caching.
|
||||
When dependencies don't change, Docker reuses the cached `node_modules` layer and only rebuilds your application code.
|
||||
|
||||
Instead of running `build`, use the `prune` target which prepares your application for deployment with its dependencies:
|
||||
Instead of running `build`, use the `prune` target to prepare your application for deployment with its dependencies:
|
||||
|
||||
```shell
|
||||
nx prune my-app
|
||||
```
|
||||
|
||||
For the full setup, see [pruning projects for deployment](/docs/technologies/node/guides/deploying-node-projects).
|
||||
|
||||
This creates a deployment-ready structure:
|
||||
|
||||
```text
|
||||
@@ -159,11 +169,12 @@ WORKDIR /app
|
||||
CMD ["node", "main.js"]
|
||||
```
|
||||
|
||||
## Bundling Libraries
|
||||
## Bundling libraries
|
||||
|
||||
Nx recommends publishing workspace dependencies as separate packages rather than bundling them into a single library. This approach provides better versioning control and allows consumers to manage their own dependency trees.
|
||||
Publish workspace dependencies as separate packages rather than bundling them into a single library.
|
||||
This gives better versioning control and lets consumers manage their own dependency trees.
|
||||
|
||||
However, bundling workspace libraries could make sense when:
|
||||
Bundling workspace libraries makes sense when:
|
||||
|
||||
- The library contains only types that should be inlined
|
||||
- You want to distribute an internal library as part of your package
|
||||
@@ -245,9 +256,9 @@ See `rollupOptions` from [vite documentation for more information](https://vite.
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
## Managing Workspace Dependencies
|
||||
## Managing workspace dependencies
|
||||
|
||||
When building libraries that consume other workspace libraries, always define the dependency relationship in `package.json`:
|
||||
When building libraries that consume other workspace libraries, define the dependency relationship in `package.json`:
|
||||
|
||||
```json
|
||||
// libs/my-lib/package.json
|
||||
@@ -266,7 +277,7 @@ The `workspace:*` syntax:
|
||||
|
||||
This ensures your library correctly declares its dependencies regardless of whether they're bundled.
|
||||
|
||||
## Quick Reference
|
||||
## Quick reference
|
||||
|
||||
| Scenario | Tool | Key Settings |
|
||||
| --------------------------------------- | ------- | ------------------------------------------------------------ |
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
---
|
||||
title: Pruning Projects for Deployment
|
||||
description: Generate a pruned package.json and lockfile so Docker installs only production dependencies. Replaces the deprecated generatePackageJson option in Nx 20+.
|
||||
sidebar:
|
||||
label: Pruning for Deployment
|
||||
filter: 'type:Guides'
|
||||
---
|
||||
|
||||
When deploying Node.js applications to containers, you typically need only production dependencies, not your entire workspace `node_modules`.
|
||||
Pruning generates a standalone `package.json`, a pruned lockfile, and copies any workspace libraries your app depends on.
|
||||
The result is everything you need to run `npm ci` inside a Docker image with only the packages your application uses.
|
||||
|
||||
To bundle your app into a single file instead (no `node_modules` needed),
|
||||
see [Bundling projects for deployment](/docs/technologies/node/guides/bundling-node-projects).
|
||||
|
||||
## When to prune instead of bundle
|
||||
|
||||
| Approach | Best for | Trade-off |
|
||||
| ----------------------------------------------------------------- | --------------------------------------- | --------------------------------------------- |
|
||||
| [Bundling](/docs/technologies/node/guides/bundling-node-projects) | Serverless functions, simple APIs | Single file output, no `node_modules` needed |
|
||||
| Pruning | Docker deployments, native dependencies | Keeps `node_modules` but only production deps |
|
||||
|
||||
Use pruning when:
|
||||
|
||||
- Your app has native dependencies (e.g. `bcrypt`, `sharp`) that can't be bundled
|
||||
- You want Docker layer caching, where dependency layers rebuild only when `package.json` changes
|
||||
- You consume workspace libraries as packages rather than bundling them
|
||||
|
||||
{% aside type="tip" %}
|
||||
New Node applications include prune targets by default.
|
||||
Pass `--docker` to also generate an example Dockerfile: `nx g @nx/node:app --docker`.
|
||||
{% /aside %}
|
||||
|
||||
## How pruning works
|
||||
|
||||
Pruning uses four Nx targets that run in sequence:
|
||||
|
||||
1. `build` compiles your application (esbuild, webpack, tsc, etc.).
|
||||
1. `prune-lockfile` (`@nx/js:prune-lockfile`) reads your project `package.json`, generates a minimal `package.json`, and creates a pruned lockfile containing only production dependencies.
|
||||
1. `copy-workspace-modules` (`@nx/js:copy-workspace-modules`) copies workspace libraries referenced via `workspace:*` into a `workspace_modules/` directory and rewrites their dependency references to `file:` paths.
|
||||
1. `prune` (`nx:noop`) depends on both `prune-lockfile` and `copy-workspace-modules`, giving you a single command to run.
|
||||
|
||||
After running `nx prune my-app`, the build output directory contains:
|
||||
|
||||
```text
|
||||
apps/my-app/dist/
|
||||
├── main.js # Compiled application
|
||||
├── package.json # Pruned production dependencies
|
||||
├── package-lock.json # Pruned lockfile (or yarn.lock / pnpm-lock.yaml)
|
||||
└── workspace_modules/ # Only present if you have workspace deps
|
||||
└── @my-org/
|
||||
└── my-lib/
|
||||
├── package.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Set up prune targets
|
||||
|
||||
Add the following targets to your project's `package.json` or `project.json`:
|
||||
|
||||
{% tabs syncKey="config" %}
|
||||
|
||||
{% tabitem label="package.json" %}
|
||||
|
||||
```json
|
||||
// apps/my-app/package.json
|
||||
{
|
||||
"name": "@my-org/my-app",
|
||||
"nx": {
|
||||
"targets": {
|
||||
"prune-lockfile": {
|
||||
"dependsOn": ["build"],
|
||||
"cache": true,
|
||||
"executor": "@nx/js:prune-lockfile",
|
||||
"outputs": [
|
||||
"{workspaceRoot}/apps/my-app/dist/package.json",
|
||||
"{workspaceRoot}/apps/my-app/dist/package-lock.json"
|
||||
],
|
||||
"options": {
|
||||
"buildTarget": "build"
|
||||
}
|
||||
},
|
||||
"copy-workspace-modules": {
|
||||
"dependsOn": ["build"],
|
||||
"cache": true,
|
||||
"outputs": ["{workspaceRoot}/apps/my-app/dist/workspace_modules"],
|
||||
"executor": "@nx/js:copy-workspace-modules",
|
||||
"options": {
|
||||
"buildTarget": "build"
|
||||
}
|
||||
},
|
||||
"prune": {
|
||||
"dependsOn": ["prune-lockfile", "copy-workspace-modules"],
|
||||
"executor": "nx:noop"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% /tabitem %}
|
||||
|
||||
{% tabitem label="project.json" %}
|
||||
|
||||
```json
|
||||
// apps/my-app/project.json
|
||||
{
|
||||
"name": "@my-org/my-app",
|
||||
"targets": {
|
||||
"prune-lockfile": {
|
||||
"dependsOn": ["build"],
|
||||
"cache": true,
|
||||
"executor": "@nx/js:prune-lockfile",
|
||||
"outputs": [
|
||||
"{workspaceRoot}/apps/my-app/dist/package.json",
|
||||
"{workspaceRoot}/apps/my-app/dist/package-lock.json"
|
||||
],
|
||||
"options": {
|
||||
"buildTarget": "build"
|
||||
}
|
||||
},
|
||||
"copy-workspace-modules": {
|
||||
"dependsOn": ["build"],
|
||||
"cache": true,
|
||||
"outputs": ["{workspaceRoot}/apps/my-app/dist/workspace_modules"],
|
||||
"executor": "@nx/js:copy-workspace-modules",
|
||||
"options": {
|
||||
"buildTarget": "build"
|
||||
}
|
||||
},
|
||||
"prune": {
|
||||
"dependsOn": ["prune-lockfile", "copy-workspace-modules"],
|
||||
"executor": "nx:noop"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% /tabitem %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
Replace `package-lock.json` in the `outputs` array with `yarn.lock` or `pnpm-lock.yaml` if needed.
|
||||
|
||||
Then run:
|
||||
|
||||
```shell
|
||||
nx prune my-app
|
||||
```
|
||||
|
||||
Both `prune-lockfile` and `copy-workspace-modules` set `cache: true`,
|
||||
so subsequent runs are instant when nothing changes.
|
||||
|
||||
## Use pruned output in Docker
|
||||
|
||||
The generated Dockerfile copies the build output and runs `npm install`:
|
||||
|
||||
```dockerfile
|
||||
# apps/my-app/Dockerfile
|
||||
FROM docker.io/node:lts-alpine
|
||||
|
||||
ENV HOST=0.0.0.0
|
||||
ENV PORT=3000
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY dist .
|
||||
|
||||
# You can remove this install step if you build with `--bundle` option.
|
||||
# The bundled output will include external dependencies.
|
||||
RUN npm --omit=dev -f install
|
||||
|
||||
CMD ["node", "main.js"]
|
||||
```
|
||||
|
||||
The `COPY dist .` line works because the Dockerfile lives inside the project directory (`apps/my-app/`),
|
||||
and the build output goes to `apps/my-app/dist/`.
|
||||
The pruned `package.json`, lockfile, and `workspace_modules/` are all inside `dist/`.
|
||||
|
||||
Build and run:
|
||||
|
||||
```shell
|
||||
# Build the app and prune dependencies
|
||||
nx prune my-app
|
||||
|
||||
# Build the Docker image
|
||||
npx nx docker:build my-app
|
||||
|
||||
# Run the container
|
||||
nx docker:run my-app -p 3000:3000
|
||||
```
|
||||
|
||||
## Migrate from `generatePackageJson`
|
||||
|
||||
If you're upgrading to Nx 20+ with TS Solution Setup (the default for new workspaces),
|
||||
the `generatePackageJson` option is no longer supported.
|
||||
You'll see this error:
|
||||
|
||||
{% aside type="caution" title="Error: generatePackageJson not supported" %}
|
||||
`Setting 'generatePackageJson: true' is not supported with the current TypeScript setup. Update the 'package.json' file at the project root as needed and unset the 'generatePackageJson' option.`
|
||||
{% /aside %}
|
||||
|
||||
Follow these steps to migrate to the prune workflow:
|
||||
|
||||
### Step 1: Move dependencies to your project package.json
|
||||
|
||||
With TS Solution Setup, each project has its own `package.json`.
|
||||
List all runtime dependencies there:
|
||||
|
||||
```json
|
||||
// apps/my-app/package.json
|
||||
{
|
||||
"name": "@my-org/my-app",
|
||||
"dependencies": {
|
||||
"express": "^4.18.0",
|
||||
"@my-org/shared-utils": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use the `workspace:*` protocol for workspace libraries.
|
||||
|
||||
### Step 2: Remove `generatePackageJson` from your build configuration
|
||||
|
||||
{% tabs syncKey="bundler" %}
|
||||
|
||||
{% tabitem label="esbuild" %}
|
||||
|
||||
Remove `generatePackageJson` from your esbuild target options:
|
||||
|
||||
```json
|
||||
// apps/my-app/package.json
|
||||
{
|
||||
"nx": {
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nx/esbuild:esbuild",
|
||||
"options": {
|
||||
"platform": "node",
|
||||
"outputPath": "dist/apps/my-app",
|
||||
"format": ["cjs"],
|
||||
"main": "apps/my-app/src/main.ts",
|
||||
"tsConfig": "apps/my-app/tsconfig.app.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% /tabitem %}
|
||||
|
||||
{% tabitem label="Webpack" %}
|
||||
|
||||
Remove `generatePackageJson` from your webpack config:
|
||||
|
||||
```js
|
||||
// apps/my-app/webpack.config.js
|
||||
const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
|
||||
const { join } = require('path');
|
||||
|
||||
module.exports = {
|
||||
output: {
|
||||
path: join(__dirname, '../../dist/apps/my-app'),
|
||||
},
|
||||
plugins: [
|
||||
new NxAppWebpackPlugin({
|
||||
target: 'node',
|
||||
compiler: 'tsc',
|
||||
main: './src/main.ts',
|
||||
tsConfig: './tsconfig.app.json',
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
{% /tabitem %}
|
||||
|
||||
{% tabitem label="Rollup / Vite" %}
|
||||
|
||||
Remove `generatePackageJson` from your rollup or vite build options.
|
||||
With TS Solution Setup, the project `package.json` is used directly.
|
||||
|
||||
{% /tabitem %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
### Step 3: Add prune targets
|
||||
|
||||
Add the `prune-lockfile`, `copy-workspace-modules`, and `prune` targets
|
||||
to your project `package.json` as shown in the [set up prune targets](#set-up-prune-targets) section.
|
||||
|
||||
### Step 4: Update your Dockerfile
|
||||
|
||||
Replace references to the old generated `package.json` with the pruned output.
|
||||
See the [use pruned output in Docker](#use-pruned-output-in-docker) section for a recommended Dockerfile structure.
|
||||
@@ -9,6 +9,16 @@ filter: 'type:References'
|
||||
[Express](https://expressjs.com/) is a mature, minimal, and an open source web framework for making web applications and
|
||||
apis.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/express` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------- | ------------------ |
|
||||
| `express` | ^4.21.2 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Create a New Workspace
|
||||
|
||||
To create a new workspace with a pre-created Express app, run the following command:
|
||||
|
||||
@@ -8,6 +8,26 @@ filter: 'type:References'
|
||||
|
||||
The Node Plugin contains generators and executors to manage Node applications within an Nx workspace. It provides:
|
||||
|
||||
## Requirements
|
||||
|
||||
Below is a reference table that matches the most recent major versions of Nx to the versions of Node.js that they officially support, and are tested against.
|
||||
|
||||
The Nx policy is to support the LTS versions (i.e. actively maintained even numbered versions) of Node.js, but we will only remove support for older versions in a major version of Nx to avoid unexpected disruption. We may add support for newer LTS versions in a minor version of Nx as long as it would not break existing projects.
|
||||
|
||||
{% aside type="note" title="Other Node.js versions" %}
|
||||
Other versions of Node.js **may** still work without issue for these versions of Nx. Those include versions which are already EOL, or odd version numbers (e.g. 23), which Node.js actively discourages using in production.
|
||||
{% /aside %}
|
||||
|
||||
| Nx Version | Node Version |
|
||||
| -------------- | ------------------------ |
|
||||
| 22.x (current) | 24.x, ^22.12.0, ^20.19.0 |
|
||||
| 21.x | 24.x, ^22.12.0, ^20.19.0 |
|
||||
| 20.x | 22.x, 20.x, 18.x |
|
||||
|
||||
We intentionally do not include an `"engines"` field in the `package.json` file for Nx in order to allow for user flexibility, but this table should be considered the official compatibility matrix.
|
||||
|
||||
This table will be updated from time to time to reflect the latest versions of Node.js that are supported. If you encounter issues with Nx, please make sure you are using a supported version of Node.js before filing an issue.
|
||||
|
||||
## Setting Up @nx/node
|
||||
|
||||
### Installation
|
||||
@@ -92,7 +112,7 @@ nx g @nx/node:application apps/my-new-app \
|
||||
|
||||
#### VSCode Integration
|
||||
|
||||
When generating Node applications, Nx automatically creates a VSCode debugging configuration for seamless development experience:
|
||||
When generating Node applications, Nx automatically creates a VSCode debugging configuration:
|
||||
|
||||
- **Automatic setup**: A `.vscode/launch.json` file is created with pre-configured debugging settings.
|
||||
- **Smart port allocation**: Debug ports are automatically assigned starting from 9229, preventing conflicts between multiple applications.
|
||||
|
||||
@@ -16,6 +16,18 @@ Nest.js is a framework designed for building scalable server-side applications.
|
||||
|
||||
Many conventions and best practices used in Angular applications can be also be used in Nest.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/nest` plugin depends on `@nestjs/schematics` for code generation, which pins the supported NestJS major version.
|
||||
|
||||
| Nx Version | NestJS Version |
|
||||
| -------------- | -------------- |
|
||||
| 22.x (current) | ^11.0.0 |
|
||||
| 21.x | ^11.0.0 |
|
||||
| 20.x | ^10.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/nest
|
||||
|
||||
### Generating a new workspace
|
||||
@@ -128,7 +140,7 @@ Nest applications also have the `inspect` flag set, so you can attach your debug
|
||||
|
||||
##### VSCode Integration
|
||||
|
||||
When generating Nest applications, Nx automatically creates a VSCode debugging configuration for seamless development experience:
|
||||
When generating Nest applications, Nx automatically creates a VSCode debugging configuration:
|
||||
|
||||
- **Automatic setup**: A `.vscode/launch.json` file is created with pre-configured debugging settings.
|
||||
- **Smart port allocation**: Debug ports are automatically assigned starting from 9229, preventing conflicts between multiple applications.
|
||||
@@ -214,7 +226,7 @@ module.exports = {
|
||||
Ensuring a smooth and reliable deployment of a Nest.js application in a production environment requires careful planning and the right strategy. Depending on your specific needs and infrastructure, you can choose from several deployment approaches. Below are four commonly used methods:
|
||||
|
||||
1. **Using Docker:**
|
||||
Create a Dockerfile that specifies the application's environment and dependencies. Build a Docker image and optionally push it to a container registry. Deploy and run the Docker container on the server. Utilize the `@nx/node:setup-docker` generator to streamline the Docker setup process.
|
||||
Create a Dockerfile that specifies the application's environment and dependencies. Build a Docker image and optionally push it to a container registry. Deploy and run the Docker container on the server. Use the `@nx/node:setup-docker` generator to set up Docker for your project.
|
||||
|
||||
2. **Installing Dependencies on the Server:**
|
||||
Transfer the build artifacts to the server, install all dependencies using the package manager of your choice, and start the application. Ensure that [NxAppWebpackPlugin](/docs/technologies/build-tools/webpack/guides/webpack-plugins#nxappwebpackplugin) is configured with `generatePackageJson: true` so that the build artifacts directory includes `package.json` and `package-lock.json` (or the equivalent files for other package managers).
|
||||
|
||||
@@ -10,6 +10,17 @@ Expo is an open-source framework for apps that run natively on Android, iOS, and
|
||||
|
||||
Expo is a set of tools built on top of React Native. The Nx Plugin for Expo contains generators for managing Expo applications and libraries within an Nx workspace.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/expo` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| -------------- | -------------------- |
|
||||
| `metro-config` | >= 0.82.0 |
|
||||
| `expo` | ~53.0.0 \|\| ~54.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up Expo
|
||||
|
||||
To create a new workspace with Expo, run the following command:
|
||||
|
||||
@@ -12,6 +12,16 @@ The React plugin for Nx, `@nx/react`, provides generators for [applications and
|
||||
|
||||
You don't need the plugin to use React with Nx. Any project already benefits from [caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph). The plugin simplifies scaffolding and code generation.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/react` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------- | -------------------- |
|
||||
| `react` | ^18.0.0 \|\| ^19.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
{% aside type="tip" title="Using a React Meta-Framework?" %}
|
||||
If you're building with **Next.js** or **Remix**, use their dedicated plugins which include inferred task support. See the [Next.js plugin](/docs/technologies/react/next/introduction) or [Remix plugin](/docs/technologies/react/remix/introduction) hub pages. For **React Router** in framework mode, see the [React Router guide](/docs/technologies/react/guides/react-router).
|
||||
{% /aside %}
|
||||
|
||||
@@ -12,6 +12,16 @@ The Next.js plugin for Nx, `@nx/next`, automatically [infers `build`, `dev`, and
|
||||
|
||||
You don't need the plugin to use Next.js with Nx. Any project already benefits from [caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph). The plugin adds automatic task inference, code generators, and simplified configuration.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/next` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------- | ------------------ |
|
||||
| `next` | >=14.0.0 <17.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/next
|
||||
|
||||
### Add to an Existing Nx Workspace
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
title: Overview of the Nx React Native Plugin
|
||||
description: The Nx Plugin for React Native contains generators for managing React Native applications and libraries within an Nx workspace. This page also explains how to configure React Native on your Nx workspace.
|
||||
title: React Native Plugin for Nx
|
||||
description: The Nx Plugin for React Native contains generators for managing React Native applications and libraries within an Nx workspace, including setup and configuration.
|
||||
sidebar:
|
||||
label: 'Introduction'
|
||||
filter: 'type:References'
|
||||
---
|
||||
|
||||
React Native brings React's declarative UI framework to iOS and Android. With React Native, you use native UI controls and have full access to the native platform.
|
||||
React Native brings the React declarative UI framework to iOS and Android. With React Native, you use native UI controls and have full access to the native platform.
|
||||
|
||||
The Nx Plugin for React Native contains generators for managing React Native applications and libraries within an Nx workspace. It provides:
|
||||
|
||||
@@ -14,6 +14,17 @@ The Nx Plugin for React Native contains generators for managing React Native app
|
||||
- Scaffolding for creating buildable libraries that can be published to npm.
|
||||
- Utilities for automatic workspace refactoring.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/react-native` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| -------------- | ------------------ |
|
||||
| `metro-config` | >= 0.82.0 |
|
||||
| `react-native` | ~0.79.3 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up React Native
|
||||
|
||||
### Create a New Workspace
|
||||
|
||||
@@ -16,6 +16,16 @@ You don't need the plugin to use Remix with Nx. Any project already benefits fro
|
||||
React Router is the successor to Remix. For new projects, consider using [React Router](/docs/technologies/react/guides/react-router) instead. Existing Remix projects continue to work with `@nx/remix`.
|
||||
{% /aside %}
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/remix` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ---------------- | ------------------ |
|
||||
| `@remix-run/dev` | ^2.17.3 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/remix
|
||||
|
||||
### Add to an Existing Nx Workspace
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview of the Nx Cypress Plugin
|
||||
description: The Nx Plugin for Cypress contains executors and generators that support e2e testing with Cypress. This page also explains how to configure Cypress on your Nx workspace.
|
||||
title: Cypress Plugin for Nx
|
||||
description: The Nx Plugin for Cypress contains executors and generators that support e2e testing with Cypress, including setup and configuration for your Nx workspace.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
@@ -15,6 +15,16 @@ Cypress is a test runner built for the modern web. It has a lot of great feature
|
||||
- Network traffic control
|
||||
- Screenshots and videos
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/cypress` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| --------- | ------------------ |
|
||||
| `cypress` | >= 13 < 16 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/cypress
|
||||
|
||||
> Info about [Cypress Component Testing can be found here](/docs/technologies/test-tools/cypress/guides/cypress-component-testing)
|
||||
@@ -99,7 +109,7 @@ The options shown above control the names of the inferred Cypress tasks. The fol
|
||||
|
||||
### Splitting E2E tasks by file
|
||||
|
||||
The `@nx/cypress/plugin` will automatically split your e2e tasks by file. You can read more about the Atomizer feature [here](/docs/features/ci-features/split-e2e-tasks).
|
||||
The `@nx/cypress/plugin` will automatically split your e2e tasks by file. Read more about the [Atomizer feature](/docs/features/ci-features/split-e2e-tasks).
|
||||
|
||||
To enable e2e task splitting, make sure there is a `ciWebServerCommand` property set in your `cypress.config.ts` file. It will look something like this:
|
||||
|
||||
@@ -264,7 +274,7 @@ If no `baseUrl` and no `devServerTarget` are provided, Cypress will expect to ha
|
||||
|
||||
If you need to fine tune your Cypress setup, you can do so by modifying `cypress.config.ts` in the project root. For
|
||||
instance,
|
||||
you can easily add your `projectId` to save all the screenshots and videos into your Cypress dashboard. The complete
|
||||
you can add your `projectId` to save all the screenshots and videos into your Cypress dashboard. The complete
|
||||
configuration is documented
|
||||
on [the official website](https://docs.cypress.io/guides/references/configuration.html#Options).
|
||||
|
||||
@@ -276,7 +286,7 @@ If you need to pass a variable to Cypress that you don't want to commit to your
|
||||
|
||||
There are a handful of ways to pass environment variables to Cypress, but the most common is going to be via the [`cypress.env.json` file](https://docs.cypress.io/guides/guides/environment-variables#Option-1-configuration-file), the `-e` Cypress arg or the `env` option from the `@nx/cypress:cypress` executor in the [project configuration](/docs/reference/project-configuration#task-definitions-targets) or the command line.
|
||||
|
||||
Create a `cypress.env.json` file in the projects root (i.e. `apps/my-cool-app-e2e/cypress.env.json`). Cypress will automatically pick up this file. This method is helpful for configurations that you don't want to commit. Just don't forget to add the file to the `.gitignore` and add documentation so people in your repo know what values to populate in their local copy of the `cypress.env.json` file.
|
||||
Create a `cypress.env.json` file in the projects root (i.e. `apps/my-cool-app-e2e/cypress.env.json`). Cypress will automatically pick up this file. This method is helpful for configurations that you don't want to commit. Make sure to add the file to the `.gitignore` and add documentation so people in your repo know what values to populate in their local copy of the `cypress.env.json` file.
|
||||
|
||||
Setting the `-e` Cypress arg or the `env` option from the `@nx/cypress:cypress` executor in the project configuration is a good way to add values you want to define that you don't mind committing to the repository, such as a base API URL.
|
||||
|
||||
|
||||
@@ -14,6 +14,16 @@ Detox is gray box end-to-end testing and automation library for mobile apps. It
|
||||
- Test Runner Independent
|
||||
- Debuggable
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/detox` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------- | ------------------ |
|
||||
| `detox` | ^20.9.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up Detox
|
||||
|
||||
### Setup Environment
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview of the Nx Jest Plugin
|
||||
description: The Nx Plugin for Jest contains executors and generators that support testing projects using Jest. This page also explains how to configure Jest on your Nx workspace.
|
||||
title: Jest Plugin for Nx
|
||||
description: The Nx Plugin for Jest contains executors and generators that support testing projects using Jest, including setup and configuration for your Nx workspace.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
@@ -12,6 +12,16 @@ The `@nx/jest` plugin adds [inferred Jest targets](#configuration), a [Jest conf
|
||||
|
||||
You can use Jest with Nx without the plugin and still get [task caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph).
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/jest` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------- | -------------------- |
|
||||
| `jest` | ^29.0.0 \|\| ^30.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setup
|
||||
|
||||
### Add to an existing workspace
|
||||
@@ -234,7 +244,7 @@ Organize tests by feature to get better cache hits and more targeted CI runs. Se
|
||||
|
||||
Typically, in CI it's recommended to use `nx affected -t test --parallel=[# CPUs] --runInBand` for the best performance.
|
||||
|
||||
This is because each jest process creates workers based on system resources, running multiple projects via Nx and using jest workers will create too many processes overall causing the system to run slower than desired. Using the `--runInBand` flag tells jest to run in a single process. You can then leverage Nx parallelism to run multiple jest projects at once.
|
||||
This is because each Jest process creates workers based on system resources, and running multiple projects via Nx with Jest workers will create too many processes overall, causing the system to run slower than desired. Using the `--runInBand` flag tells Jest to run in a single process. You can then use Nx parallelism to run multiple Jest projects at once.
|
||||
|
||||
### Batch Mode
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview of the Nx Playwright Plugin
|
||||
description: The Nx Plugin for Playwright contains executors and generators that support e2e testing with Playwright. This page also explains how to configure Playwright on your Nx workspace.
|
||||
title: Playwright Plugin for Nx
|
||||
description: The Nx Plugin for Playwright contains executors and generators that support e2e testing with Playwright, including setup and configuration for your Nx workspace.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
@@ -14,6 +14,16 @@ Playwright is a modern web test runner. With included features such as:
|
||||
- Test generation
|
||||
- Screenshots and videos
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/playwright` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------------------ | ------------------ |
|
||||
| `@playwright/test` | ^1.36.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/playwright
|
||||
|
||||
### Installation
|
||||
@@ -68,7 +78,7 @@ The `targetName` and `ciTargetName` options control the name of the inferred Pla
|
||||
|
||||
### Splitting E2E Tests
|
||||
|
||||
`@nx/playwright/plugin` leverages Nx Atomizer to split your e2e tests into smaller tasks in a fully automated way. This allows for a much more efficient distribution of tasks in CI. You can read more about the Atomizer feature [here](/docs/features/ci-features/split-e2e-tasks).
|
||||
`@nx/playwright/plugin` uses Nx Atomizer to automatically split your e2e tests into smaller tasks for more efficient distribution in CI. Read more about the [Atomizer feature](/docs/features/ci-features/split-e2e-tasks).
|
||||
|
||||
If you would like to disable Atomizer for Playwright tasks, set `ciTargetName` to `false`.
|
||||
|
||||
|
||||
@@ -1,15 +1,30 @@
|
||||
---
|
||||
title: Nx Storybook Plugin Overview
|
||||
title: Storybook Plugin for Nx
|
||||
description: This is an overview page for the Storybook plugin in Nx. It explains what Storybook is and how to set it up in your Nx workspace.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
---
|
||||
|
||||
[Storybook](https://storybook.js.org) is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.
|
||||
[Storybook](https://storybook.js.org) is a development environment for UI components. Browse a component library, view the different states of each component, and interactively develop and test components.
|
||||
|
||||
This guide will briefly walk you through using Storybook within an Nx workspace.
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/storybook` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ----------- | ------------------ |
|
||||
| `storybook` | >=8.0.0 <11.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
<!-- The peerDependencies in @nx/storybook's package.json declares >=7.0.0 so that
|
||||
users who still have Storybook 7 installed get a friendlier error from Nx
|
||||
rather than a cryptic package-manager resolution failure. Storybook 7 is
|
||||
no longer actively supported. -->
|
||||
|
||||
## Setting Up Storybook
|
||||
|
||||
### Installation
|
||||
@@ -169,7 +184,7 @@ nx test-storybook project-name
|
||||
|
||||
### Anatomy of the Storybook setup
|
||||
|
||||
When running the Nx Storybook generator, it'll configure the Nx workspace to be able to run Storybook seamlessly. It'll create a project specific Storybook configuration.
|
||||
When running the Nx Storybook generator, it configures the Nx workspace to run Storybook and creates a project-specific Storybook configuration.
|
||||
|
||||
The project-specific Storybook configuration is pretty much similar to what you would have for a non-Nx setup of Storybook. There's a `.storybook` folder within the project root folder.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview of the Nx Vitest Plugin
|
||||
description: The Nx Plugin for Vitest contains executors and generators that support testing projects using Vitest. This page also explains how to configure Vitest on your Nx workspace.
|
||||
title: Vitest Plugin for Nx
|
||||
description: The Nx Plugin for Vitest contains executors and generators that support testing projects using Vitest, including setup and configuration for your Nx workspace.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
@@ -12,6 +12,16 @@ The `@nx/vitest` plugin adds [inferred Vitest targets](#configuration), a [proje
|
||||
|
||||
You can use Vitest with Nx without the plugin and still get [task caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph).
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/vite` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| -------- | ------------------------------------------ |
|
||||
| `vitest` | ^1.0.0 \|\| ^2.0.0 \|\| ^3.0.0 \|\| ^4.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setup
|
||||
|
||||
### Add to an existing workspace
|
||||
|
||||
@@ -12,7 +12,15 @@ The TypeScript plugin for Nx, `@nx/js`, provides [generators for creating TypeSc
|
||||
|
||||
You don't need the plugin to use TypeScript with Nx, any project already benefits from [caching](/docs/features/cache-task-results), [task orchestration](/docs/features/run-tasks), and the [project graph](/docs/features/explore-graph). The plugin can help simplify setups and maintenance of TypeScript projects at scale.
|
||||
|
||||
See the [TypeScript compatibility matrix](/docs/reference/nodejs-typescript-compatibility#typescript-compatibility) for supported TypeScript versions.
|
||||
## Requirements
|
||||
|
||||
Nx supports the latest version of TypeScript. TypeScript itself only officially supports its latest release under the [Modern Lifecycle Policy](https://learn.microsoft.com/en-us/lifecycle/policies/modern), but Nx maintains a wider range to give you time to upgrade. Support for an older TypeScript version may be dropped in an Nx major release, and support for a newer version may be added in an Nx minor release.
|
||||
|
||||
| Nx Version | TypeScript Version |
|
||||
| -------------- | ------------------ |
|
||||
| 22.x (current) | >= 5.4.2 < 5.10.0 |
|
||||
| 21.x | >= 5.4.2 < 5.10.0 |
|
||||
| 20.x | ~5.4.2 |
|
||||
|
||||
## Setting Up @nx/js plugin
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview of the Nx Vue Plugin
|
||||
description: The Nx Plugin for Vue contains generators for managing Vue applications and libraries within an Nx workspace. This page also explains how to configure Vue on your Nx workspace.
|
||||
title: Vue Plugin for Nx
|
||||
description: The Nx Plugin for Vue contains generators for managing Vue applications and libraries within an Nx workspace, including setup and configuration.
|
||||
sidebar:
|
||||
label: 'Introduction'
|
||||
filter: 'type:References'
|
||||
@@ -8,6 +8,16 @@ filter: 'type:References'
|
||||
|
||||
The Nx plugin for [Vue](https://vuejs.org/).
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/vue` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------- | ------------------ |
|
||||
| `vue` | ^3.5.13 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting Up @nx/vue
|
||||
|
||||
### Generating a new Workspace
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview of the Nx Nuxt Plugin
|
||||
description: The Nx Plugin for Nuxt contains generators for managing Nuxt applications within a Nx workspace. This page also explains how to configure Nuxt on your Nx workspace.
|
||||
title: Nuxt Plugin for Nx
|
||||
description: The Nx Plugin for Nuxt contains generators for managing Nuxt applications within an Nx workspace, including setup and configuration.
|
||||
sidebar:
|
||||
label: Introduction
|
||||
filter: 'type:References'
|
||||
@@ -8,6 +8,16 @@ filter: 'type:References'
|
||||
|
||||
The Nx plugin for [Nuxt](https://nuxt.com/).
|
||||
|
||||
## Requirements
|
||||
|
||||
The `@nx/nuxt` plugin supports the following package versions.
|
||||
|
||||
| Package | Supported Versions |
|
||||
| ------- | ------------------- |
|
||||
| `nuxt` | ^3.10.0 \|\| ^4.0.0 |
|
||||
|
||||
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
|
||||
|
||||
## Setting up a new Nx workspace with @nx/nuxt
|
||||
|
||||
You can create a new workspace that uses Nuxt with one of the following commands:
|
||||
@@ -95,7 +105,7 @@ To perform end-to-end (E2E) testing on static HTML files using a test runner lik
|
||||
|
||||
This feature is particularly useful for testing in continuous integration (CI) pipelines, where resources may be constrained. Unlike the `serve` target, `serve-static` does not require a Nuxt's Nitro server to operate, making it more efficient and faster by eliminating background processes, such as file change monitoring.
|
||||
|
||||
To utilize the `serve-static` target for testing, run the following command:
|
||||
To use the `serve-static` target for testing, run the following command:
|
||||
|
||||
```shell
|
||||
nx serve-static my-nuxt-app-e2e
|
||||
|
||||
@@ -15,6 +15,7 @@ const { Content, headings } = await render(nxCli);
|
||||
...nxCli.data,
|
||||
title: 'Nx Commands',
|
||||
description: 'Complete reference for Nx CLI',
|
||||
tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 3 },
|
||||
}}
|
||||
headings={headings || []}
|
||||
>
|
||||
|
||||
@@ -213,11 +213,12 @@ The Nx command line has various subcommands and options to help you manage your
|
||||
Below is a complete reference for all available commands and their options.
|
||||
You can run nx --help to view all available options.
|
||||
|
||||
## Available Commands
|
||||
|
||||
${flattenedCommands
|
||||
.map(({ fullName, cmd, parentOptions }) => {
|
||||
let section = `### \`nx ${fullName}\`\n`;
|
||||
const isSubCommand = parentOptions !== undefined;
|
||||
const headingLevel = isSubCommand ? '###' : '##';
|
||||
|
||||
let section = `${headingLevel} \`nx ${fullName}\`\n`;
|
||||
|
||||
section += cmd.description || 'No description available';
|
||||
|
||||
@@ -228,9 +229,20 @@ ${flattenedCommands
|
||||
}
|
||||
|
||||
// Build the usage command string
|
||||
const usageCmd = cmd.command
|
||||
? cmd.command.replace('$0', fullName)
|
||||
: fullName;
|
||||
let usageCmd: string;
|
||||
if (cmd.command && cmd.command.includes('$0')) {
|
||||
// Has $0 placeholder - replace with full name
|
||||
usageCmd = cmd.command.replace('$0', fullName);
|
||||
} else if (cmd.command && parentOptions !== undefined) {
|
||||
// Sub-command without $0: use fullName, append positional args from cmd.command
|
||||
const firstSpaceIdx = cmd.command.indexOf(' ');
|
||||
usageCmd =
|
||||
firstSpaceIdx !== -1
|
||||
? fullName + cmd.command.substring(firstSpaceIdx)
|
||||
: fullName;
|
||||
} else {
|
||||
usageCmd = cmd.command || fullName;
|
||||
}
|
||||
|
||||
section += `\n\n**Usage:**
|
||||
\`\`\`bash
|
||||
|
||||
@@ -5,7 +5,6 @@ authors: ['Victor Savkin', 'Philip Fulcher']
|
||||
tags: ['nx']
|
||||
cover_image: /blog/images/2026-01-09/header.avif
|
||||
description: 'Discover why AI agents underperform in polyrepos and how Nx monorepos unlock 30% productivity gains. Learn why architecture matters for AI agent success.'
|
||||
pinned: true
|
||||
---
|
||||
|
||||
## Nx doesn't just make monorepos manageable. It makes AI agents effective.
|
||||
|
||||
@@ -15,6 +15,7 @@ metrics:
|
||||
label: 'projects unified'
|
||||
- value: '2x faster'
|
||||
label: 'CI pipelines'
|
||||
pinned: true
|
||||
---
|
||||
|
||||
Broadcom is a global technology leader providing semiconductor, enterprise software, and security solutions to thousands of customers worldwide. Their engineering organization manages a wide portfolio of complex applications, including the [VMware](https://www.vmware.com/) suite of products. Their frontend architecture team has spent nearly a decade figuring out how to manage this portfolio efficiently.
|
||||
|
||||
@@ -5,6 +5,7 @@ authors: ['Max Kless']
|
||||
tags: [nx, ai, mcp]
|
||||
cover_image: /blog/images/articles/bg-mcp-to-skills.avif
|
||||
description: 'How the shift from MCP tools to agent skills changed the way AI assistants work with Nx monorepos — and why MCP still matters.'
|
||||
pinned: true
|
||||
---
|
||||
|
||||
Remember when MCP was the hot new thing? That was barely a year ago. We built [MCP tools for Nx](/blog/nx-made-cursor-smarter) — surfacing project graphs, generator schemas, task pipelines directly into LLM conversations — and for the first time AI assistants could actually _understand_ your workspace. We shipped integrations for Cursor, VS Code Copilot, and JetBrains, and it worked well.
|
||||
|
||||
@@ -9,9 +9,8 @@ authors: ['Jeff Cross', 'Juri Strumpflohner']
|
||||
tags: [webinar]
|
||||
cover_image: /blog/images/2026-02-18/Feb2026-webinar-card.avif
|
||||
time: 2pm ET/7pm UTC
|
||||
status: Upcoming
|
||||
status: Past - Gated
|
||||
registrationUrl: https://go.nx.dev/feb2026-webinar
|
||||
pinned: true
|
||||
---
|
||||
|
||||
**Feb 18, 2026 - 2pm ET/7pm UTC**
|
||||
@@ -22,4 +21,4 @@ Monorepo architecture has evolved significantly in the past few years, yet the l
|
||||
|
||||
This webinar will provide a clear framework for understanding monorepos in 2026, cutting through the noise to explain how they deliver measurable impact. Particularly for organizations working to ship at AI-accelerated speeds.
|
||||
|
||||
{% call-to-action title="Register today!" url="https://go.nx.dev/feb2026-webinar" description="Save your spot" /%}
|
||||
{% call-to-action title="Download the recording!" url="https://go.nx.dev/feb2026-webinar" description="Sign up to gain access" /%}
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
---
|
||||
title: 'A Monorepo Is NOT a Monolith'
|
||||
slug: 'monorepo-is-not-monolith'
|
||||
authors: ['Victor Savkin', 'Juri Strumpflohner']
|
||||
tags: [nx, monorepo]
|
||||
cover_image: /blog/images/articles/monorepo-is-not-monolith-bg.avif
|
||||
hideCoverImage: true
|
||||
description: 'Common objections to monorepos debunked: they are not monoliths, they scale, and they work great with AI.'
|
||||
---
|
||||
|
||||
I've been building dev tools for monorepos and helping companies use them for years. **And I've been hearing similar objections to the monorepo idea from many teams:**
|
||||
|
||||
- It forces us to release together. Monoliths are bad.
|
||||
- It lets other teams change my code without my knowing.
|
||||
- It creates a big ball of mud. It makes applications hard to understand and maintain.
|
||||
- It doesn't scale.
|
||||
- AI tools can't handle large monorepos.
|
||||
|
||||
Many of them arise from confusion, often after trying a basic workspace setup, seeing a bunch of problems, and concluding that it is not a viable approach for multi-project-multi-team scenarios.
|
||||
|
||||
In this article, **I will show what a proper monorepo setup looks like and talk about common misconceptions related to monorepos.**
|
||||
|
||||
Monorepos are not a silver bullet. Nothing is. But hopefully **at the end of this article, you will have a clear understanding of the benefits a monorepo brings, what _actual_ challenges you will face, and if it is the right approach for your organization.**
|
||||
|
||||
_For the examples in this post, I will use [Nx](/docs/getting-started/intro), an extensible build system optimized for monorepos. But the concepts apply broadly to any monorepo tooling._
|
||||
|
||||
{% toc /%}
|
||||
|
||||
## What is a Monorepo?
|
||||
|
||||
**Monorepo-style development is a software development approach where**:
|
||||
|
||||
- You develop multiple projects in the same repository.
|
||||
- The projects can depend on each other, so they can share code.
|
||||
- When you make a change, you do not rebuild or retest every project in the monorepo. Instead, you only rebuild and retest the projects that can be affected by your change.
|
||||
|
||||
That last point is crucial for two reasons:
|
||||
|
||||
**It keeps CI fast.** On a large scale, running only what's affected can be orders of magnitude faster than rebuilding everything. Layer on [remote caching](/docs/concepts/how-caching-works) so work that's already been done is never repeated, and [distribute tasks across machines](/docs/features/ci-features/distribute-task-execution) intelligently, and you have a CI pipeline that scales with your codebase rather than against it.
|
||||
|
||||
**It gives teams independence.** If two projects A and B do not depend on each other, they cannot affect each other. Team A will be able to develop their project, test it, build it, merge PRs into master without ever having to run any code written by Team B. Team B can have flaky tests, poorly typed code, broken code, broken tests. None of it matters to Team A.
|
||||
|
||||
## Misconceptions
|
||||
|
||||
### A Monorepo Is NOT a Monolith
|
||||
|
||||
> "Will we have to release all on the same day? I don't like monoliths!"
|
||||
|
||||
It's a common misconception, which comes from a strong association of a repository with a deployment artifact.
|
||||
|
||||
But it is not hard to see that **where you develop your code and what/when you deploy are actually orthogonal concerns**. Google, for instance, has thousands of applications in its monorepo, but obviously, all of them are not released together.
|
||||
|
||||
Moreover, it's actually a good CI/CD practice to build and store artifacts when doing CI, and deploy the stored artifacts to different environments during the deployment phase. In other words, **deploying an application should not require access to any repository**, one or many.
|
||||
|
||||
**So a monorepo is not a monolith. Quite the contrary, because monorepos simplify code sharing and cross-project refactorings, they significantly lower the cost of creating libs, microservices and microfrontends. So adopting a monorepo often enables more deployment flexibility.**
|
||||
|
||||
### It lets other teams change my code without my knowing
|
||||
|
||||
> "Another team can break my app, without my knowing, right before the release!"
|
||||
|
||||
This misconception originates from folks only using repository settings to control access and permissions. Not many know that **many tools let you configure ownership on the folder basis**.
|
||||
|
||||
For instance, GitHub has a feature called [CODEOWNERS](https://help.github.com/en/articles/about-code-owners). You can provision a file that looks like this:
|
||||
|
||||
```rb
|
||||
apps/app-a/* @susan
|
||||
apps/app-b/* @bob
|
||||
```
|
||||
|
||||
With this configuration, if you have a PR updating App A, Susan will have to approve it. If the PR touches only App B, Bob will have to approve it. And if the PR touches A and B, both Susan and Bob will have to approve it.
|
||||
|
||||
Nx takes this further with [`@nx/owners`](/docs/reference/owners/overview), which lets you define ownership based on **projects and tags** rather than raw file paths. Ownership rules are defined in `nx.json` or per-project `package.json` (or `project.json`) and compiled into standard CODEOWNERS files via `nx sync`. This means ownership stays in sync with your project structure automatically, instead of requiring you to manually maintain path patterns.
|
||||
|
||||
You actually get more control over code ownership. Look here:
|
||||
|
||||

|
||||
|
||||
We have two teams in the org. Team B want to share code between their applications, so they created a library shared-b. This library is private, so they don't want Team A to depend on it. Why? Because if it happens, the teams will get coupled to each other, and Team B will have to account for Team A when changing the shared library.
|
||||
|
||||
In a multi-repo setup, nothing prevents Team A from adding shared-b to their `package.json`. It is hard for Team B to know about it because it is done in a repository they do not control. Most monorepo tools (including Nx) allow you to define the visibility of a library in a precise way. So when trying to import shared-b, you see this:
|
||||
|
||||

|
||||
|
||||
### It creates a big ball of mud
|
||||
|
||||
> "Even one of our applications is barely manageable. If we put five of them in the same repo, no one will be able to understand anything at all!"
|
||||
|
||||
This misconception comes from the fact that in most repositories any file can import any other file. Folks try to impose some structure during code reviews, but things do not stay well-defined for long, and the dependency graph gets muddled.
|
||||
|
||||
Everyone knows this. Open a mid-sized project (maybe 50k lines of code), and draw a dependency diagram of its main components and how they depend on each other. Now check it against the repository. You will find a lot of "unexpected" edges in the graph.
|
||||
|
||||
With Nx, you can create libraries that have well-defined public APIs. And because creating libraries takes just a few seconds, folks tend to create more libraries. So a typical application will be partitioned into dozens of libraries, which can depend on each other only through their public APIs.
|
||||
|
||||

|
||||
|
||||
Nx also automates the generation of the dependency graph which you can view by running `nx graph`.
|
||||
|
||||

|
||||
|
||||
In opposite to the diagram created by some architect you can find in your wiki, which became outdated the day after it was created, this graph is correct and up to date.
|
||||
|
||||
You can also [enforce module boundaries](/docs/features/enforce-module-boundaries) by adding tags to your projects and defining dependency constraints. For instance, you can tag projects with `scope:client` or `scope:shared` and create rules like "client-scoped projects can only depend on client or shared projects." These constraints are enforced at lint time via the `@nx/enforce-module-boundaries` ESLint rule, meaning violations are caught before code is even committed. You can statically guarantee that presentation components cannot depend on state management code, or that a team's private library cannot be imported by another team.
|
||||
|
||||

|
||||
|
||||
Funny enough, this is another case where using monorepos results in the opposite of what a lot of folks think.
|
||||
|
||||
### It does not scale
|
||||
|
||||
> "Am I to expect 5 hour CI time?"
|
||||
|
||||
Rebuilding and retesting everything on every commit is slow. It does not scale beyond a handful of projects. But as mentioned above, when using monorepo tools, you only rebuild and retest what is affected.
|
||||
|
||||
Modern monorepo tooling provides a layered scaling strategy that you can adopt incrementally:
|
||||
|
||||
1. **Affected commands**: only run tasks for projects impacted by your change. This alone can cut CI time dramatically.
|
||||
2. **Local and remote caching**: never redo work that's already been done. [Remote caching](/docs/concepts/how-caching-works) (via Nx Replay) shares results across your team and CI, so if a teammate already built that library, you get the result instantly.
|
||||
3. **Distributed task execution**: when a single machine isn't enough, [Nx Agents](/docs/features/ci-features/distribute-task-execution) dynamically distribute tasks across multiple machines based on the dependency graph and historical runtime data.
|
||||
4. **Task atomization**: large test suites become a bottleneck even with distribution. The [Atomizer](/docs/features/ci-features/split-e2e-tasks) splits monolithic e2e or integration test targets into per-file tasks that can run in parallel. A 10-minute e2e suite becomes five 2-minute tasks spread across agents.
|
||||
|
||||
Each layer builds on the previous one, and you only adopt what you need at your current scale.
|
||||
|
||||
> "Is git going to break?"
|
||||
|
||||
This concern is not truly unjustified. If your repo has millions of files, many tools you know and love, including plain Git, will stop working. However, most monorepos do not have thousands of apps. They have a dozen apps built by a single org. Thousands of files, millions of lines of code. All the tools you use can handle this without any problems.
|
||||
|
||||
Microsoft released [Scalar](https://github.com/microsoft/scalar), a tool that enables Git to work with enormous repos. Azure Pipelines, BitBucket, and GitHub all support it.
|
||||
|
||||
### AI doesn't work in monorepos
|
||||
|
||||
> "My codebase is too big, AI tools will be overwhelmed!"
|
||||
|
||||
A common concern is that AI coding agents can't handle monorepos because there's too much code, too many projects, too much context. In practice, the opposite is true. Monorepo tooling provides exactly the structure AI agents need: a project graph that maps dependencies, consistent conventions across projects, and clear module boundaries. Instead of an agent guessing how your 15 repos relate to each other, it can query the graph and understand the architecture instantly.
|
||||
|
||||
Nx is built to work with AI agents. The CLI is optimized for agent navigation, and dedicated [Nx agent skills](/blog/nx-ai-agent-skills) teach your AI how to explore the workspace, run tasks, scaffold code following your conventions, and even monitor CI pipelines. On the CI side, [self-healing CI](/docs/features/ci-features/self-healing-ci) uses AI to automatically detect and fix pipeline failures, posting fixes as PR comments or auto-applying high-confidence patches. Monorepos don't overwhelm AI: they give it the structure to actually be effective.
|
||||
|
||||
If you want to dive deeper into how Nx and AI work together, check out:
|
||||
|
||||
- [Nx and AI: Why They Work so Well Together](/blog/nx-and-ai-why-they-work-together)
|
||||
- [End to End Autonomous AI Agent Workflows with Nx](/blog/autonomous-ai-workflows-with-nx)
|
||||
- [Autonomous Agents at Scale](/blog/ai-agents-and-continuity)
|
||||
|
||||
{% callout type="note" title="Dive deeper" %}
|
||||
We cover additional misconceptions (polyglot support, lockstep versioning, dependency hell, and more) in [10 Monorepo Myths Debunked](/blog/monorepo-myths-debunked).
|
||||
{% /callout %}
|
||||
|
||||
## Real Challenges
|
||||
|
||||
The things listed above are misconceptions. It does not mean that monorepos are perfect. They come with their own challenges.
|
||||
|
||||
### Trunk-based development
|
||||
|
||||
Monorepos and long-lived feature branches do not play together nicely. Chances are you will have to adopt some form of [trunk-based development](https://trunkbaseddevelopment.com/). Transitioning to this style of development can be challenging for some teams, partially because they have to adopt new practices such as feature toggles.
|
||||
|
||||
Trunk-based development results in better quality code and higher velocity regardless of repo size, but it is still something you must take into account.
|
||||
|
||||
### CI
|
||||
|
||||
Moving to a monorepo requires you to rethink how you do continuous integration. You are no longer building a single app: you are building only the things affected by your change, caching aggressively, and potentially distributing work across machines.
|
||||
|
||||
The tooling gap that existed in 2019 has largely closed. Nx Cloud provides [remote caching](/docs/concepts/how-caching-works), [distributed task execution](/docs/features/ci-features/distribute-task-execution), [task atomization](/docs/features/ci-features/split-e2e-tasks), and [self-healing CI](/docs/features/ci-features/self-healing-ci) out of the box. The challenge is no longer "can I make this work" but rather tuning your pipeline as your codebase grows.
|
||||
|
||||
### Large-scale changes
|
||||
|
||||
Monorepos make some large-scale changes a lot simpler: you can refactor ten apps made out of a hundred libs, verify that they all work before committing the change.
|
||||
|
||||
But they force you to think through large-scale changes more and make some of them more difficult. For instance, if you change a shared library, you will affect all the applications that depend on it. If it is a breaking change, and it cannot be automated, you will have to make the change in a backward-compatible way. You will have to create two versions of the parameter/method/class/package and help folks move from the old version to the new one.
|
||||
|
||||
## Let's Recap
|
||||
|
||||
**Monorepos are known for the following benefits:**
|
||||
|
||||
- Everything at that current commit works together. Changes can be verified across all affected parts of the organization.
|
||||
- Easy to split code into composable modules
|
||||
- Easier dependency management
|
||||
- One toolchain setup
|
||||
- Code editors and IDEs are "workspace" aware
|
||||
- Consistent developer experience
|
||||
|
||||
**In spite of what folks say, they also:**
|
||||
|
||||
- Give you more deployment flexibility
|
||||
- Allow you to set up precise ownership policies
|
||||
- Provide more structure to your source code
|
||||
- Scale well with the right tooling (affected, caching, distribution, atomization)
|
||||
- Complement AI-assisted development rather than hinder it
|
||||
|
||||
**But they come with some challenges:**
|
||||
|
||||
- Trunk-based development is a lot more important
|
||||
- Require more sophisticated CI setup (though modern tooling handles most of it)
|
||||
- Require you to think about large-scale changes
|
||||
|
||||
## Learn More
|
||||
|
||||
- [Nx Docs](/docs/getting-started/intro)
|
||||
- [Nx Community Discord](https://go.nx.dev/community)
|
||||
- [X / Twitter](https://twitter.com/nxdevtools)
|
||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||
- [Nx YouTube Channel](https://www.youtube.com/@nxdevtools)
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: 'Nx Joins the Linux Foundation and the Agentic AI Foundation'
|
||||
slug: nx-joins-linux-foundation-and-aaif
|
||||
authors: ['Philip Fulcher']
|
||||
tags: ['nx']
|
||||
cover_image: /blog/images/2026-02-25/header.avif
|
||||
description: 'Nx joins the Linux Foundation and Agentic AI Foundation (AAIF) to help shape open standards for AI-powered development. Learn how the intersection of agentic AI and build tooling will transform software development workflows, and why Nx is committing to open collaboration with Anthropic, AWS, Google, and Microsoft to build the future of autonomous AI agents in developer tooling.'
|
||||
pinned: true
|
||||
---
|
||||
|
||||
As AI agents become central to how developers build and scale software, the need for open standards, shared tooling, and transparent governance has never been greater. Today, we're excited to announce that Nx is now a member of the [Linux Foundation](https://www.linuxfoundation.org) and the [Agentic AI Foundation (AAIF)](https://aaif.io).
|
||||
|
||||
## Building the Future of Agentic AI
|
||||
|
||||
The software development landscape is shifting. Agentic AI — autonomous systems that can plan, coordinate, and act across tools and codebases — is quickly moving from research concept to production reality. The companies and communities that define the standards for this new era will shape how millions of developers work for years to come.
|
||||
|
||||
The Linux Foundation has long served as the neutral, trusted home for the open source projects that power global infrastructure. The Agentic AI Foundation, formed in December 2025 under the Linux Foundation umbrella, extends that mission into the age of AI agents. Anchored by foundational projects like Anthropic's Model Context Protocol (MCP), Block's goose, and OpenAI's AGENTS.md, the AAIF is where the open standards for agentic AI are being built.
|
||||
|
||||
Nx is joining both foundations because we believe the future of developer tooling is inseparable from the future of agentic AI, and that future must be open.
|
||||
|
||||
## The Intersection of Agentic AI and Build Tooling
|
||||
|
||||
Nx has spent years building intelligent tooling that helps developers and teams manage complex codebases at scale. Our monorepo platform is used by organizations worldwide, empowering software developers across the JavaScript, TypeScript, and broader polyglot ecosystem.
|
||||
|
||||
As AI agents increasingly operate within these environments — navigating dependency graphs, orchestrating builds, generating and modifying code — the intersection of agentic AI and build tooling becomes critical. Nx is uniquely positioned to contribute to the standards and practices that ensure these agents work reliably, predictably, and at scale within real-world development workflows.
|
||||
|
||||
## What's Ahead
|
||||
|
||||
By joining the Linux Foundation and the AAIF, we're committing to collaborating with leaders across the ecosystem to advance open standards for agentic workflows. That means participating in working groups, contributing to shared specifications, and helping ensure that the tooling developers rely on every day is designed to work seamlessly with the next generation of AI-powered development.
|
||||
|
||||
We're looking forward to working alongside Anthropic, AWS, Google, Microsoft, and the many other organizations shaping this space. The era of agentic AI is here, and we're proud to help build it — together, and in the open.
|
||||
|
||||
_To learn more about the Linux Foundation, visit [linuxfoundation.org](http://linuxfoundation.org). To learn more about the Agentic AI Foundation, visit [aaif.io](http://aaif.io). And to learn more about Nx, visit [nx.dev](http://nx.dev)._
|
||||
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 421 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,38 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 220" width="400" height="220" font-family="system-ui, -apple-system, sans-serif" font-size="13">
|
||||
<!-- Row 1: e2e apps -->
|
||||
<rect x="10" y="10" width="100" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="60" y="33" text-anchor="middle">app-a-e2e</text>
|
||||
|
||||
<rect x="150" y="10" width="100" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="200" y="33" text-anchor="middle">app-b2-e2e</text>
|
||||
|
||||
<rect x="290" y="10" width="100" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="340" y="33" text-anchor="middle">app-b1-e2e</text>
|
||||
|
||||
<!-- Row 2: apps -->
|
||||
<rect x="10" y="90" width="100" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="60" y="113" text-anchor="middle">app-a</text>
|
||||
|
||||
<rect x="150" y="90" width="100" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="200" y="113" text-anchor="middle">app-b2</text>
|
||||
|
||||
<rect x="290" y="90" width="100" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="340" y="113" text-anchor="middle">app-b1</text>
|
||||
|
||||
<!-- Row 3: shared lib (ellipse) -->
|
||||
<ellipse cx="230" cy="185" rx="70" ry="22" fill="#fff3cd" stroke="#d4a017" stroke-width="1.5"/>
|
||||
<text x="230" y="190" text-anchor="middle">shared-b</text>
|
||||
|
||||
<!-- Arrows: e2e -> apps -->
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
|
||||
<line x1="60" y1="46" x2="60" y2="88" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
<line x1="200" y1="46" x2="200" y2="88" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
<line x1="340" y1="46" x2="340" y2="88" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Arrows: app-b2 and app-b1 -> shared-b -->
|
||||
<line x1="200" y1="126" x2="218" y2="162" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
<line x1="340" y1="126" x2="248" y2="164" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,57 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 340" width="420" height="340" font-family="system-ui, -apple-system, sans-serif" font-size="13">
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||
</marker>
|
||||
|
||||
<!-- Row 1: e2e apps -->
|
||||
<rect x="60" y="10" width="110" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="115" y="33" text-anchor="middle">agent-e2e</text>
|
||||
|
||||
<rect x="260" y="10" width="110" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="315" y="33" text-anchor="middle">tickets-e2e</text>
|
||||
|
||||
<!-- Row 2: apps -->
|
||||
<rect x="80" y="90" width="90" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="125" y="113" text-anchor="middle">agent</text>
|
||||
|
||||
<rect x="270" y="90" width="90" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="315" y="113" text-anchor="middle">tickets</text>
|
||||
|
||||
<!-- Row 3: libs -->
|
||||
<rect x="10" y="180" width="90" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="55" y="203" text-anchor="middle">agent-api</text>
|
||||
|
||||
<rect x="140" y="180" width="90" height="36" rx="3" fill="#f5f5f5" stroke="#888" stroke-width="1"/>
|
||||
<text x="185" y="203" text-anchor="middle">api</text>
|
||||
|
||||
<ellipse cx="320" cy="198" rx="60" ry="20" fill="#e8e8e8" stroke="#888" stroke-width="1"/>
|
||||
<text x="320" y="203" text-anchor="middle">ticket-list</text>
|
||||
|
||||
<!-- Row 4: data lib -->
|
||||
<ellipse cx="210" cy="295" rx="55" ry="20" fill="#e8e8e8" stroke="#888" stroke-width="1"/>
|
||||
<text x="210" y="300" text-anchor="middle">data</text>
|
||||
|
||||
<!-- Arrows: e2e -> apps -->
|
||||
<line x1="115" y1="46" x2="122" y2="88" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
<line x1="315" y1="46" x2="315" y2="88" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Arrows: agent -> agent-api, api -->
|
||||
<line x1="105" y1="126" x2="70" y2="178" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
<line x1="145" y1="126" x2="175" y2="178" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Arrows: tickets -> api, ticket-list -->
|
||||
<line x1="295" y1="126" x2="205" y2="178" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
<line x1="320" y1="126" x2="320" y2="176" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Arrows: agent-api -> data -->
|
||||
<line x1="75" y1="216" x2="170" y2="285" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Arrows: api -> data -->
|
||||
<line x1="190" y1="216" x2="205" y2="273" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Arrows: ticket-list -> data -->
|
||||
<line x1="295" y1="215" x2="248" y2="282" stroke="#555" stroke-width="1.2" marker-end="url(#arrow)"/>
|
||||
|
||||
<!-- Arrows: tickets -> data (wide curve around ticket-list) -->
|
||||
<path d="M 355,126 C 415,160 415,280 262,293" stroke="#555" stroke-width="1.2" fill="none" marker-end="url(#arrow)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
@@ -11,7 +11,7 @@ width="100%" /%}
|
||||
|
||||
{% cards cols="2" %}
|
||||
{% card title="TypeScript Project References & Workspaces Support" type="document" url="/docs/concepts/typescript-project-linking" /%}
|
||||
{% card title="New @nx/rsbuild Plugin" type="document" url="/docs/technologies/angular/angular-rsbuild/create-config" /%}
|
||||
{% card title="New @nx/rsbuild Plugin" type="document" url="/docs/technologies/angular/angular-rsbuild/introduction" /%}
|
||||
{% card title="Support for Rollup TypeScript Config" type="external" url="https://github.com/nrwl/nx/pull/28240" /%}
|
||||
{% card title="Expo v52 Support" type="external" url="https://github.com/nrwl/nx/pull/29142" /%}
|
||||
{% /cards %}
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('Angular Projects - Build and Test', () => {
|
||||
console.log(
|
||||
`The current es2015 bundle size is ${es2015BundleSize / 1000} KB`
|
||||
);
|
||||
expect(es2015BundleSize).toBeLessThanOrEqual(221000);
|
||||
expect(es2015BundleSize).toBeLessThanOrEqual(223000);
|
||||
|
||||
// check unit tests
|
||||
runCLI(
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"projectType": "application",
|
||||
"implicitDependencies": [
|
||||
"gradle",
|
||||
"gradle-project-graph",
|
||||
"gradle-batch-runner"
|
||||
":gradle-project-graph",
|
||||
":gradle-batch-runner"
|
||||
],
|
||||
"// targets": "to see all targets run: nx show project e2e-gradle --web",
|
||||
"targets": {}
|
||||
|
||||
@@ -36,14 +36,14 @@ describe('Gradle Plugin V1', () => {
|
||||
});
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should build', () => {
|
||||
it('should build without batch mode', () => {
|
||||
const projects = runCLI(`show projects`);
|
||||
expect(projects).toContain('app');
|
||||
expect(projects).toContain('list');
|
||||
expect(projects).toContain('utilities');
|
||||
expect(projects).toContain(gradleProjectName);
|
||||
|
||||
const buildOutput = runCLI('build app', { verbose: true });
|
||||
const buildOutput = runCLI('build app --no-batch', { verbose: true });
|
||||
expect(buildOutput).toContain('nx run list:build');
|
||||
expect(buildOutput).toContain(':list:classes');
|
||||
expect(buildOutput).toContain('nx run utilities:build');
|
||||
@@ -56,7 +56,7 @@ describe('Gradle Plugin V1', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should track dependencies for new app', () => {
|
||||
it('should track dependencies for new app without batch mode', () => {
|
||||
if (type === 'groovy') {
|
||||
createFile(
|
||||
`app2/build.gradle`,
|
||||
@@ -94,7 +94,7 @@ dependencies {
|
||||
}
|
||||
);
|
||||
|
||||
let buildOutput = runCLI('build app2', { verbose: true });
|
||||
let buildOutput = runCLI('build app2 --no-batch', { verbose: true });
|
||||
// app2 depends on app
|
||||
expect(buildOutput).toContain('nx run app:build');
|
||||
expect(buildOutput).toContain(':app:classes');
|
||||
|
||||
@@ -23,14 +23,14 @@ describe('Gradle', () => {
|
||||
});
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should build', () => {
|
||||
it('should build without batch mode', () => {
|
||||
const projects = runCLI(`show projects`);
|
||||
expect(projects).toContain('app');
|
||||
expect(projects).toContain('list');
|
||||
expect(projects).toContain('utilities');
|
||||
expect(projects).toContain(gradleProjectName);
|
||||
|
||||
let buildOutput = runCLI('build app', { verbose: true });
|
||||
let buildOutput = runCLI('build app --no-batch', { verbose: true });
|
||||
expect(buildOutput).toContain(':list:classes');
|
||||
expect(buildOutput).toContain(':utilities:classes');
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('Gradle', () => {
|
||||
expect(bootJarOutput).toContain(':app:bootJar');
|
||||
});
|
||||
|
||||
it('should track dependencies for new app', () => {
|
||||
it('should track dependencies for new app without batch mode', () => {
|
||||
if (type === 'groovy') {
|
||||
createFile(
|
||||
`app2/build.gradle`,
|
||||
@@ -86,7 +86,7 @@ dependencies {
|
||||
}
|
||||
);
|
||||
|
||||
let buildOutput = runCLI('build app2', { verbose: true });
|
||||
let buildOutput = runCLI('build app2 --no-batch', { verbose: true });
|
||||
// app2 depends on app
|
||||
expect(buildOutput).toContain(':app:classes');
|
||||
expect(buildOutput).toContain(':list:classes');
|
||||
@@ -109,8 +109,12 @@ dependencies {
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
runCLI('run app:test-ci--MessageUtilsTest', { verbose: true });
|
||||
runCLI('run list:test-ci--LinkedListTest', { verbose: true });
|
||||
runCLI('run app:test-ci--MessageUtilsTest --no-batch', {
|
||||
verbose: true,
|
||||
});
|
||||
runCLI('run list:test-ci--LinkedListTest --no-batch', {
|
||||
verbose: true,
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
@@ -153,7 +157,7 @@ dependencies {
|
||||
expect(output).toContain('gradle-classes');
|
||||
|
||||
// Verify prefixed target works
|
||||
const buildOutput = runCLI('run app:gradle-build');
|
||||
const buildOutput = runCLI('run app:gradle-build --no-batch');
|
||||
expect(buildOutput).toContain('BUILD SUCCESSFUL');
|
||||
});
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ export function createGradleProject(
|
||||
|
||||
e2eConsoleLogger(
|
||||
execSync(
|
||||
`${gradleCommand} :project-graph:publishToMavenLocal -PskipSign=true`,
|
||||
`${gradleCommand} :gradle-project-graph:publishToMavenLocal -PskipSign=true`,
|
||||
{
|
||||
cwd: `${__dirname}/../../../..`,
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ import {
|
||||
updateJson,
|
||||
} from '@nx/e2e-utils';
|
||||
|
||||
// TODO: Re-enable once @microsoft/api-extractor ESM import issue is resolved
|
||||
// See: https://github.com/qmhc/unplugin-dts/issues/461
|
||||
xdescribe('JS - TS solution setup', () => {
|
||||
describe('JS - TS solution setup', () => {
|
||||
beforeAll(() => {
|
||||
newProject({
|
||||
packages: ['@nx/js'],
|
||||
|
||||
@@ -46,9 +46,9 @@ describe('Maven', () => {
|
||||
expect(output).toContain('- install-ci:');
|
||||
});
|
||||
|
||||
it('should build Maven project with dependencies', () => {
|
||||
it('should build Maven project with dependencies without batch mode', () => {
|
||||
// Build app which depends on lib, which depends on utils
|
||||
let buildOutput = runCLI('run app:install', { verbose: true });
|
||||
let buildOutput = runCLI('run app:install --no-batch', { verbose: true });
|
||||
|
||||
// Should build dependencies first
|
||||
expect(buildOutput).toContain('BUILD SUCCESS');
|
||||
@@ -60,8 +60,8 @@ describe('Maven', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should run tests for Maven project', () => {
|
||||
const testOutput = runCLI('run utils:test', { verbose: true });
|
||||
it('should run tests for Maven project without batch mode', () => {
|
||||
const testOutput = runCLI('run utils:test --no-batch', { verbose: true });
|
||||
expect(testOutput).toContain('BUILD SUCCESS');
|
||||
});
|
||||
|
||||
@@ -118,7 +118,7 @@ describe('Maven', () => {
|
||||
expect(output).toContain('- mvn-install-ci:');
|
||||
|
||||
// Verify prefixed target works
|
||||
const buildOutput = runCLI('run app:mvn-compile');
|
||||
const buildOutput = runCLI('run app:mvn-compile --no-batch');
|
||||
expect(buildOutput).toContain('BUILD SUCCESS');
|
||||
});
|
||||
});
|
||||
|
||||