Skip to content

feat(config): support all TS webpack configs using esbuild fallback#4726

Open
ThierryRakotomanana wants to merge 7 commits intowebpack:mainfrom
ThierryRakotomanana:feat/typescript-config-esbuild-fallback
Open

feat(config): support all TS webpack configs using esbuild fallback#4726
ThierryRakotomanana wants to merge 7 commits intowebpack:mainfrom
ThierryRakotomanana:feat/typescript-config-esbuild-fallback

Conversation

@ThierryRakotomanana
Copy link
Copy Markdown
Contributor

Summary

This is a feature I discussed accross my PR #4723 with Alexander

Webpack config files written in TypeScript fail to load as ECMAScript modules, producing the following error even when all dependencies are installed and the configuration is correctly set up:

[webpack-cli] Failed to load 'webpack.config.mts' config
▶ ESM (import) failed: Unknown file extension ".ts"
▶ CJS (require) failed:
Cannot require() ES Module ... because it is not yet fully loaded.
This is caused by either a bug in Node.js...

This forces users to pass --require or --import via NODE_OPTIONS before webpack even starts, a poor developer experience that requires additional configuration just to use TypeScript configs.

What kind of change does this PR introduce?

It's Feature to support all kind of typescript no matter what type of javascript(CJS or ECMA) the user use without adding any additional config, it's like a native support.

Users no longer need to pass NODE_OPTIONS inside package.json to tell Node.js which TypeScript loader webpack should use. This improves the developer experience by requiring minimal or no additional configuration.

Why esbuild and not tsx/ts-node hooks: Hook-based loaders (tsx/esm/api register(), ts-node/esm) inject themselves into Node's module graph mid-execution. Since webpack-cli itself runs as ESM, this causes circular dependency errors. esbuild writes a standalone output file, no hooks, no circular dependencies.

Why next to the original config and not /tmp/:
Node.js resolves bare specifiers (import HtmlWebpackPlugin from 'html-webpack-plugin') relative to the importing file's location. Writing the temp file to /tmp/ would break this resolution. Writing it next to the original config preserves it correctly.

Did you add tests for your changes?

Yes, I added and updated the following:

  • test/build/config-format/typescript-esbuild/ :
    New test fixture and test suite covering ESM syntax, CJS syntax, .mts extension, and the missing-esbuild error message.

  • test/build/config-format/typescript-auto/typescript.test.mjs :
    Removed the assertion on Node.js's "Reparsing" warning, esbuild now handles loading before Node.js built-in type stripping runs, so the warning no longer appears. The test has been updated to reflect this improved behavior.

Does this PR introduce a breaking change?

Not in the traditional sense — all existing loading paths are untouched. The new code only runs when every existing path has already failed. Here is a summary of the changes:

  • packages/webpack-cli/src/webpack-cli.ts

    • Add private isTypeScriptConfig() method
    • Add private loadTypeScriptConfig() method
    • Update RechoirError handler to re-throw for TypeScript files
    • Update outer catch to attempt esbuild recovery for TypeScript files
    • Add a clean, colored error message when esbuild is not installed
  • packages/webpack-cli/package.json

    • Add esbuild >=0.17.0 as an optional peer dependency
  • package.json (monorepo root)

    • Add esbuild to devDependencies for the test suite

If relevant, what needs to be documented once your changes are merged or what have you already documented?

Documentation is already in progress but couldn't be submit before this change will be approved. One open question worth discussing: what is the recommended guidance for users who prefer ts-node or tsx over esbuild? and what configuration should be needed for each of them.

Use of AI
No, I spent several days working through this before even opening the PR.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 5, 2026

⚠️ No Changeset found

Latest commit: 2fe1093

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 5, 2026

Codecov Report

❌ Patch coverage is 20.98765% with 128 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.65%. Comparing base (4f415db) to head (2fe1093).

Files with missing lines Patch % Lines
packages/webpack-cli/src/webpack-cli.ts 20.98% 128 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (4f415db) and HEAD (2fe1093). Click for more details.

HEAD has 12 uploads less than BASE
Flag BASE (4f415db) HEAD (2fe1093)
13 1
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #4726       +/-   ##
===========================================
- Coverage   91.43%   25.65%   -65.79%     
===========================================
  Files          14       14               
  Lines        4716     4873      +157     
  Branches      679      122      -557     
===========================================
- Hits         4312     1250     -3062     
- Misses        402     3621     +3219     
  Partials        2        2               
Files with missing lines Coverage Δ
packages/webpack-cli/src/webpack-cli.ts 41.33% <20.98%> (-54.73%) ⬇️

... and 12 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4f415db...2fe1093. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

1 participant