代码分割动态导入报错:JSX元素无构造或调用签名
解决Webpack 4 + React + TypeScript动态导入的"JSX element type 'Hello' does not have any construct or call signatures"错误
你碰到的这个问题其实是动态导入的一个常见坑——动态导入返回的是整个模块对象,而不是直接的默认导出组件。
当你写let Hello = await import('./components/Hello')时,Hello变量实际指向的是包含所有导出项的模块(比如里面会有default属性对应你的组件类),而不是可直接用于JSX的组件本身。TypeScript会严格检查类型,自然会报错说这个模块对象没有构造或调用签名。
快速修复方案
只需要修改App.tsx里的动态导入逻辑,手动获取模块的默认导出即可:
方案1:解构获取默认导出(推荐)
import * as React from 'react'; import * as ReactDOM from 'react-dom'; (async () => { // 解构出模块的default属性,赋值给Hello变量 const { default: Hello } = await import('./components/Hello'); ReactDOM.render(<Hello compiler="TypeScript" framework="React" bundler="webpack" />, document.getElementById('root')); })();
方案2:显式访问.default属性
如果不习惯解构,也可以分步处理:
import * as React from 'react'; import * as ReactDOM from 'react-dom'; (async () => { const HelloModule = await import('./components/Hello'); // 从模块对象中取出默认导出的组件 const Hello = HelloModule.default; ReactDOM.render(<Hello compiler="TypeScript" framework="React" bundler="webpack" />, document.getElementById('root')); })();
为什么静态导入没问题?
你用静态导入import Hello from './components/Hello'时,TypeScript(以及ES模块规范)会自动帮你把模块的default导出赋值给Hello变量,所以不需要手动处理。但动态导入遵循的是ES模块的动态加载规范,返回的始终是完整的模块对象,必须手动提取需要的导出项。
你的tsconfig.json和webpack.config.js配置本身没有问题——module: "esnext"支持动态导入语法,awesome-typescript-loader也能正确处理这种场景,只要调整动态导入的使用方式就能解决报错。
内容的提问来源于stack exchange,提问作者tomsseisums
相关产品推荐
相关产品推荐

