Tags: nrwl/nx
Tags
feat(repo): enable the tsgo compiler workspace-wide (#35926) ## Current Behavior The workspace builds and typechecks every first-party package with `tsc`. An earlier attempt to enable the Go-based TypeScript compiler (tsgo) for just `packages/nx` (#35047) was reverted (#35167) because mixing compilers caused `.tsbuildinfo` version-mismatch cascades — a downstream `tsc --build` would see a tsgo-stamped build info and recompile everything. ## Expected Behavior The entire `@nx/js/typescript` build + typecheck graph — packages, graph, tools, `e2e/**`, and `nx-dev/ui-fence` — compiles with `tsgo`. Now that every package is on `nodenext` (NXC-4538), a single compiler runs across the whole graph, so there is no cross-compiler `.tsbuildinfo` cascade. ### Changes - Install `@typescript/native-preview` and set `compiler: "tsgo"` on **both** `@nx/js/typescript` plugin entries (the package build/typecheck entry and the e2e/nx-dev typecheck entry — the latter does `tsc --build` with references into `packages/*`, so it had to move too). - `tsconfig.base.json`: switch to `nodenext` module resolution, remove `baseUrl` (tsgo removed it — `TS5102`), and set `strict: false` to preserve current tsc behavior (tsgo defaults strict on). - Align spec/e2e tsconfig `module` to `nodenext` (`TS5110`) and add `customConditions: ["@nx/nx-source"]` to the spec tsconfigs so test files resolve `@nx/*` subpaths to workspace **source** — notably `@nx/devkit/internal-testing-utils`, which is excluded from devkit's build so no declaration is emitted under nodenext. - Source fixes surfaced by tsgo: two accidental workspace-root (`baseUrl`-anchored) imports now use package names; `@nx/expo` `addJest` gets an explicit `Promise<GeneratorCallback>` return type; `@nx/angular` webpack-browser casts past the angular/webpack plugin type difference; `graph/client-e2e` cypress global augmentations and `AUTWindow` casts; `Task` mocks get the required `cache` field; `update-repos`/`create-embeddings` config fixes. ## Validation - `build-base`: **42 projects green** under tsgo. - `typecheck`: **53 projects, 0 errors** under tsgo (entire `@nx/js/typescript` graph). - lint / test / e2e: pending CI. > Note: tsgo's incremental/cached builds occasionally drop emitted declarations (observed with devkit's `internal-testing-utils`); a from-scratch build emits them. Worth watching in CI. The remaining `tsc` users — `astro-docs` (astro check), `nx-dev`'s Next.js build, and `@nx/angular`'s ng-packagr (ngc) — do **not** `tsc --build` the packages, so they don't share `.tsbuildinfo` with the tsgo graph and coexist safely. ## Related Issue(s) Implements Linear NXC-4539 (builds on NXC-4538 — all packages on nodenext). No GitHub issue to close. --------- Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
cleanup(testing): drop sub-default timeout overrides on release e2e s… …etup hooks (#36009) ## Current Behavior The `e2e/release` jest project sets a `120000` ms `testTimeout` (`e2e/release/jest.config.cts`), which Jest applies to any setup hook without an explicit timeout. Ten release suites instead hardcoded a `60000` ms timeout on their `newProject`-based `beforeEach`/`beforeAll` setup, half the suite default. Under CI load that setup (`newProject` plus `@nx/workspace:npm-package` generators plus git tagging) can run past 60s, so the hook times out and the suite fails intermittently. These surface as recurring high-risk flaky tasks on the Nx Cloud dashboard (version-plans, version-plans-check, version-plans-only-touched, conventional-commits-config, among others), and a CI run on this branch reproduced it in the `first-release` `beforeAll`, where `newProject` alone took 58s. ## Expected Behavior The setup hooks drop the explicit per-hook timeout and inherit the suite's `120000` ms default, giving the heavy setup enough headroom and removing the artificial sub-default cap. The `60000` values were copy-paste boilerplate carried in by each suite's introducing PR, not a deliberate limit, and this matches the common e2e idiom where setup hooks omit a per-hook timeout and rely on the file default. <!-- polygraph-session-start --> --- [View session information ↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-9deac4de) <!-- polygraph-session-end -->
feat(core): revert array-shape targetDefaults support pending redesig… …n and reapplication (#36005) ## Current Behavior `nx.json` `targetDefaults` accepts the new filtered **array shape** (entries matched by `target`/`executor` and narrowed by `projects`/`plugin`), alongside the legacy record shape. This was introduced and refined across: - #35340 — feat: support filtered array-shape targetDefaults with projects and source - #35711 — fix: do not drop target defaults in the 23.0.0 array migration - #35752 — docs: document the `convert-target-defaults-to-array` migration - #35991 — docs: rewrite the targetDefaults reference and guide for the array shape ## Expected Behavior This PR **reverts the array-shape `targetDefaults` feature pending a redesign**, with the intent that it be **reapplied** once the design is finalized. `targetDefaults` returns to the record-shape-only form (`Record<string, Partial<TargetConfiguration>>`). To keep reapplication easy, the revert is split into focused commits that mirror the original PRs — the feature can be brought back later by reverting these reverts. Changes: - Restore the `TargetDefaults` type; remove `TargetDefaultEntry`, `TargetDefaultsRecord`, and `NormalizedTargetDefaults` - Restore the core target-defaults matcher and project-configuration utils to the record-shape logic - Remove the `convert-target-defaults-to-array` migration (and its registration/docs) - Remove the devkit `upsertTargetDefault`/`findTargetDefault` helpers and the `normalize-target-defaults` utility; restore generators across all plugins (angular, cypress, react, jest, eslint, vite, etc.) to write the record shape - Restore the `nx.json` schema `targetDefaults` definition and revert the array-shape documentation Unrelated changes that landed in the same files after the feature are **preserved** (the `CreateNodesV2`→`CreateNodes` rename, the `findMatchingConfigFiles` optimization, the `nx migrate` config, `.gitignore` entries, migration-doc packaging globs, and the maven `createNodesV2` migration). ## Related Issue(s) Reverts #35340, #35711, #35752, #35991 (to be reapplied after redesign). --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
fix(core): do not fail local plugin lookup when workspace has no root… … tsconfig (#35969) ## Current Behavior In a workspace that has **no root `tsconfig.base.json` / `tsconfig.json`** — packages wired purely through package-manager workspaces and `package.json` `exports` — every workspace-local plugin listed in `nx.json` fails to load: ``` NX Failed to load 6 Nx plugin(s): - @scope/my-plugin: unable to find tsconfig.base.json or tsconfig.json ... ``` **This affects the latest stable release, not just the 23 RCs.** The source-first local plugin resolution was backported to the 22.x line in **`22.7.3`**. Verified against the published dists of every version in between: | nx version | symlinked local plugin, no root tsconfig | |---|---| | 22.7.1 | ✅ works | | 22.7.2 | ✅ works | | 22.7.3 | ❌ broken (backport of #35631 / #35751 lands) | | 22.7.4 | ❌ broken | | 22.7.5 (`latest`) | ❌ broken | | 23.0.0-rc.0 (`next`) | ❌ broken | | 22.7.5 + this fix | ✅ works | Since the source-first local plugin resolution (#35631, #35751), `resolveNxPlugin` runs `lookupLocalPlugin` for any plugin whose `require.resolve` lands inside the workspace (true for every symlinked workspace package). `findNxProjectForImportPath` then calls `readTsConfigPaths`, which **throws** when no root tsconfig exists — aborting the whole plugin load before the function ever reaches its tsconfig-independent fallbacks (package-metadata matching, then Node resolution of the built artifact). ### Minimal reproduction (5 files, released `nx@22.7.5`) ```jsonc // package.json { "name": "repro", "private": true, "devDependencies": { "nx": "22.7.5" } } ``` ```yaml # pnpm-workspace.yaml packages: - 'packages/*' ``` ```jsonc // nx.json { "plugins": ["@repro/my-plugin"] } ``` ```jsonc // packages/my-plugin/package.json { "name": "@repro/my-plugin", "exports": { ".": { "default": "./dist/index.js" } } } ``` ```js // packages/my-plugin/dist/index.js module.exports.createNodesV2 = ['**/never-matches.xyz', async () => []]; ``` `pnpm install && pnpm exec nx show projects` → ``` NX Failed to load 1 Nx plugin(s): - @repro/my-plugin: unable to find tsconfig.base.json or tsconfig.json ``` With this PR's change applied to `dist/src/project-graph/plugins/resolve-plugin.js` in the same install: exit 0, projects list as expected. ## Expected Behavior A missing root tsconfig just means the workspace has no tsconfig path mappings. `readTsConfigPaths` returns an empty mapping, `findNxProjectForImportPath` falls through to `getWorkspacePackagesMetadata` matching, and plugin resolution proceeds exactly as before the change (source via `exports` conditions when present, built dist otherwise). This matches the function's own tolerance for a tsconfig *without* `compilerOptions.paths` (`return tsconfigPaths ?? {}`). Given the 22.x backport, a backport of this fix to the 22.x line would also be appreciated. ## Related Issue(s) Fixes #35970 Standalone repro (5 files, released `nx@22.7.5`): https://github.com/agcty/nx-repro-local-plugin-no-root-tsconfig Regression introduced with the source-first local plugin resolution (#35631 / #35751), present in `23.0.0-rc.0` and backported into the stable line in `22.7.3` (22.7.2 and below unaffected). Originally encountered upgrading a bun-workspaces monorepo (six local inference plugins, per-package tsconfigs, no root tsconfig) from 22.7.1 to 23.0.0-rc.0 — all `nx` commands fail at plugin load. Additionally verified end-to-end: in the affected workspace, with this change applied, all 57 projects and all six local plugins load and tasks run; the new unit test fails with exactly the pre-fix error when the source change is reverted. --------- Co-authored-by: Jason Jean <jason@nrwl.io>
chore(gradle): bump gradle project graph plugin version to 0.1.22 (#3… …5973) ## Current Behavior Workspaces reference the `dev.nx.gradle.project-graph` Gradle plugin at version `0.1.21`. ## Expected Behavior Bump the plugin to `0.1.22`. This release carries the deterministic project-configuration-hash fix from #35972 (sorting `options.includeDependsOnTasks` so the `ProjectConfiguration` hash no longer drifts between JVM runs). The bump updates the version constant, the plugin's `build.gradle.kts`, and adds a migration (`change-plugin-version-0-1-22`, gated at `23.0.0-rc.2`) that updates existing workspaces' version catalogs and `build.gradle(.kts)` files on `nx migrate`. > Note: the published `0.1.22` plugin artifact must include #35972 before this is released. ## Related Issue(s) Follow-up to #35972 (the source fix).
fix(core): degrade cooldown-blocked dist-tags within their own channel ( #35967) ## Current Behavior When a package manager's minimum-release-age (cooldown) policy is active, `nx migrate` resolves dist-tags through per-package-manager emulation, and degrading a too-new tag produced inconsistent, often nonsensical results. `nx migrate next` could resolve to an internal `pr.*` preview build or a years-old release candidate; the npm path diverged from what npm itself installs; and yarn errored outright. Each of npm, pnpm, yarn, and bun carried its own tag-degrade implementation. ## Expected Behavior Dist-tag degrade is unified into a single rule across all four package managers. When the resolved tag target is within the cooldown window, the candidate pool is every version at or below it that is stable, in the target's own prerelease channel, or on a lower rung of an explicit channel ladder (`alpha < beta < rc`). That pool is ordered, and the first compliant version wins: - Prereleases of the target's exact `major.minor.patch` come first — own channel, then lower ladder rungs. - Then everything else, ordered by most recently published. So `latest` (or any stable tag) lands on the newest compliant stable. A prerelease tag keeps a compliant prerelease of the release it points at: every same-line release candidate is exhausted first, and a blocked `rc.0` with no older rc sibling falls to a same-line `beta.x` rather than skipping back to the previous stable. A newer-published cross-line backport can't outrank the same-line beta, and the degrade never climbs the ladder upward. Channels with no place on the ladder (such as the internal `pr` builds, or `canary`) stay walled off entirely. `next` is deliberately left off the ladder: it is pre-rc in some ecosystems (Angular) but a rolling dev snapshot in others — exactly the class of build a degrade must never land on. The channel is derived generically from a version's prerelease identifier, so it works for any package's naming convention. ## Implementation Details A shared `degradeTagToCompliant` helper replaces npm's `<=tagTarget` recursion, pnpm's same-major degrade (and its deprecation tie-break machinery), yarn's latest-only walk-down, and bun's channel walk. It builds the pool, orders it (same-line own-channel, then same-line lower-rung, then by publish date), and returns the first version that passes the caller's maturity test; each package manager supplies only that test and its own violation shape. The helper guards against non-semver dist-tag targets and registry version entries (`semver.compare` previously threw, and the migrate consumer swallows unknown errors into a real-install fallback). The cleanup also drops the now-dead `latestTagDegrade` behavior axis and the redundant pnpm 10.20 behavior row, along with the tests that pinned the old version-specific behavior. The npm policy-reader specs are isolated from the host's real `~/.npmrc` and reuse the real `.npmrc` parser (`parseNpmrcContent`) instead of a hand-copied mirror, and npm's tag-path ENOVERSIONS branch is now covered. <!-- polygraph-session-start --> --- [View session information ↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/fix-nx-migrate-min-release-99acf946) <!-- polygraph-session-end --> --------- Co-authored-by: FrozenPandaz <jasonjean1993@gmail.com>
fix(vite): improve vitest 4 migration to better handle vitest workspa… …ce config (#35940) ## Current Behavior The `migrate-to-vitest-4` migration defers `vitest.workspace.*` handling entirely to the AI step, which inlines the project globs verbatim into a root `vitest.config.*` under `test.projects`. After the upgrade, packages that run tests through a package.json `vitest` script without a local config fail with "No projects were found": Vitest 4 discovers the new root config by walking up from the package directory and resolves the `test.projects` globs relative to that directory. Workspaces migrated without the AI step get no workspace-file handling at all. Reported while testing the Nx 23 betas; reproduction: https://github.com/juristr/nx23-vitest-issue-repro. ## Expected Behavior The migration handles workspace files deterministically and produces a working setup on its own: - Static `vitest.workspace.*` files (the Nx-generated shape) are inlined into the root `vitest.config.*` under `test.projects` and deleted. Only dynamic shapes are forwarded to the AI step. - Packages that run vitest via a package.json script and have no local config get a minimal `vitest.config.*` generated, so their tests keep running from the package directory and `@nx/vitest` infers their test target. - When the inlined globs match both a `vite.config.*` and a `vitest.config.*` in the same directory resolving to the same project name, the `vite.config.*` file is excluded with a negative glob. This matches vitest's own vitest-over-vite preference and avoids the "Project name ... is not unique" startup error that the copied globs previously produced on root-level runs. Cases that can't be determined statically are forwarded to the AI step as advisories. Anything the migration cannot do safely (dynamic workspace files, configs it can't merge into) is still deferred to the AI step with accurate context, and the instructions teach the agent the same rules for the files it inlines itself. <!-- polygraph-session-start --> --- [View session information ↗](https://snapshot.app.trypolygraph.com/orgs/69cdc268b6aa527e4129c2b4/sessions/troubleshoot-migrate-to-vitest-4-issue-ba08225a) <!-- polygraph-session-end --> --------- Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
chore(repo): finish migrating builds off the workspace-root dist (#35915 ) ## Current Behavior Following the local-dist migration (#35900), several projects were still writing build or typecheck output to the shared workspace-root `dist/`: - **Five packages' spec configs** — `@nx/angular-rspack`, `@nx/angular-rspack-compiler`, `@nx/dotnet`, `@nx/maven`, and `nx` — kept their `tsconfig.spec.json` `outDir` pointing at `dist/packages/<name>/spec` even though their lib output had been migrated to a local `dist`. - **`tools/workspace-plugin`** built to the shared `dist/workspace-plugin` (its conformance rules are loaded from the built output). - **The graph client** bundled to `dist/apps/graph` and emitted its typecheck declarations to `dist/graph/client`; the graph libs wrote spec/storybook typecheck output under `dist/out-tsc`. - **nx-dev** lib/spec tsconfigs pointed their `outDir` at `dist/out-tsc/...`. Separately, astro-docs documentation generation resolved each plugin's `schema.json` from its **built** `dist` (the migrated `generators.json`/`executors.json` refs point at `./dist/src/...`). Reading another project's build output tripped the task sandbox with undeclared `dist/**/schema.json` reads. ## Expected Behavior Each project builds to its own local directory, leaving the workspace-root `dist/` alone: - The five spec configs now emit to local `dist/spec`. - `tools/workspace-plugin` builds to `tools/workspace-plugin/dist`; the seven conformance rule paths in `nx.json` are updated, and `main`/`typings` are repointed into `dist` so the `@nx/js/typescript` plugin still infers its build target. - The graph client bundles to `graph/client/dist` (the `nx` package's `assets.json` input is updated to match); its typecheck output goes to a local `out-tsc` so the emitted declarations stay out of the copied bundle dir. Graph lib spec/storybook output moves to local `dist`. - nx-dev lib/spec outputs move to local `dist` / `dist/spec` (preventative — these were vestigial as no target runs `tsc` on most nx-dev libs today). astro-docs now reads plugin `schema.json` from source (the verbatim copy), which also matches `astro-docs:build`'s already-declared `packages/*/src/.../schema.json` inputs — removing the sandbox violation without weakening cache correctness. Validation: `nx build workspace-plugin` + `nx conformance` pass from the new path; the graph client builds and copies into `packages/nx/dist/src/core/graph` with no declaration leakage; `nx build astro-docs` is green (753 pages, no schema-resolution errors); affected graph and nx-dev `typecheck`/`lint`/`test` pass. ## Related Issue(s) Follow-up to #35900 (local-dist build migration). No separate issue. --------- Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
fix(repo): use import type for type-only @nx/devkit imports in copy-a… ( #35897) …ssets plugin CreateNodesV2 and TargetConfiguration are types but were imported as values. The @nx/workspace-plugin package is type: module, so under Node's native TypeScript stripping (Node >= 22.18) those names are left as runtime imports. @nx/devkit is CommonJS with no such runtime exports, so the plugin fails to load -- surfacing on the FreeBSD publish job as the misleading "imported again after being required. Status = 0" Node error. Marking them import type lets native strip erase them so the plugin loads on any Node. <!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
docs(module-federation): add Vite Module Federation example page Add a dedicated docs page under Technologies > Module Federation covering a Vite-based federation setup using @module-federation/vite, with Nx orchestrating host/remote tasks. Links the example workspace maintained by Giorgio Boa. Part of DOC-514.
PreviousNext