Vite项目外部化React v17.0.2遇react/jsx-runtime缺失求助
外部化React v17.0.2后@azure/msal-react触发Invalid hook call错误
问题背景
为适配single-spa,将项目中的React v17.0.2、react-dom、react-router-dom设为外部依赖,通过JSDelivr的importmap脚本引入这些库,但预览构建后的项目时,@azure/msal-react的MsalProvider触发Invalid hook call错误。
配置信息
Vite配置(vite.config.mjs)
export default defineConfig({ plugins: [react(), devEnvPlugin(), vitePluginSingleSpa({ type: 'root', imo: '3.1.0', importMaps: { dev: ['src/importMap.Dev.json', 'src/importMap.shared.json'], build: ['src/importMap.json', 'src/importMap.shared.json'] } })], build: { sourcemap: true, target: 'es2022', rollupOptions: { external: [fastrEnvModuleId, "react", "react-dom", "react-router-dom"] } }, esbuild: { supported: { 'top-level-await': true } }, server: { host: true, port: 4100, proxy: getProxyConfig() }, preview: { port: 4100 } });
ImportMap配置
{ "imports": { "react": "https://cdn.jsdelivr.net/npm/@esm-bundle/react@17.0.2-fix.1/+esm", "react-dom": "https://cdn.jsdelivr.net/npm/react-dom@17.0.2/+esm", "react-router-dom": "https://cdn.jsdelivr.net/npm/react-router-dom@5.3.4/+esm" } }
错误信息
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. at ye (react.development.js:1476:13) at o.useEffect (react.development.js:1519:20) at D1 (MsalProvider.js:76:5) at Lu (react-dom.production.min.js:157:137) at hs (react-dom.production.min.js:267:460) at ns (react-dom.production.min.js:250:347) at Ji (react-dom.production.min.js:250:278) at Zi (react-dom.production.min.js:250:138) at Qi (react-dom.production.min.js:243:163) at Ui (react-dom.production.min.js:237:175)
已尝试的操作
- 执行
npm ls react和npm ls react-dom确认依赖已去重 - 删除node_modules中的react和react-dom后,Vite构建提示react/jsx-runtime无法解析
- 尝试MDN方式配置importmap前缀映射无效,使用react-jsx-runtime包仍存在多React实例错误
- 注意到堆栈中同时出现react-dom.production.min.js和react.development.js,不确定是否相关
解决方案
1. 统一React/ReactDOM的环境版本
堆栈同时出现开发版和生产版文件,会导致实例不兼容。需确保importmap中引入的React和ReactDOM环境一致:
- 将react的CDN地址替换为生产版:
https://cdn.jsdelivr.net/npm/react@17.0.2/+esm(替换原@esm-bundle的开发版) - 保持react-dom的生产版地址,确保两者同为生产或开发环境
2. 外部化react/jsx-runtime相关依赖
Vite构建需要解析jsx运行时,需将相关模块加入外部依赖并映射:
- 在vite.config.mjs的
rollupOptions.external中添加:"react/jsx-runtime", "react/jsx-dev-runtime" - 在importmap中补充映射:
{ "imports": { // 原有映射 "react/jsx-runtime": "https://cdn.jsdelivr.net/npm/react@17.0.2/jsx-runtime/+esm", "react/jsx-dev-runtime": "https://cdn.jsdelivr.net/npm/react@17.0.2/jsx-dev-runtime/+esm" } }
3. 强制@azure/msal-react使用外部化React
确保@azure/msal-react不会打包自身的React副本,在vite.config.mjs中添加:
export default defineConfig({ // 其他配置 optimizeDeps: { exclude: ['react', 'react-dom', 'react-router-dom', '@azure/msal-react'] } });
4. 验证单React实例
在浏览器控制台执行以下代码,检查是否存在多实例:
// 统计React脚本数量 const reactScriptCount = Array.from(document.querySelectorAll('script')) .filter(s => s.src.includes('react')).length; console.log('React脚本实例数:', reactScriptCount); // 验证React对象一致性 Promise.all([import('react'), import('react-dom')]).then(([reactMod, reactDomMod]) => { console.log('模块引入的React:', reactMod.default); console.log('全局React(若存在):', window.React); console.log('是否为同一实例:', reactMod.default === window.React); });
若对象不一致,需确保importmap脚本在应用脚本之前加载。
内容的提问来源于stack exchange,提问作者José Ramírez
相关产品推荐
相关产品推荐

