无宿主控制权下用Module Federation加载双版本React方案问询
解决Module Federation插件中React 17/18版本共存问题
核心思路
通过插件侧的Module Federation配置,将宿主的React 17映射为独立别名(如react-shared),与插件自身的React 18完全隔离:宿主渲染的入口组件使用宿主提供的React 17,插件内部业务组件则使用自身的React 18,互不干扰。
1. 配置插件的Webpack Module Federation
修改插件的webpack.config.js,在ModuleFederationPlugin中添加以下配置:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); module.exports = { // ...其他配置 plugins: [ new ModuleFederationPlugin({ name: 'yourPlugin', // 插件的唯一标识 filename: 'remoteEntry.js', exposes: { './PluginEntry': './src/PluginEntry' // 暴露给宿主的入口组件 }, remotes: { // 将宿主的React 17及其相关包映射为独立别名 'react-shared': 'hostName/react', // hostName替换为宿主的Module Federation名称 'react-dom-shared': 'hostName/react-dom', 'react-shared/jsx-runtime': 'hostName/react/jsx-runtime', 'react-shared/jsx-dev-runtime': 'hostName/react/jsx-dev-runtime' }, shared: { // 声明插件自身的React 18为共享依赖,禁用单例模式避免强制使用宿主版本 react: { singleton: false, version: require('./package.json').dependencies.react, requiredVersion: '^18.0.0' }, 'react-dom': { singleton: false, version: require('./package.json').dependencies['react-dom'], requiredVersion: '^18.0.0' } } }) ] };
2. 编写插件入口组件
在PluginEntry.js中,明确区分宿主的React 17(react-shared)和插件的React 18:
/** @jsxImportSource react-shared */ // 强制使用宿主的React 17编译JSX import React from 'react-shared'; import { useEffect } from 'react-shared'; // 导入插件自身的React 18的react-dom import { createRoot } from 'react-dom/client'; // 内部业务组件,使用React 18 import PluginApp from './PluginApp'; export default function PluginEntry() { useEffect(() => { const container = document.getElementById('plugin-root'); const root = createRoot(container); root.render(<PluginApp />); return () => root.unmount(); }, []); return <div id="plugin-root"></div>; }
关键注意事项
- 宿主必须暴露React依赖:确保宿主的Module Federation配置中已将
react、react-dom、react/jsx-runtime、react/jsx-dev-runtime加入exposes或shared(通常宿主会将React作为共享依赖暴露)。 - 禁用单例模式:插件侧
shared配置中singleton: false是核心,否则Webpack会强制使用宿主的React 17覆盖插件的React 18。 - JSX编译隔离:通过
@jsxImportSource react-shared注释,确保入口组件的JSX使用宿主的React 17编译,避免版本冲突导致的渲染错误。
内容的提问来源于stack exchange,提问作者mdarwi
相关产品推荐
相关产品推荐

