Skip to content

解决 "Failed to parse source map" 错误

问题描述

当使用 Rollup 构建的 npm 库在 React 项目中安装并使用时,可能会遇到以下警告信息:

Failed to parse source map from 'C:\Users\XXXX\Desktop\example\node_modules\@AAA\BBB\src\components\Button\Button.tsx' file: 
Error: ENOENT: no such file or directory, open 
'C:\Users\XXXX\Desktop\example\node_modules\@AAA\BBB\src\components\Button\Button.tsx'

这个警告通常出现在使用 Webpack 5 和 Create React App (CRA) 的项目中。虽然这只是一个警告,不会阻止应用程序运行,但可能会影响开发体验。

问题根源

这个问题的根本原因是 Webpack 的 source-map-loader 尝试解析第三方库的源映射文件,但找不到对应的源文件(.tsx 文件)。这通常发生在以下情况:

  1. 库的构建配置中源映射生成有问题
  2. 库发布时没有包含源文件
  3. Webpack 配置过于严格地尝试解析所有源映射

解决方案

方法一:禁用源映射生成(临时解决方案)

在项目根目录创建或修改 .env 文件,添加:

env
GENERATE_SOURCEMAP=false

或者修改 package.json 中的启动脚本:

json
{
  "scripts": {
    "start": "GENERATE_SOURCEMAP=false react-scripts start"
  }
}

WARNING

这种方法会完全禁用源映射,可能会影响你在开发过程中的调试体验。

方法二:配置 Webpack 排除特定包

修改 Webpack 配置,排除对特定包的源映射处理:

javascript
// webpack.config.js 或通过 react-app-rewired 自定义配置
module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|mjs|jsx|ts|tsx|css)$/,
        enforce: 'pre',
        exclude: [
          /@babel(?:\/|\\{1,2})runtime/,
          /node_modules(\/|\\)@AAA(\/|\\)BBB/
        ],
        use: {
          loader: 'source-map-loader'
        }
      }
    ]
  }
}

方法三:使用 filterSourceMappingUrl 选项

更精确地控制哪些源映射应该被处理:

javascript
{
  test: /\.js$/,
  enforce: 'pre',
  use: {
    loader: 'source-map-loader',
    options: {
      filterSourceMappingUrl: (url, resourcePath) => {
        if (resourcePath.includes('@AAA/BBB')) {
          return false;
        }
        return true;
      }
    }
  }
}

方法四:修复库的构建配置(库开发者)

如果你是库的开发者,可以修复 Rollup 配置来正确生成源映射:

javascript
// rollup.config.js
import typescript from '@rollup/plugin-typescript';
import sourcemaps from 'rollup-plugin-sourcemaps';

export default {
  input: 'src/index.ts',
  output: [
    {
      file: 'dist/cjs/index.js',
      format: 'cjs',
      sourcemap: true
    },
    {
      file: 'dist/esm/index.js',
      format: 'esm',
      sourcemap: true
    }
  ],
  plugins: [
    // 确保插件顺序正确
    typescript({ 
      tsconfig: './tsconfig.json',
      sourceMap: true // 确保 TypeScript 生成源映射
    }),
    sourcemaps() // 正确处理源映射
  ]
};

确保 tsconfig.json 中包含正确的源映射配置:

json
{
  "compilerOptions": {
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true
  }
}

方法五:发布时包含源文件

package.json 中指定发布时应包含 src 目录:

json
{
  "files": ["dist", "src"]
}

这样安装包时会包含源文件,source-map-loader 就能找到对应的源文件。

最佳实践

  1. 对于应用程序开发者:使用方法二或三配置 Webpack 排除规则,这样既保留了调试能力,又避免了不必要的警告。

  2. 对于库开发者:确保正确配置构建工具生成完整的源映射,并在发布时包含必要的源文件。

  3. 慎用完全禁用源映射的方案:虽然方法一简单有效,但会牺牲开发调试体验。

总结

"Failed to parse source map" 警告通常是由于源映射配置不匹配导致的。通过合理配置 Webpack 排除规则或修复库的构建配置,可以有效解决这个问题,同时保持良好的开发体验。

INFO

这个问题在 Webpack 5 和 Create React App 中较为常见,相关团队已经在积极解决中。关注官方更新可以获取最新的解决方案。