esbuild-loader替换ts-loader/babel-loader后报错找不到导入模块
问题原因
该报错本质是ES模块和CommonJS模块的互操作不兼容导致的,具体触发原因来自以下几个常见场景:
- esbuild-loader默认未开启ES模块互操作配置,不会自动将CommonJS格式的
module.exports/exports.xxx转换为ES模块的default导出和命名导出,当你用ES模块的import { A } from 'xxx'语法导入CommonJS模块时,webpack无法识别到对应的命名导出,就会抛出找不到导出的错误。 - 你提供的loader规则未保留CRA eject配置默认的
exclude: /node_modules/规则,如果esbuild-loader处理了node_modules中的CommonJS格式第三方依赖,会放大上述互操作问题。 - 若未完全移除原有ts-loader、babel-loader的js/ts类文件处理规则,两个loader同时处理同类文件会导致编译结果冲突,也会触发导出识别异常。
- esbuild-loader 2.16.0对应版本的esbuild内核对TS配置的对齐逻辑不完善,若未显式传入tsconfig配置,编译规则和项目本地tsconfig不一致,也会导致导出逻辑编译错误。
解决方案
按顺序检查修改以下配置即可解决问题:
- 给esbuild-loader补全互操作配置、排除node_modules、对齐TS配置,修改后的规则如下:
{ test: /\.tsx?$/, exclude: /node_modules/, loader: 'esbuild-loader', options: { loader: 'tsx', target: 'es2015', // 开启ES模块和CommonJS互操作 esModuleInterop: true, // 对齐本地tsconfig配置 tsconfigRaw: require('./tsconfig.json') } }, { test: /\.(js|mjs|jsx)$/, exclude: /node_modules/, loader: 'esbuild-loader', options: { loader: 'jsx', target: 'es2015', esModuleInterop: true } }
- 检查webpack配置,完全删除原有针对
.ts/.tsx/.js/.jsx文件的ts-loader、babel-loader处理规则,避免多loader重复编译。 - 如果修改配置后仍有少量导出报错,可以将对应报错模块的导入语法改为全量导入形式:
import * as XXX from 'xxx',再通过XXX.A的方式取用对应导出。 - 若上述操作都无效,可以升级esbuild-loader到最新的2.x稳定版,修复内核版本的编译bug,不要直接升级到3.x及以上大版本,避免和当前webpack 5.x版本出现兼容问题。
内容的提问来源于stack exchange,提问作者Gabrielle
相关产品推荐
相关产品推荐

