使用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
相关产品推荐
相关产品推荐

