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

使用Rollup+TypeScript构建的React组件库导入后Jest测试报错

React组件库Jest测试报错:组件类型无效

场景

用Rollup、TypeScript和MUI构建的React组件库在生产环境运行正常,但在客户端用Jest+@testing-library测试时,出现以下错误:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

已做过以下排查:

  • 导出/导入语法无问题(自查)
  • 向MUI Button传递图标的语法正确
  • 尝试在Rollup配置中使用命名导出
  • 组件库内部执行相同测试(未转译)可正常运行
  • 尝试将库添加至transformIgnorePatterns
  • 客户端仅使用MUI时Jest测试正常,导入自定义库后才报错

组件库Rollup配置

import { babel } from "@rollup/plugin-babel";
import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import terser from "@rollup/plugin-terser";
import typescript from "@rollup/plugin-typescript";
import postcss from "rollup-plugin-postcss";
import pkg from "./package.json" assert { type: "json" };

export default [
  {
    input: "src/index.ts",
    output: [
      {
        file: pkg.main,
        format: "cjs",
        sourcemap: true,
      },
      {
        file: pkg.module,
        format: "esm",
        sourcemap: true,
      },
    ],
    external: [
      "react",
      "react-dom",
      "@mui/styles",
      "@mui/material",
      "@mui/icons-material",
      "@emotion/styled",
      "@emotion/react",
    ],
    plugins: [
      json(),
      nodeResolve(),
      commonjs(),
      postcss(),
      typescript({ tsconfig: "../../tsconfig.json" }),
      babel({
        exclude: "node_modules/**",
        babelrc: false,
        presets: [["@babel/preset-env", { modules: false }], "@babel/preset-react"],
      }),
      terser(),
    ],
  },
];

组件库Tsconfig配置

{
  "compilerOptions": {
    "jsx": "react",
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "allowJs": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dts",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["./src/**/*"],
  "exclude": ["./src/__tests__/**/*"]
}

客户端应用Jest配置

export default {
  clearMocks: true,

  moduleFileExtensions: ['js', 'mjs', 'cjs', 'jsx', 'ts', 'tsx', 'json', 'node'],

  moduleNameMapper: {
    '\\.(css|scss)$': '<rootDir>/empty-module.js',
  },
  verbose: true,

  testEnvironment: 'jsdom',
};

解决思路与方案

1. 调整Jest转译规则

Jest默认忽略node_modules目录下的代码转译,但你的组件库是ES模块格式,Node环境下的Jest无法直接解析,需要让Jest转译你的组件库代码:

  • 修改客户端Jest配置,添加transformIgnorePatterns,排除node_modules中除你组件库之外的其他包:
transformIgnorePatterns: ['/node_modules/(?!your-library-name)/']
  • 添加转译配置,确保Jest能处理TypeScript和React代码:
transform: {
  '^.+\\.(ts|tsx)$': 'ts-jest',
  '^.+\\.(js|jsx)$': 'babel-jest'
}

2. 确认组件库package.json导出配置

确保package.json中正确声明不同模块规范的入口,避免Jest解析混乱:

{
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "types": "dts/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.esm.js",
      "require": "./dist/index.cjs.js"
    }
  }
}

3. 检查组件导出方式

确保组件库的导出是命名导出或正确的默认导出,避免导出对象导致React无法识别:

  • 正确写法(命名导出):
// src/index.ts
export { YourButton } from './components/YourButton';
  • 错误写法(导出对象):
// 不要这样写
export default { YourButton };

4. 验证客户端导入方式

确保客户端导入组件的方式和组件库的导出方式匹配:

  • 如果是命名导出:
import { YourButton } from 'your-library-name';
  • 如果是默认导出:
import YourButton from 'your-library-name';

5. 临时禁用Terser压缩(排查用)

可以尝试在Rollup配置中仅在生产环境启用Terser,避免压缩导致的测试环境解析问题:

// 修改Rollup插件配置
plugins: [
  // ...其他插件
  process.env.NODE_ENV === 'production' && terser(),
].filter(Boolean)

内容的提问来源于stack exchange,提问作者vetroxl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 20:52:52