Skip to content

fix(plugin-core): declare minimum Node.js version in engines - #328

Closed
jingjing2222 wants to merge 1 commit into
mainfrom
fix/declare-node-engines
Closed

fix(plugin-core): declare minimum Node.js version in engines#328
jingjing2222 wants to merge 1 commit into
mainfrom
fix/declare-node-engines

Conversation

@jingjing2222

@jingjing2222 jingjing2222 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

Declares the minimum required Node.js version (>=22.15.0) in the engines field of @granite-js/plugin-core.

Problem

image

Running granite dev (or build) on Node.js < 22.15.0 in a Yarn PnP project crashes at startup with a hard-to-diagnose error:

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'pathe' imported from /.../.yarn/__virtual__/c12-virtual-.../node_modules/c12/dist/index.mjs
Did you mean to import "pathe/dist/index.cjs"?
    at loadESMFromCJS (node:internal/modules/cjs/loader:1385:24)

Nothing warns about the Node.js version at install time, so users only hit this at runtime.

Cause

  • @granite-js/plugin-core's CJS bundle (dist/index.cjs) calls require('c12'), and c12 v3 is an ESM-only package, so this goes through Node's require(esm) path.
  • Yarn PnP registers its ESM resolution support as async customization hooks (--experimental-loader .pnp.loader.mjs).
  • On Node.js <= 22.14, the require(esm) module graph is resolved with #cachedDefaultResolve, which bypasses registered customization hooks entirely. c12's own import 'pathe' is then resolved against the real filesystem (inside a zip, with no node_modules) and fails.
  • Node.js 22.15.0 changed this path to #cachedResolveSync, which routes require(esm) resolution through the registered hooks (implement module.registerHooks() to run synchronous module customization hooks in thread nodejs/node#55698), making it work under Yarn PnP.

Verified by bisecting: 22.12.0 / 22.13.0 / 22.14.0 all reproduce the exact error above, and 22.15.0 / 22.15.1 / 22.17.1 / 22.18.0 all work (granite build completes and granite dev starts normally on 22.15.0).

Note: this floor comes from the ESM-only dependency + require(esm) + Yarn PnP combination. It is unrelated to Node 22.18's type stripping — granite.config.ts is loaded via jiti.

Effect

This declares the requirement in a machine-readable way. Verified behavior per package manager when installing on Node.js 22.14.0:

  • npm: prints EBADENGINE warnings at install time (covers transitive dependencies too); hard-fails with engine-strict=true
  • pnpm: fails the install with ERR_PNPM_UNSUPPORTED_ENGINE when engine-strict=true is set (silent by default)
  • Yarn Berry: does not enforce engines (neither the project's own nor dependencies'), so PnP users are not protected at install time — for them the field serves as documentation, and is picked up by deployment platforms, Renovate, and the yarn-plugin-engines plugin

Since Yarn PnP users (where the failure actually occurs) get no install-time protection, a runtime Node.js version check in the CLI with a friendly error message would be a good follow-up.

@changeset-bot

changeset-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ecd97e3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 28 packages
Name Type
@granite-js/plugin-core Patch
@granite-js/cli Patch
@granite-js/mpack Patch
@granite-js/plugin-env Patch
@granite-js/plugin-hermes Patch
@granite-js/plugin-micro-frontend Patch
@granite-js/plugin-router Patch
@granite-js/plugin-rozenite Patch
@granite-js/plugin-sentry Patch
@granite-js/react-native Patch
@granite-js/forge-cli Patch
babel-preset-granite Patch
create-granite-app Patch
@granite-js/blur-view Patch
@granite-js/brownfield-module Patch
@granite-js/cookies Patch
@granite-js/screen Patch
@granite-js/image Patch
@granite-js/jest Patch
@granite-js/lottie Patch
@granite-js/native Patch
@granite-js/naver-map Patch
@granite-js/style-utils Patch
@granite-js/utils Patch
@granite-js/video Patch
@granite-js/vitest Patch
@granite-js/deployment-manager Patch
@granite-js/pulumi-aws Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
granite-docs Ready Ready Preview, Comment Jul 10, 2026 8:47am

Request Review

l2hyunwoo
l2hyunwoo previously approved these changes Jul 10, 2026

@l2hyunwoo l2hyunwoo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

@jingjing2222 jingjing2222 self-assigned this Jul 10, 2026
@jingjing2222
jingjing2222 force-pushed the fix/declare-node-engines branch from ecd97e3 to d0c3691 Compare July 10, 2026 08:47
@jingjing2222
jingjing2222 marked this pull request as draft July 10, 2026 08:48
@jingjing2222
jingjing2222 marked this pull request as ready for review July 10, 2026 08:49
@jingjing2222
jingjing2222 requested a review from l2hyunwoo July 10, 2026 08:50
@jingjing2222

jingjing2222 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

tsdown makes itself dying

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants