Skip to content

chore: use tsx for Nx commands to execute local plugins same as other projects#1241

Closed
BioPhoton wants to merge 16 commits intomainfrom
chore/use-tsx-to-execute-nx
Closed

chore: use tsx for Nx commands to execute local plugins same as other projects#1241
BioPhoton wants to merge 16 commits intomainfrom
chore/use-tsx-to-execute-nx

Conversation

@BioPhoton
Copy link
Collaborator

@BioPhoton BioPhoton commented Feb 8, 2026

Problem
This repository uses local Nx plugins and async generators written in TypeScript that need to:

  • Import files with .js extensions (ES modules convention)
  • Resolve TypeScript path aliases (e.g., @code-pushup/models)

Without proper TypeScript execution setup, Nx commands fail when trying to execute these local plugins/generators.

Solution
Explicit environment variable configuration for both local development and CI:

  • Local Development - Use .env.local (gitignored)
  • Developers copy .env.local.example to .env.local
  • Nx automatically loads .env.local files
  • CI - Set environment variables explicitly at workflow level
    • NODE_OPTIONS=--import tsx - Enables TypeScript execution
    • TSX_TSCONFIG_PATH=tsconfig.base.json - Resolves path aliases

Background

Why SWC is skipped when running Nx with NODE_OPTIONS="--import tsx"

Nx has hardcoded transpiler-selection logic for local TS/TSX execution (plugins, executors, generators).
When running with a Node loader like tsx, Nx does not register SWC, even if SWC is available.

Relevant source:
https://github.com/nrwl/nx/blob/81c157d0631927b3d1891453aa45652f3b5a7988/packages/nx/src/plugins/js/utils/register.ts

Key logic:

export function registerTranspiler(
  compilerOptions: CompilerOptions,
  tsConfigRaw?: unknown
): () => void {
  const transpiler = getTranspiler(compilerOptions, tsConfigRaw);

  if (!transpiler) {
    warnNoTranspiler();
    return () => {};
  }

  return transpiler();
}

If getTranspiler(...) returns undefined, Nx intentionally does not register SWC or ts-node.

getTranspiler(...) only detects:

  • @swc-node/register
  • ts-node

Node loaders like tsx are not detected, so:

  • getTranspiler(...) === undefined
  • registerTranspiler becomes a no-op
  • SWC is effectively disabled by design for this execution path

This is not in @nx/js:swc, but in Nx’s runtime TS/TSX plugin execution pipeline.
Running with NODE_OPTIONS="--import tsx" therefore bypasses SWC via hardcoded logic.

Related:

@github-actions github-actions bot added 📖 Project documentation improvements or additions to the project documentation 🦾 CI/CD Continuous integration and deployment labels Feb 8, 2026
@nx-cloud
Copy link

nx-cloud bot commented Feb 8, 2026

View your CI Pipeline Execution ↗ for commit 3571d73

Command Status Duration Result
nx run ci:code-pushup -- merge-diffs --files=/h... ✅ Succeeded 5s View ↗
nx run-many --targets=code-pushup --parallel=fa... ✅ Succeeded 1m 30s View ↗
nx run-many --targets=code-pushup --parallel=fa... ✅ Succeeded 13m View ↗
nx run-many -t unit-test,int-test ✅ Succeeded 3s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-08 15:41:22 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 8, 2026

Open in StackBlitz

@code-pushup/ci

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/ci@1241

@code-pushup/cli

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/cli@1241

@code-pushup/core

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/core@1241

@code-pushup/create-cli

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/create-cli@1241

@code-pushup/models

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/models@1241

@code-pushup/axe-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/axe-plugin@1241

@code-pushup/nx-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/nx-plugin@1241

@code-pushup/coverage-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/coverage-plugin@1241

@code-pushup/eslint-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/eslint-plugin@1241

@code-pushup/js-packages-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/js-packages-plugin@1241

@code-pushup/jsdocs-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/jsdocs-plugin@1241

@code-pushup/lighthouse-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/lighthouse-plugin@1241

@code-pushup/typescript-plugin

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/typescript-plugin@1241

@code-pushup/utils

npm i https://pkg.pr.new/code-pushup/cli/@code-pushup/utils@1241

commit: 3571d73

@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2026

Code PushUp

🤨 Code PushUp report has both improvements and regressions – compared current commit 9f23abb with previous commit 3dbf378.

🕵️ See full comparison in Code PushUp portal 🔍

🏷️ Categories

🏷️ Category ⭐ Previous score ⭐ Current score 🔄 Score change
Updates 🟡 78 🟡 75 ↓ −3
Performance 🔴 37 🔴 35 ↓ −2
Bug prevention 🟡 75 🟡 75 ↓ −0.1
Axe Accessibility 🟡 88 🟡 88 ↓ −0.1
Code style 🟢 100 🟢 100
Code coverage 🟢 93 🟢 93
Security 🔴 47 🔴 47
Type Safety 🟡 67 🟡 67
Miscellaneous 🟡 67 🟡 67
Documentation 🟡 53 🟡 53
Accessibility 🟢 92 🟢 92
Best Practices 🟢 100 🟢 100
SEO 🟢 92 🟢 92
👎 2 groups regressed, 👍 4 audits improved, 👎 3 audits regressed, 12 audits changed without impacting score

🗃️ Groups

🔌 Plugin 🗃️ Group ⭐ Previous score ⭐ Current score 🔄 Score change
JS packages npm outdated dependencies 🟡 78 🟡 75 ↓ −3
Lighthouse Performance 🔴 37 🔴 35 ↓ −2

32 other groups are unchanged.

🛡️ Audits

🔌 Plugin 🛡️ Audit 📏 Previous value 📏 Current value 🔄 Value change
Lighthouse Minify CSS 🟨 Potential savings of 10 KiB 🟩 0  −∞ %
Lighthouse Total Blocking Time 🟥 1,310 ms 🟥 1,980 ms ↑ +51.6 %
Lighthouse First Contentful Paint 🟥 3.5 s 🟥 3.3 s ↓ −6.5 %
Lighthouse Speed Index 🟥 7.3 s 🟥 7.0 s ↓ −4.2 %
JS packages Outdated npm prod dependencies. 🟨 20 outdated package versions (5 major, 11 minor, 4 patch) 🟨 20 outdated package versions (6 major, 10 minor, 4 patch)  +0 %
Lighthouse Time to Interactive 🟥 13.4 s 🟥 13.8 s ↑ +2.8 %
JS packages Outdated npm dev dependencies. 🟨 62 outdated package versions (29 major, 25 minor, 8 patch) 🟨 62 outdated package versions (29 major, 25 minor, 8 patch)  +0 %
Lighthouse Avoids enormous network payloads 🟩 Total size was 2,119 KiB 🟩 Total size was 2,098 KiB ↓ −1 %
Lighthouse JavaScript execution time 🟥 3.2 s 🟥 4.0 s ↑ +24.2 %
Lighthouse Minimizes main-thread work 🟥 10.2 s 🟥 10.7 s ↑ +5.4 %
Lighthouse Metrics 🟩 100% 🟩 100% ↑ +2.8 %
Lighthouse Uses efficient cache policy on static assets 🟨 31 resources found 🟨 31 resources found ↓ −0.1 %
Lighthouse Server Backend Latencies 🟩 1,220 ms 🟩 1,060 ms ↓ −13.3 %
Lighthouse Remove duplicate modules in JavaScript bundles 🟥 Potential savings of 91 KiB 🟥 Potential savings of 81 KiB ↓ −33.3 %
Lighthouse Max Potential First Input Delay 🟥 1,080 ms 🟥 1,190 ms ↑ +10.2 %
Lighthouse Initial server response time was short 🟩 Root document took 560 ms 🟩 Root document took 470 ms ↓ −15.6 %
Lighthouse Largest Contentful Paint 🟥 12.3 s 🟥 12.4 s ↑ +0.3 %
Lighthouse Network Round Trip Times 🟩 70 ms 🟩 70 ms ↑ +10 %
JS packages Vulnerabilities for npm dev dependencies. 🟥 47 vulnerabilities (3 critical, 9 high, 32 moderate, 3 low) 🟥 48 vulnerabilities (3 critical, 9 high, 32 moderate, 4 low) ↑ +2.1 %

660 other audits are unchanged.

BioPhoton and others added 3 commits February 8, 2026 14:41
The Code PushUp composite action uses npx tsx explicitly, so NODE_OPTIONS
at job level causes "Post job cleanup" errors when tsx is no longer available.

The runner script sets NODE_OPTIONS programmatically when needed.

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove extra blank lines to pass prettier checks

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2026

Code PushUp

🥳 Code PushUp report has improved – compared current commit 9f23abb with previous commit 3dbf378.

💼 Project utils

🥳 Code PushUp report has improved.

🕵️ See full comparison in Code PushUp portal 🔍

🏷️ Category ⭐ Previous score ⭐ Current score 🔄 Score change
Code coverage 🟢 95 🟢 95 ↑ +0.1
Documentation 🟡 61 🟡 61 ↑ +0.1

4 other categories are unchanged.

👍 2 groups improved, 👍 1 audit improved

🗃️ Groups

🔌 Plugin 🗃️ Group ⭐ Previous score ⭐ Current score 🔄 Score change
Code coverage Code coverage metrics 🟢 95 🟢 95 ↑ +0.1
JSDocs coverage Documentation coverage 🟡 61 🟡 61 ↑ +0.1

13 other groups are unchanged.

🛡️ Audits

🔌 Plugin 🛡️ Audit 📏 Previous value 📏 Current value 🔄 Value change
Code coverage Branch coverage 🟩 91.9 % 🟩 91.9 % ↑ +0.1 %

443 other audits are unchanged.


13 other projects are unchanged.

BioPhoton and others added 6 commits February 8, 2026 15:08
E2E tests create temporary directories (e.g. tmp/e2e/plugin-eslint-e2e/)
and tsx was trying to resolve the relative path from the current working
directory instead of the workspace root, causing:

Error: Cannot resolve tsconfig at path:
/home/runner/work/cli/cli/tmp/e2e/plugin-eslint-e2e/tsconfig.base.json

Solution: Use absolute path ${{ github.workspace }}/tsconfig.base.json
in all workflow steps that set TSX_TSCONFIG_PATH.

Local .env.local can still use relative path since development happens
from the workspace root.

Co-authored-by: Cursor <cursoragent@cursor.com>
@BioPhoton BioPhoton closed this Feb 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🦾 CI/CD Continuous integration and deployment 📖 Project documentation improvements or additions to the project documentation 🛠️ tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant