Skip to content

fix(common): add resolveJsonModule to ts-node compilerOptions (fixes #816)#2189

Open
just-jeb wants to merge 4 commits into
masterfrom
fix/816-resolve-json-module
Open

fix(common): add resolveJsonModule to ts-node compilerOptions (fixes #816)#2189
just-jeb wants to merge 4 commits into
masterfrom
fix/816-resolve-json-module

Conversation

@just-jeb
Copy link
Copy Markdown
Owner

@just-jeb just-jeb commented Apr 26, 2026

PR Checklist

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

[x] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] Other... Please describe:

What is the current behavior?

Importing .json files in TypeScript webpack configs (e.g. import * as pkg from './package.json') fails with TS2732 even when the user's tsconfig has resolveJsonModule: true, because ts-node's explicit compilerOptions override in load-module.ts does not include resolveJsonModule, which resets it to the default false.

Issue Number: #816

What is the new behavior?

resolveJsonModule: true is added to the explicit compilerOptions passed to ts-node.register(), so JSON imports work in TypeScript webpack config files.

New integration test: custom-webpack: TS config with JSON import.

Does this PR introduce a breaking change?

[ ] Yes
[x] No

resolveJsonModule is a permissive flag — it enables a behavior that was previously rejected. No existing valid config can be broken by this change.

Other information

Note: This PR modifies load-module.ts which is also rewritten by PR #1659. If #1659 merges first, this fix needs to be applied to register-ts-project.ts instead.

@just-jeb
Copy link
Copy Markdown
Owner Author

Thanks for the PR!

After discussion, we have decided not to add resolveJsonModule: true at the builder level for now. The reasoning:

  • resolveJsonModule is a TypeScript compiler option that belongs in the user tsconfig.json. The builder already passes the user tsconfig to ts-node via the project option, so users can opt in by adding it there.
  • Silently injecting it could surprise users who have explicitly set it to false, or cause subtle behavioral differences.
  • If we decide to make it a default in the future, that would be a breaking change appropriate for a major version bump.

The workaround is straightforward: add resolveJsonModule: true to the tsconfig that your webpack config uses. We will update the docs to make this clearer.

Appreciate the contribution!

@just-jeb just-jeb closed this Apr 26, 2026
@just-jeb
Copy link
Copy Markdown
Owner Author

Correction to my previous comment: looking more carefully at the issue history, the reporter confirmed that adding resolveJsonModule to the user tsconfig does NOT fully solve it (it still fails for the karma builder). So the user-side workaround is incomplete.

The actual validated workarounds are:

  • Use require() instead of import for JSON files in webpack configs
  • Or fix it at the builder level by passing resolveJsonModule: true to ts-node

We are reconsidering the approach. Fixing it at the builder level is valid but would be a deliberate decision for a major version. Apologies for the premature close — we will reopen and track this properly.

@just-jeb just-jeb reopened this Apr 26, 2026
@just-jeb
Copy link
Copy Markdown
Owner Author

Updated analysis after reading the code:

The root cause is that _tsNodeRegister passes an explicit compilerOptions object to ts-node, which replaces rather than merges with the user's tsconfig compilerOptions. This means a user cannot work around the issue by adding resolveJsonModule: true to their own tsconfig — the builder overrides it regardless. The only user-side workaround is require() instead of import.

There are two possible approaches to fix this properly:

  1. Add resolveJsonModule: true to the explicit override — what this PR does. Simple, but opinionated.
  2. Read the user's tsconfig compilerOptions and merge them into the override — more principled, respects any option the user has set.

Both approaches could be a breaking change for setups that rely on the current minimal override behavior. We are deferring this to the next major version. Keeping this PR open as a reference implementation for when that time comes.

@just-jeb just-jeb force-pushed the fix/816-resolve-json-module branch from 96f1f05 to b0bafff Compare April 26, 2026 14:58
@just-jeb just-jeb added bug Something isn't working builders:common labels May 11, 2026
@just-jeb just-jeb force-pushed the fix/816-resolve-json-module branch 7 times, most recently from 8cab3b2 to 85ba473 Compare May 15, 2026 04:30
@just-jeb
Copy link
Copy Markdown
Owner Author

Option 1 seems fine.

@just-jeb just-jeb force-pushed the fix/816-resolve-json-module branch 2 times, most recently from 273d7c2 to 44f1069 Compare May 16, 2026 16:30
just-jeb and others added 3 commits May 18, 2026 11:38
…816)

When a TypeScript webpack config imports a JSON file (e.g. `import * as pkg from './package.json'`),
ts-node throws TS2732 ('Cannot find module') if the project tsconfig uses moduleResolution:'node'
and does not set resolveJsonModule:true.

The root cause: the builder's ts-node registration overrides `module: 'CommonJS'` but never
sets `resolveJsonModule`. With moduleResolution:'node' (the Angular default before v17),
TypeScript requires an explicit `resolveJsonModule: true` to allow JSON imports.

Fix: add `resolveJsonModule: true` to the compilerOptions override in `_tsNodeRegister()`.
This is safe to always enable — it has no downside and works with all moduleResolution modes
(node, node16, bundler, etc.).

Reproduction: tsconfig with moduleResolution:node + TS webpack config importing package.json -> TS2732
Fix verifier: same config with resolveJsonModule injected by ts-node -> build succeeds

Integration test added: ts-config-json-module-import
… test

moduleResolution:node cannot resolve Angular 21 subpath exports, making
the ts-config-json-import configuration fundamentally broken.
@just-jeb just-jeb force-pushed the fix/816-resolve-json-module branch from 44f1069 to 27688d8 Compare May 18, 2026 10:02
…st for JSON import

- Add examples/custom-webpack/sanity-app/extra-webpack.config.ts that imports
  package.json (uses `import { name } from './package.json'`). sanity-app's
  tsconfig does not set resolveJsonModule, so this requires the fix in #816 to
  work: ts-node must be registered with resolveJsonModule:true.
- Add 'ts-json-import' build configuration to sanity-app/angular.json wiring
  in the new config.
- Add 'ts-config-json-import' integration test entry to integration.js.
- Remove the ts-node options toHaveBeenCalledWith assertion from
  transform-factories.spec.ts (it checked implementation detail, not behavior).
  Keep the warning-on-duplicate-tsconfig assertion which tests real behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working builders:common

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant