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

如何在基于Webpack 5的React微前端中调用Vue组件

问题:React微前端壳应用调用Vue组件报错

我刚开始学习微前端,用npx create-mf-app创建了React壳应用Micro-Shell-App,又用同样命令创建了Vue微前端项目SectionPart。想在React壳应用中调用Vue组件,但遇到以下错误:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.


项目目录结构

项目目录结构

相关代码片段

MyComponent.vue

<template>
  <div>
    <h2>Hello, {{ name }}!</h2>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: 'World'
    };
  }
};
</script>

SectionPart的webpack.config.js

// some imports
module.exports = (_, argv) => ({
  output: {
    publicPath: "http://localhost:3003/",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".vue", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3003,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: "vue-loader",
      },
      {
        test: /\.tsx?$/,
        use: [
          "babel-loader",
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true,
              appendTsSuffixTo: ["\\.vue$"],
              happyPackMode: true,
            },
          },
        ],
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
    ],
  },

  plugins: [
    new VueLoaderPlugin(),
    new ModuleFederationPlugin({
      name: "SectionPart",
      filename: "remoteEntry.js",
      remotes: {
       
      },
      exposes: {
        "./MyComponent":"./src/components/MyComponent.vue",
      },
      shared: require("./package.json").dependencies,
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
    new Dotenv()
  ],
});

Micro Shell App的webpack.config.js

// some imports 

module.exports = (_, argv) => ({
  output: {
    publicPath: "http://localhost:3000/",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3000,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /\.vue$/,
        loader: "vue-loader",
        exclude: /node_modules/
    }
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: "Micro_Shell_App",
      filename: "remoteEntry.js",
      remotes: {
        section:"SectionPart@http://localhost:3003/remoteEntry.js"
      },
      exposes: {},
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
    new VueLoaderPlugin(),
    new Dotenv()
  ],
});

壳应用的App.jsx

import React from "react";
import ReactDOM from "react-dom";
import MyComponent from "section/MyComponent"

const App = () => (
 
    <MyComponent />
  
);
ReactDOM.render(<App />, document.getElementById("app"));

解决方案

错误核心是Vue组件不能直接在React中当作React组件渲染:Vue组件输出的是Vue实例选项对象,而React期望接收符合React规范的组件(字符串/类/函数)。需要通过适配层将Vue组件包装为React可识别的组件。

步骤1:在Vue远程应用中导出适配后的组件

在SectionPart项目中创建包装文件src/exposes/MyComponentWrapper.js:

import Vue from 'vue';
import MyComponent from '../components/MyComponent.vue';

// 导出Vue组件选项,供React侧包装使用
export default MyComponent;

修改SectionPart的webpack.config.js中exposes配置:

exposes: {
  "./MyComponent": "./src/exposes/MyComponentWrapper.js",
},

步骤2:在React壳应用中添加Vue到React的适配组件

在Micro-Shell-App中安装依赖(如果未安装):

npm install vue

创建React包装组件src/components/VueToReact.jsx:

import React, { useEffect, useRef } from 'react';
import Vue from 'vue';

export default function VueToReact({ component: VueComponent, ...props }) {
  const containerRef = useRef(null);
  const vueInstanceRef = useRef(null);

  useEffect(() => {
    if (!containerRef.current || !VueComponent) return;

    // 挂载Vue实例到容器
    vueInstanceRef.current = new Vue({
      el: containerRef.current,
      render: h => h(VueComponent, { props })
    });

    // 组件卸载时销毁Vue实例
    return () => {
      if (vueInstanceRef.current) {
        vueInstanceRef.current.$destroy();
        vueInstanceRef.current = null;
      }
    };
  }, [VueComponent, props]);

  return <div ref={containerRef} />;
}

步骤3:在React壳应用中使用适配后的组件

修改App.jsx:

import React from "react";
import ReactDOM from "react-dom";
import VueToReact from './components/VueToReact';
import MyComponent from "section/MyComponent"

const App = () => (
    <VueToReact component={MyComponent} />
);
ReactDOM.render(<App />, document.getElementById("app"));

额外注意事项

  • 确保两个应用的Vue版本一致,避免冲突。可以在shared配置中共享Vue:
    在SectionPart的webpack.config.js的shared中添加:
    shared: {
      ...require("./package.json").dependencies,
      vue: { singleton: true, requiredVersion: require("./package.json").dependencies.vue }
    }
    
    在React壳应用的webpack.config.js的shared中添加:
    shared: {
      ...deps,
      react: { singleton: true, requiredVersion: deps.react },
      "react-dom": { singleton: true, requiredVersion: deps["react-dom"] },
      vue: { singleton: true, requiredVersion: deps.vue }
    }
    
  • 重启两个应用的开发服务器,确保webpack重新编译。

内容的提问来源于stack exchange,提问作者Emre Sert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:55:37