You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js Module Federation微前端:远程组件加载后如何注册使用?

Vue 3 + Module Federation 远程组件注册与使用方案

核心问题分析

你的代码主要问题在于:

  1. 直接赋值Header = res不是响应式状态,模板无法识别这个动态组件;
  2. 模板中直接写<Header>会被Vue视为原生HTML标签,而非Vue组件;
  3. defineAsyncComponent的用法错误,没有结合你自定义的loadComponent流程来封装远程组件加载逻辑。

方法一:响应式变量+动态组件(最简洁方案)

这是Vue 3中动态渲染异步组件的标准方式,适合你的场景:

<script setup>
import { ref, onMounted } from 'vue'

// 用响应式变量存储远程组件
const Header = ref(null)
const modules = [
  {
    protocol: 'http',
    host: 'localhost',
    port: 8080,
    moduleName: 'Company',
    fileName: 'remoteEntry.js',
    componentNames: ['Header'],
  },
]

onMounted(() => {
  modules.forEach((uiApplication) => {
    const remoteURL = `${uiApplication.protocol}://${uiApplication.host}:${uiApplication.port}/${uiApplication.fileName}`
    const { componentNames, moduleName } = uiApplication

    const element = document.createElement('script')
    element.type = 'text/javascript'
    element.async = true
    element.src = remoteURL

    element.onload = async () => {
      for (const componentName of componentNames || []) {
        const componentLoader = loadComponent(moduleName, `./${componentName}`)
        const remoteComponent = await componentLoader()
        // 注意:远程组件如果是export default导出,需要取.default;命名导出则取对应属性
        Header.value = remoteComponent.default || remoteComponent
      }
    }
    document.head.appendChild(element)
  })
})

function loadComponent(scope, module) {
  return async () => {
    await __webpack_init_sharing__('default')
    const container = window[scope]
    await container.init(__webpack_share_scopes__.default)
    const factory = await container.get(module)
    const Module = factory()
    return Module
  }
}
</script>
<template>
  <div>
    <!-- 使用Vue动态组件渲染远程组件,v-if确保组件加载完成后再渲染 -->
    <component v-if="Header" :is="Header" title="Test shop" />
    <h2>Our Shop Page</h2>
  </div>
</template>

方法二:预定义异步组件(提前注册方案)

如果想像使用本地组件一样直接在模板中调用,可通过defineAsyncComponent封装远程组件加载流程:

<script setup>
import { defineAsyncComponent } from 'vue'

// 预定义远程Header组件
const RemoteHeader = defineAsyncComponent(() => {
  return new Promise(async (resolve) => {
    // 先加载remoteEntry.js,避免重复加载
    await loadRemoteEntry('http://localhost:8080/remoteEntry.js', 'Company')
    // 再加载目标组件
    const componentLoader = loadComponent('Company', './Header')
    const component = await componentLoader()
    resolve(component.default || component)
  })
})

// 封装remoteEntry加载逻辑,加缓存避免重复请求
async function loadRemoteEntry(url, scope) {
  if (window[scope]) return
  return new Promise((resolve, reject) => {
    const element = document.createElement('script')
    element.type = 'text/javascript'
    element.async = true
    element.src = url
    element.onload = resolve
    element.onerror = reject
    document.head.appendChild(element)
  })
}

function loadComponent(scope, module) {
  return async () => {
    await __webpack_init_sharing__('default')
    const container = window[scope]
    await container.init(__webpack_share_scopes__.default)
    const factory = await container.get(module)
    const Module = factory()
    return Module
  }
}
</script>
<template>
  <div>
    <!-- 直接使用预定义的远程组件 -->
    <RemoteHeader title="Test shop" />
    <h2>Our Shop Page</h2>
  </div>
</template>

关键注意事项

  • 响应式要求:动态获取的组件必须存储在响应式变量中,模板才能感知到组件加载完成的状态变化;
  • 组件导出格式:远程组件如果是export default导出,需取.default属性;如果是命名导出,则对应取命名属性;
  • 重复加载防护:添加判断逻辑,确保remoteEntry.js只加载一次,避免重复创建script标签;
  • 错误处理:建议在异步流程中添加try/catch,处理网络错误、组件不存在等异常情况。

内容的提问来源于stack exchange,提问作者by Neznayka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:45:37