# mf-remote-comps **Repository Path**: scobiser/mf-remote-comps ## Basic Information - **Project Name**: mf-remote-comps - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-10 - **Last Updated**: 2026-07-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MF Demo — Module Federation 本地示例 演示「主应用 A 远程引用组件库 B」的微前端架构。 ## 架构 ``` ┌────────────────────┐ ┌────────────────────┐ │ a-host-app │ HTTP │ b-component-lib │ │ Host (port 5000) │ ──────► │ Remote (port 5001)│ │ │ │ │ │ import('B/...') │ │ exposes: │ │ ▼ │ │ ./HelloButton │ │ 渲染远程组件 │ │ │ └────────────────────┘ └────────────────────┘ ``` ## 启动顺序 > **必须先启动 B**,A 才能拿到 `remoteEntry.js`。 ### 1) 启动组件库 B(Remote) ```bash cd b-component-lib npm install npm run dev # → http://localhost:5001 # → remoteEntry.js 在 http://localhost:5001/remoteEntry.js ``` 打开 B 的预览页,你应该能看到本地按钮。 ### 2) 启动主应用 A(Host) ```bash cd a-host-app npm install npm run dev # → http://localhost:5000 ``` 打开 A 的预览页,如果按钮能正常渲染并响应点击,说明 A 成功通过 `remoteEntry.js` 远程加载到了 B 的组件。 ## 验证「远程」是真的远程 打开 A 页面的 Network 面板,刷新页面,你会看到: - 来自 `localhost:5001` 的 JS chunk(组件代码) - 来自 `localhost:5001/remoteEntry.js` 的入口 这些请求证明组件代码**不是**被打进 A 的 bundle,而是**运行时**从 B 拉取的。 ## 关键文件对应关系 | 角色 | 文件 | 关键点 | |---|---|---| | B(Remote) | `b-component-lib/vite.config.js` | `exposes` 决定暴露什么 | | A(Host) | `a-host-app/vite.config.js` | `remotes` 决定从哪里拉取 | | A 引用 B | `a-host-app/src/main.js` | `import('b_component_lib/HelloButton')` ← key | ## 改成「长 hash key」 `@module-federation/vite` 的 `exposes` key 本身支持任意字符串,例如: ```js exposes: { './HelloButton_v2_a3f8b9c2d1': './src/components/HelloButton.vue', } ``` A 端相应改成: ```js import('b_component_lib/HelloButton_v2_a3f8b9c2d1') ``` 实际项目里 key 来自 CI 注入的环境变量(版本号 + commit hash),效果和前面描述的「一长串字母」完全一致。 ## 排错 1. **A 报 `Failed to fetch dynamically imported module`** → B 没启动,或者端口被占。先 `curl http://localhost:5001/remoteEntry.js` 看能否访问。 2. **Vue 版本冲突警告** → A/B 的 `vue` 主版本必须一致(本示例都用 `^3.4.0`)。 3. **`shared: { vue: { singleton: true } }` 必须打开**,否则 A 和 B 会有两个 Vue 实例,组件会渲染不出来。