React微前端Module Federation报错:Uncaught (in promise) TypeError: fn非函数
解决Webpack Module Federation微前端"fn is not a function"错误
问题场景
使用Webpack Module Federation构建微前端,Products应用作为远程服务暴露模块,容器应用加载远程模块时出现以下错误:
Uncaught (in promise) TypeError: fn is not a function
while loading "./productsIndex" from webpack/container/reference/products
at handleFunction (main.js:500:31)
at onInitialized (main.js:512:60)
at main.js:502:52
at async Promise.all (:8080/index 0)
错误原因
Module Federation要求暴露的远程模块必须导出可被调用的函数/组件,当前Products应用的index.js直接执行DOM操作,没有任何导出内容,容器应用加载时无法找到可执行的入口逻辑,从而抛出错误。
解决方案
方案1:适配现有原生JS代码
修改Products应用的src/index.js,将DOM操作逻辑封装为导出函数,并保留独立运行能力:
import faker from 'faker'; // 封装初始化逻辑为导出函数 export const initProducts = () => { let products = ''; for (let index = 0; index < 5; index++) { products += `<div>${faker.commerce.productName()}</div>`; } document.querySelector('#products').innerHTML = products; }; // 独立运行时自动执行初始化 if (typeof window !== 'undefined') { initProducts(); }
修改容器应用的bootstrap.js,导入并调用该初始化函数:
import { initProducts } from 'products/productsIndex'; // 调用远程模块的初始化函数 initProducts(); console.log('container');
方案2:React组件场景(符合你尝试用React的需求)
如果要基于React实现,调整Products应用的src/index.js为导出React组件:
import React from 'react'; import ReactDOM from 'react-dom/client'; import faker from 'faker'; const Products = () => { return ( <div> {Array.from({ length: 5 }).map((_, idx) => ( <div key={idx}>{faker.commerce.productName()}</div> ))} </div> ); }; // 独立运行时渲染组件 if (typeof window !== 'undefined') { const container = document.querySelector('#products'); if (!container._reactRootContainer) { const root = ReactDOM.createRoot(container); root.render(<Products />); } } export default Products;
修改容器应用的bootstrap.js,导入并渲染React组件:
import React from 'react'; import ReactDOM from 'react-dom/client'; import Products from 'products/productsIndex'; // 在容器中渲染远程React组件 const root = ReactDOM.createRoot(document.querySelector('#products')); root.render(<Products />); console.log('container');
验证步骤
- 重启Products应用(端口8081)和容器应用(端口8080)
- 访问容器应用
http://localhost:8080,即可正常加载Products模块的内容
内容的提问来源于stack exchange,提问作者Nithya
相关产品推荐
相关产品推荐

