Webpack构建报错:React-TypeScript项目迁移ESM模块后无法解析导入
解决Webpack无法解析ESM迁移后的导入问题
问题根源
核心矛盾在于:TSC要求ESM模块导入必须带上编译输出后的扩展名(如.mjs/.js),但Webpack构建时处理的是源文件(.mts/.tsx)而非编译产物,直接引用输出扩展名会导致Webpack找不到对应源文件。
推荐解决方案(最简洁)
使用TypeScript 4.7+支持的bundler模块解析策略,让TSC信任Webpack处理扩展名,无需在源文件中添加输出扩展名。
1. 修改tsconfig.json
更新compilerOptions中的moduleResolution为bundler,确保ESM配置正确:
{ "compilerOptions": { "module": "ESNext", "moduleResolution": "bundler", // 关键配置,适配打包工具的解析逻辑 "target": "ESNext", "outDir": "./dist", "esModuleInterop": true, "skipLibCheck": true, "strict": true, "jsx": "react-jsx", "resolveJsonModule": true, "allowImportingTsExtensions": false // 禁止直接导入.ts/.mts扩展名 }, "include": ["src/**/*"], "exclude": ["node_modules"] }
2. 恢复导入语句为无扩展名形式
把之前修改的带扩展名导改回原样:
// ./src/webapp/mainContextProviders.tsx import utils from '../common/utils' import settings from './Settings/SettingsContext' import { pkgApis } from './callPkgApis'
3. 确保Webpack识别源文件扩展名
在webpack.config.js(或.mjs)中更新resolve.extensions,包含所有源文件扩展名:
module.exports = { // ...其他配置 resolve: { extensions: ['.tsx', '.ts', '.mts', '.js', '.mjs'], }, module: { rules: [ { // 让Webpack能处理.mts/.ts/.tsx文件 test: /\.(ts|mts|tsx)$/, exclude: /node_modules/, use: 'ts-loader' // 或babel-loader,根据你的配置选择 } ] } }
备选方案(若需保留带扩展名的导入)
如果必须保留导入语句中的输出扩展名,可通过Webpack插件替换扩展名,映射到源文件:
添加NormalModuleReplacementPlugin
在Webpack配置中添加插件,将.mjs/.js替换为对应的源文件扩展名:
const webpack = require('webpack'); const fs = require('fs'); const path = require('path'); module.exports = { // ...其他配置 plugins: [ // 替换.mjs为.mts new webpack.NormalModuleReplacementPlugin(/\.mjs$/, resource => { resource.request = resource.request.replace(/\.mjs$/, '.mts'); }), // 替换.js为.tsx(优先)或.mts new webpack.NormalModuleReplacementPlugin(/\.js$/, resource => { const basePath = resource.request.replace(/\.js$/, ''); const tsxPath = `${basePath}.tsx`; const mtsPath = `${basePath}.mts`; if (fs.existsSync(path.resolve(resource.context, tsxPath))) { resource.request = tsxPath; } else if (fs.existsSync(path.resolve(resource.context, mtsPath))) { resource.request = mtsPath; } }) ] }
额外注意事项
- 确保
package.json中已设置"type": "module",若Webpack配置为CommonJS格式,需命名为webpack.config.cjs(避免ESM解析冲突)。 - 若使用babel-loader,需确保
@babel/preset-typescript支持.mts文件,可在babel配置中添加extensions: [".ts", ".mts", ".tsx"]。
内容的提问来源于stack exchange,提问作者aleclofabbro
相关产品推荐
相关产品推荐

