[No QA] Upgrade Node to 26.5.0 and npm to 11.17.0#96205
Conversation
|
@carlosmiceli Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Codecov Report✅ All modified and coverable lines are covered by tests. |
| env: | ||
| # See the runs-on comment: each worker needs ~12GB of heap on a cold cache, so run | ||
| # 2 workers with a 14GB cap instead of ESLint's defaults (4 workers, 8GB cap). | ||
| ESLINT_CONCURRENCY: 2 | ||
| NODE_OPTIONS: --max_old_space_size=14336 |
There was a problem hiding this comment.
This might be a temporal fix as right now ESLint's result cache hashes ${eslintVersion}_${nodeVersion}_${config} (node_modules/eslint/lib/cli-engine/lint-result-cache.js:50);, so the migration Node 20 → node 26 invalidates every cache entry forcing a lint of the entire repo, verified empirically: warm cache re-lint 5s on same Node, 62s (full) when Node 26 reads Node 20's cache.
We might be able to reverse this part when we start to cache under the new nodeVersion
Node 26 applies the nearest package.json "type" to extensionless files, so requiring the extensionless yargs/yargs file (package has type: module) now fails in ESM scope. The patch points the ./yargs subpath require condition at a .cjs copy.
This reverts commit b639c1a.
HybridApp builds couple App and Mobile-Expensify: App CI builds from the Mobile-Expensify submodule and Mobile-Expensify CI installs App from main, so exact engine pins on either side cannot merge in any order. Both repos accept both versions until the upgrade lands everywhere, then a follow-up tightens the pins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ESLint's result cache hashes the Node version, so the Node 26 upgrade invalidates every cache entry and forces a full-repo relint. On a 4vcpu runner --concurrency=auto spawns only 2 workers, and half the repo of type-aware linting exceeds each worker's 8GB heap cap, failing with ERR_WORKER_OUT_OF_MEMORY. With 4 workers the full lint peaks around 25GB total, which fits on the 8vcpu (32GB) runner. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ESLint's result cache hashes the Node version, so the Node 26 upgrade invalidates every cache entry and forces a full-repo relint. Type-aware linting loads the full TypeScript program in every worker (~12GB of heap each, regardless of how files are split), so any worker count dies at the default 8GB cap. Two workers with a 14GB cap complete a cold-cache lint in ~6 minutes and fit within the 8vcpu runner's 32GB of memory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Node 26 loads the rsbuild TS config as native ESM, where CommonJS globals like __dirname don't exist, so the dev server crashed with 'ReferenceError: __dirname is not defined' when resolving the dist directory. Resolve it from compiler.outputPath instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
83f1031 to
f234a2f
Compare
Explanation of Change
Upgrades Node from 20.20.2 to 26.5.0 and npm from 10.8.2 to 11.17.0 (the npm version bundled with Node 26.5.0, so
nvm usegives the right npm with no extra steps), as part of a coordinated Node 26 upgrade across all Expensify repos.Changes:
.nvmrcandpackage.jsonengines bumped to Node 26.5.0 / npm 11.17.0.package-lock.jsonregenerated with npm 11. The previous lock was missing the@img/sharp-*platform-specific optional dependency entries, which npm 11's stricternpm cisync validation rejects; regenerating restores them.No runtime code changes — build/tooling only.
Fixed Issues
Proposal: https://expensify.slack.com/archives/C03TQ48KC/p1784011015927039
MOBILE-EXPENSIFY: https://github.com/Expensify/Mobile-Expensify/pull/14015
Tests
nvm install 26.5.0 && nvm use 26.5.0.npm ciand verify it completes without errors.npm run typecheck-tsgoand verify it passes.npx jest tests/unitand verify results matchmain(20 pre-existing date-related failures occur identically on Node 20.20.2 and are unrelated to this change).Offline tests
None — tooling-only change with no runtime behavior.
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
No UI change — tooling only.
Android: mWeb Chrome
No UI change — tooling only.
iOS: Native
No UI change — tooling only.
iOS: mWeb Safari
No UI change — tooling only.
MacOS: Chrome / Safari
No UI change — tooling only.