feat(devkit): batch tmp installs in ensurePackage#35305
feat(devkit): batch tmp installs in ensurePackage#35305AgentEnder wants to merge 3 commits intomasterfrom
Conversation
Add an `ensurePackage(Record<string, string>)` overload that resolves every missing package in a single tmp project instead of provisioning a fresh one per call. Exposes `installPackagesToTmp` / `installPackagesToTmpAsync` from `nx` core for feature-detection, with a graceful fallback to sequential single-package installs on older cores. Refactor generators that sequentially install distinct Nx plugins in the same run (js/library, react/application, react/library, remix/application, web/application, vue/library add-vite, vue/application add-e2e, react/application add-e2e, react/application add-vite/setupVitest, expo/application add-e2e, next/cypress-component-configuration, nuxt/application add-vitest) to collect their plugin set up front and ensure it once.
❌ Deploy Preview for nx-dev failed. Why did it fail? →
|
❌ Deploy Preview for nx-docs failed. Why did it fail? →
|
|
View your CI Pipeline Execution ↗ for commit dfa7015
☁️ Nx Cloud last updated this comment at |
Co-authored-by: AgentEnder <AgentEnder@users.noreply.github.com>
There was a problem hiding this comment.
Nx Cloud is proposing a fix for your failed CI:
We added @nx/jest and @nx/vite to the ignoredDependencies list in packages/js/.eslintrc.json to fix the js:lint failure. The PR's typed require('@nx/vite') as typeof import('@nx/vite') and require('@nx/jest') as typeof import('@nx/jest') calls introduce static type-level references that the Nx project graph picks up as dependencies, causing @nx/dependency-checks to report them as missing from package.json — unlike the untyped require('@nx/rollup') calls which go undetected. These packages are optional runtime plugins installed separately by users, making ignoredDependencies the correct resolution.
Tip
✅ We verified this fix by re-running js:lint.
Suggested Fix changes
diff --git a/packages/js/.eslintrc.json b/packages/js/.eslintrc.json
index e04b58643c..930d50bfc7 100644
--- a/packages/js/.eslintrc.json
+++ b/packages/js/.eslintrc.json
@@ -70,7 +70,10 @@
"@swc/cli",
"babel-plugin-const-enum",
"babel-plugin-macros",
- "babel-plugin-transform-typescript-metadata"
+ "babel-plugin-transform-typescript-metadata",
+ // Optional runtime plugins – installed by the user separately
+ "@nx/jest",
+ "@nx/vite"
]
}
]
diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts
index 287acefd66..ed44ce93d6 100644
--- a/packages/js/src/generators/library/library.ts
+++ b/packages/js/src/generators/library/library.ts
@@ -155,8 +155,8 @@ export async function libraryGeneratorInternal(
}
if (options.bundler === 'vite') {
- // nx-ignore-next-line
const { viteConfigurationGenerator, createOrEditViteConfig } =
+ // nx-ignore-next-line
require('@nx/vite') as typeof import('@nx/vite');
const viteTask = await viteConfigurationGenerator(tree, {
project: options.name,
@@ -741,8 +741,8 @@ async function addJest(
tree: Tree,
options: NormalizedLibraryGeneratorOptions
): Promise<GeneratorCallback> {
- // nx-ignore-next-line
const { configurationGenerator } =
+ // nx-ignore-next-line
require('@nx/jest') as typeof import('@nx/jest');
return await configurationGenerator(tree, {
...options,
🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.
Or Apply changes locally with:
npx nx-cloud apply-locally z8mH-Asol
Apply fix locally with your editor ↗ View interactive diff ↗
🎓 Learn more about Self-Healing CI on nx.dev
Current Behavior
ensurePackageonly accepts a single package at a time and provisions a fresh temporary project per call. Generators that need multiple Nx plugins in one run (e.g.@nx/js:librarywith a bundler + linter + test runner, or@nx/react:applicationwith a bundler + e2e runner) sequentially spin up N throwaway tmp projects — each one runs the package-manager preinstall, resolves its own lockfile, and fetches from the registry.Expected Behavior
ensurePackageaccepts a batch form:It filters out packages already resolvable via
require(pkg), then installs everything missing into a single tmp project via a newinstallPackagesToTmpinternal. Subsequent single-packageensurePackage/requirecalls hit the cache warmed by the batch call. When running against an oldernxcore that predatesinstallPackagesToTmp, the batch form degrades gracefully to sequential single-package installs.Generators that sequentially install distinct plugins in one run now derive their plugin set up front and call
ensurePackageonce:@nx/js:library@nx/react:application,@nx/react:library,@nx/reactadd-e2e / add-vite setupVitest@nx/remix:application@nx/web:application@nx/vue:libraryadd-vite,@nx/vue:applicationadd-e2e@nx/expo:applicationadd-e2e@nx/next:cypress-component-configuration@nx/nuxt:applicationadd-vitestFiles whose
ensurePackagecalls are mutually exclusive (e.g.switchon bundler or e2e runner) were intentionally left alone — only one install happens at runtime regardless.Related Issue(s)
N/A