You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 05:45:56