tsconfig配置paths指向node_modules触发ERR_REQUIRE_ESM错误的原因是什么?
问题背景
我已经掌握[ERR_REQUIRE_ESM]: Must use import to load ES Module错误的解决方法,但排查发现该错误是由tsconfig.json中paths配置指向node_modules触发,暂时不清楚具体的触发逻辑,希望了解根本原因。
初始tsconfig.json配置
{ "compileOnSave": false, "compilerOptions": { "paths": { "*": ["node_modules/*", "types/*"] } } }
删除配置项"*": ["node_modules/*", "types/*"]即可直接解决问题。
错误触发场景
该错误在给ts-node注册tsconfig-paths后执行webpack -c webpack.config.ts时必现,此时完整tsconfig.json配置如下:
{ "compileOnSave": false, "compilerOptions": { "paths": { "*": ["node_modules/*", "types/*"] } }, "ts-node": { "require": ["tsconfig-paths/register"] } }
完整错误栈
(node:6087) UnhandledPromiseRejectionWarning: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /workspace/dibo/projects/ngx-cms/node_modules/colorette/index.js require() of ES modules is not supported. require() of /workspace/dibo/projects/ngx-cms/node_modules/colorette/index.js from /workspace/dibo/projects/ngx-cms/node_modules/webpack-cli/lib/utils/index.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules. Instead rename /workspace/dibo/projects/ngx-cms/node_modules/colorette/index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /workspace/dibo/projects/ngx-cms/node_modules/colorette/package.json. at Object.Module._extensions..js (internal/modules/cjs/loader.js:1089:13) at Module.load (internal/modules/cjs/loader.js:937:32) at Function.Module._load (internal/modules/cjs/loader.js:778:12) at Module.require (internal/modules/cjs/loader.js:961:19) at require (/workspace/dibo/projects/ngx-cms/node_modules/v8-compile-cache/v8-compile-cache.js:159:20) at Object.get colors [as colors] (/workspace/dibo/projects/ngx-cms/node_modules/webpack-cli/lib/utils/index.js:3:16) at Object.error (/workspace/dibo/projects/ngx-cms/node_modules/webpack-cli/lib/utils/logger.js:5:58) at runCLI (/workspace/dibo/projects/ngx-cms/node_modules/webpack-cli/lib/bootstrap.js:13:22) (Use `node --trace-warnings ...` to show where the warning was created) (node:6087) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict`. (rejection id: 2) (node:6087) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
根本原因说明
- 你配置的
"*": ["node_modules/*", "types/*"]是全局通配的路径重写规则,配合tsconfig-paths/register启用后,会接管Node.js运行时所有模块的解析逻辑,包括node_modules中第三方包的依赖解析,而非仅处理你项目自定义的路径别名。 - 目前很多同时支持ESM和CommonJS的第三方包,都会在package.json的
exports字段中区分导入方式对应的入口:CommonJS的require()会指向.cjs后缀的CommonJS版本入口,ESM的import会指向.js后缀的ESM版本入口。但你配置的全局路径规则会强制跳过Node.js原生的模块解析逻辑,直接将所有导入指向node_modules/[包名]/index.js的ESM入口,忽略了exports字段的区分规则。 - tsconfig-paths本身不支持ESM和CommonJS的解析区分逻辑,也不会识别依赖包package.json中的
type: module配置。本次报错中webpack-cli本身是CommonJS模块,它调用require('colorette')时被强制指向了colorette的ESM入口,因此直接触发了require()加载ESM模块不被支持的错误。 - 你删除该全局路径配置后,tsconfig-paths不会接管第三方包的解析逻辑,所有node_modules中的依赖会走Node.js原生解析规则,自然会匹配到对应CommonJS格式的入口,报错就会消失。
内容的提问来源于stack exchange,提问作者Sherif eldeeb
相关产品推荐
相关产品推荐

