Skip to content

refactor(resolve)!: replaces tsconfig-paths-webpack-plugin with enhanced-resolve's own tsconfig-paths feature SLIGHTLY BREAKING#1061

Merged
sverweij merged 8 commits into
mainfrom
refactor/replace-ts-config-paths-webpack-plugin-with-ehrs-own-implementation
May 30, 2026
Merged

refactor(resolve)!: replaces tsconfig-paths-webpack-plugin with enhanced-resolve's own tsconfig-paths feature SLIGHTLY BREAKING#1061
sverweij merged 8 commits into
mainfrom
refactor/replace-ts-config-paths-webpack-plugin-with-ehrs-own-implementation

Conversation

@sverweij

@sverweij sverweij commented May 30, 2026

Copy link
Copy Markdown
Owner

Description

  • replaces tsconfig-paths-webpack-plugin with enhanced-resolve's own tsconfig-paths feature

It seems that in one edge-case enhanced-resolve reacts differently. References to config-paths defined as below (with no * on the LHS, but with a * on the RHS don't resolve, where they did in tsconfig-paths-webpack-plugin.
TBD:

  • is this pattern 'allowed'/ supported by the official typescript implementation?
    -> as it turns out it is not rejected, but it doesn't do anything either. It
    is / was something specific in the tsconfig-paths package.
  • if so, maybe make a PR at enhanced-resolve. If not, maybe plonk in a workaround locally - or put it in the list of 'breaking changes' (we're major-bumping anyway).
    -> breaking change it is.
// ...
    "paths": {
      "@sister": ["./libs/zus/*"]
    },
// ...

Motivation and Context

  • With enhanced-resolve's 'native' support for tsconfig-paths it's not necessary anymore to use a separate plugin for it.
  • tsconfig-paths-webpack-plugin currently seems to be nominally maintained anymore
  • as a bonus we loose 1 direct and 9 indirect dependencies we don't have to worry about anymore.

How Has This Been Tested?

  • green ci

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Documentation only change
  • Refactor (non-breaking change which fixes an issue without changing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • 📖

    • My change doesn't require a documentation update, or ...
    • it does and I have updated it
  • ⚖️

    • The contribution will be subject to The MIT license, and I'm OK with that.
    • The contribution is my own original work.
    • I am ok with the stuff in CONTRIBUTING.md.

@sverweij

Copy link
Copy Markdown
Owner Author

@copilot the check-windows job fails on the test step (npx mocha --invert --fgrep "#do-not-run-on-windows"), whereas the same step on linux (and locally macos) succeeds.

As an expert in differences between linux and windows - can you analyze the root-cause of this issue (and propose a fix)?

Copilot AI commented May 30, 2026

Copy link
Copy Markdown
Contributor

@copilot the check-windows job fails on the test step (npx mocha --invert --fgrep "#do-not-run-on-windows"), whereas the same step on linux (and locally macos) succeeds.

As an expert in differen...

Root cause: resolve.mjs was calling pathToPosix(pFileDirectory) to convert the Windows path D:\path\to\dirD:/path/to/dir before passing it as lookupStartPath to enhanced-resolve's resolveSync.

Inside enhanced-resolve's TsconfigPathsPlugin, D:/... is classified as PathType.AbsoluteWin (the path detection logic accepts either / or \ after the drive letter+colon). This causes resolver.join(...) to use winNormalize, producing backslash-style paths for both the tsconfig file path and the mainContext computed from it (e.g. D:\path\to\dir).

The _selectPathsDataForContext function then compares request.path = "D:/path/to/dir" (forward slashes, from pathToPosix) against context = "D:\path\to\dir" (backslashes) — they never match, so no tsconfig path aliases are applied and resolution falls through to couldNotResolve: true.

On Linux/macOS the paths never have a drive letter prefix, so they always use PathType.AbsolutePosix throughout and there's no inconsistency.

Fix (commit $(git rev-parse --short HEAD)): Removed the pathToPosix call on the lookupStartPath in resolve.mjs. Enhanced-resolve already handles native Windows paths correctly end-to-end; the POSIX normalisation of the output path happens downstream in resolve-cjs.mjs where it belongs.

@sverweij

Copy link
Copy Markdown
Owner Author

@copilot while that seems to have lessened the issue, a new issue has popped up in the test step on windows. Can you check why this is is going wrong and propose a fix?

Copilot AI commented May 30, 2026

Copy link
Copy Markdown
Contributor

@copilot while that seems to have lessened the issue, a new issue has popped up in the test step on windows. Can you check why this is is going wrong and propose a fix?

Root cause: When baseDir is given as a relative path (e.g. "test/extract/__mocks__/cjs"), pFileDirectory is also relative. On Windows, path.join normalises slashes to backslashes, producing e.g. test\extract\__mocks__\cjs. Enhanced-resolve's getType() classifies this as PathType.Normal (not PathType.AbsoluteWin), so it falls through to POSIX normalisation — which treats backslashes as ordinary characters, not separators. As a result, .. in the module request ../symlinked is never resolved against the base path, and resolution fails with couldNotResolve: true.

Fix (commit $(git rev-parse --short HEAD)): Added resolvePath(pFileDirectory) (Node's path.resolve) in resolve.mjs before passing the directory to resolveSync. For already-absolute paths this is a no-op; for relative paths it produces an absolute one, so enhanced-resolve always sees an absolute Windows path (PathType.AbsoluteWin), uses winNormalize consistently throughout, and correctly follows the junction/symlink to its target.

@sverweij sverweij changed the title refactor(resolve): replaces tsconfig-paths-webpack-plugin with enhanced-resolve's own tsconfig-paths feature refactor!(resolve): replaces tsconfig-paths-webpack-plugin with enhanced-resolve's own tsconfig-paths feature SLIGHTLY BREAKING May 30, 2026
@sverweij sverweij changed the title refactor!(resolve): replaces tsconfig-paths-webpack-plugin with enhanced-resolve's own tsconfig-paths feature SLIGHTLY BREAKING refactor(resolve)!: replaces tsconfig-paths-webpack-plugin with enhanced-resolve's own tsconfig-paths feature SLIGHTLY BREAKING May 30, 2026
@sverweij sverweij requested a review from Copilot May 30, 2026 15:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactor swaps tsconfig path resolution from tsconfig-paths-webpack-plugin to enhanced-resolve native tsconfig support, reducing dependency footprint and making resolve option normalization synchronous.

Changes:

  • Removes tsconfig-paths-webpack-plugin dependency and lockfile entries.
  • Adds enhanced-resolve tsconfig option in resolve option normalization.
  • Updates tests/callers to stop awaiting normalizeResolveOptions.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
.c8rc.json Raises coverage thresholds.
package.json Removes plugin dependency.
package-lock.json Removes plugin tree and updates dependency metadata.
src/main/resolve-options/normalize.mjs Replaces plugin setup with enhanced-resolve tsconfig option; makes function sync.
src/main/cruise.mjs Uses sync normalize call.
src/config-utl/extract-depcruise-config/index.mjs Uses sync normalize call.
src/extract/resolve/resolve.mjs Uses absolute lookup start path for enhanced-resolve.
test/cli/__fixtures__/workspaces-mono-repo-aliases/tsconfig.json Adjusts alias fixture for native tsconfig behavior.
test/main/resolve-options/normalize.spec.mjs Updates normalize tests for sync behavior.
test/extract/run-get-dependencies-fixture.utl.mjs Updates fixture helper for sync normalize.
test/extract/resolve/index.typescript.spec.mjs Updates resolve tests for sync normalize.
test/extract/resolve/index.tsconfig.spec.mjs Updates tsconfig resolve tests for sync normalize.
test/extract/resolve/index.general.spec.mjs Updates general resolve tests for sync normalize.
test/extract/resolve/external-module-helpers.spec.mjs Updates shared resolve options for sync normalize.
test/extract/index.with-stats.spec.mjs Updates extract stats test for sync normalize.
test/extract/index.maxdepth.spec.mjs Updates max-depth tests for sync normalize.
test/extract/index.exclude.spec.mjs Updates exclude tests for sync normalize.
test/extract/index.donotfollow.spec.mjs Updates do-not-follow tests for sync normalize.
test/extract/index.cachebusting.spec.mjs Updates cache-busting test for sync normalize.
test/extract/get-dependencies.odds-and-ends.spec.mjs Updates dependency extraction tests for sync normalize.
test/extract/get-dependencies.cjs.spec.mjs Updates CJS dependency tests for sync normalize.
test/extract/get-dependencies.amd.spec.mjs Updates AMD dependency tests for sync normalize.

Comment thread src/main/resolve-options/normalize.mjs Outdated
Comment thread test/main/resolve-options/normalize.spec.mjs Outdated
Comment thread test/main/resolve-options/normalize.spec.mjs Outdated
sverweij and others added 2 commits May 30, 2026 18:03
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 22 changed files in this pull request and generated 3 comments.

Comment thread test/main/resolve-options/normalize.spec.mjs Outdated
Comment thread test/main/resolve-options/normalize.spec.mjs Outdated
Comment thread test/main/resolve-options/normalize.spec.mjs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 22 changed files in this pull request and generated no new comments.

@sverweij sverweij merged commit ecb6354 into main May 30, 2026
7 checks passed
@sverweij sverweij deleted the refactor/replace-ts-config-paths-webpack-plugin-with-ehrs-own-implementation branch May 30, 2026 18:35
sverweij added a commit that referenced this pull request Jun 6, 2026
…ith enhanced-resolve's own tsconfig-paths feature SLIGHTLY BREAKING (#1061)" and "refactor(main/resolve-options): removes now unused pTSConfig parameter" (#1064)

## Description

- **Reverts** replacing the tsconfig-paths-webpack-plugin with
enhanced-resolve's own version of it

## Motivation and Context

- it turns out the SLIGHTLY BREAKING bit it the commit bumps into a
feature that is still used in the wild. It might be a misimplementation
in tsconfig-paths a.c.t. the typescript specification, however, it's
used and due to its wide spread should probably be construed as a
de-facto standard.
- enhanced-resolve's own tsconfig-paths resolution is _a lot_ slower on
some of the larger typescript repositories. Just the commits we
currently revert it added >8000ms of extra processing time to just the
_extract_ step.

These issues will need to be addressed in the enhanced-resolve codebase
- _if time permits_ I might open issues for it there and maybe even cook
PR's. Until these land in enhanced-resolve we'll stay on the old
tsconfig-paths-webpack-plugin.

## How Has This Been Tested?

- [x] green ci


## Types of changes

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Documentation only change
- [x] Refactor (non-breaking change which fixes an issue without
changing functionality)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)

Not a breaking change as these commits weren't released yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants