如何通过Vite Plugin Federation共享Redux Toolkit Store?问题排查
微前端共享Redux Toolkit Store问题排查与方案探讨
问题概述
尝试通过Vite Plugin Federation实现微前端架构下Redux Toolkit Store的跨应用共享,已搭建host、remote、store三个独立项目并完成配置,但运行remote项目时抛出错误:
TypeError: Cannot destructure property 'store' of 'useReduxContext$1(...)' as it is null.
相关配置与代码
host项目 vite.config.js
import federation from '@originjs/vite-plugin-federation' import react from '@vitejs/plugin-react' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ react(), federation({ name: 'app', remotes: { remoteApp: 'http://localhost:5001/assets/remoteEntry.js', store: 'http://localhost:5002/assets/remoteEntry.js', }, shared: ['react', 'react-dom'], }), ], build: { modulePreload: false, target: 'esnext', minify: false, cssCodeSplit: false, }, })
remote项目 vite.config.js
import federation from '@originjs/vite-plugin-federation' import react from '@vitejs/plugin-react' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ react(), federation({ name: 'remote_app', filename: 'remoteEntry.js', remotes: { store: 'http://localhost:5002/assets/remoteEntry.js', }, exposes: { './Button': './src/Button', }, shared: ['react', 'react-dom'], }), ], build: { modulePreload: false, target: 'esnext', minify: false, cssCodeSplit: false, }, })
store项目 vite.config.js
import federation from '@originjs/vite-plugin-federation' import react from '@vitejs/plugin-react' import { defineConfig } from 'vite' export default defineConfig({ plugins: [ react(), federation({ name: 'store', filename: 'remoteEntry.js', exposes: { './store': './src/store', }, shared: ['react', 'react-dom'], }), ], build: { modulePreload: false, target: 'esnext', minify: false, cssCodeSplit: false, }, })
store项目 src/store.js
import { configureStore, createSlice } from '@reduxjs/toolkit' import { Provider, useDispatch, useSelector } from 'react-redux' export const counterSlice = createSlice({ name: 'counter', initialState: { count: 0, }, reducers: { increment: state => { state.count += 1 }, clear: state => { state.count = 0 }, }, }) const { increment, clear } = counterSlice.actions const store = configureStore({ reducer: { counter: counterSlice.reducer, }, }) export function useStore() { const count = useSelector(state => state.counter.count) const dispatch = useDispatch() return { count, increment: () => dispatch(increment()), clear: () => dispatch(clear()), } } // eslint-disable-next-line react/prop-types export function StoreProvider({ children }) { return <Provider store={store}>{children}</Provider> }
remote项目 src/main.jsx
import React from 'react' import ReactDOM from 'react-dom/client' import { StoreProvider } from 'store/store' import App from './App.jsx' import './index.css' ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <StoreProvider> <App /> </StoreProvider> </React.StrictMode> )
remote项目 src/Button.jsx
import { useStore } from 'store/store' export const Button = () => { const { count, increment } = useStore() return ( <div> <button className='shared-btn' onClick={increment}> Click me: {count} </button> </div> ) } export default Button
完整错误信息
TypeError: Cannot destructure property 'store' of 'useReduxContext$1(...)' as it is null. at useSelector (__federation_expose_Store-6073bd77.js:1385:7) at useStore (__federation_expose_Store-6073bd77.js:1786:17) at Button (__federation_expose_Button-064de5a1.js:103:32) at Xh (__federation_shared_react-dom.js:202:137) at Wk (__federation_shared_react-dom.js:325:339) at Vk (__federation_shared_react-dom.js:315:393) at Uk (__federation_shared_react-dom.js:315:322) at Jk (__federation_shared_react-dom.js:315:181) at Ok (__federation_shared_react-dom.js:306:88) at Hk (__federation_shared_react-dom.js:303:432)
错误原因分析
核心问题是Redux上下文未在跨应用共享时正确互通:
useSelector和useDispatch钩子依赖Redux的Provider上下文,但当前三个项目的react-redux和@reduxjs/toolkit未配置为共享依赖,导致每个项目使用各自的库实例- remote项目中引入的
useStore来自store项目的远程模块,其依赖的react-redux实例与remote本地的实例不一致,上下文无法传递,最终触发useReduxContext返回null的错误
方案可行性与修复步骤
可行性判断
该方案完全可行,仅需修正依赖共享配置即可实现跨应用Redux Store共享。
修复步骤
- 共享状态管理依赖:在三个项目的
vite.config.js的shared配置中添加react-redux和@reduxjs/toolkit,确保所有应用使用同一库实例:
shared: ['react', 'react-dom', 'react-redux', '@reduxjs/toolkit']
- 验证上下文覆盖:确保remote项目的
StoreProvider包裹整个应用(当前代码已满足) - 确认单例Store:store项目中已导出单例store,无需额外修改
替代状态管理器与微前端状态共享方案
如果不想使用Redux Toolkit,可选择更适合微前端的轻量方案:
- Zustand:无需Provider,直接导出全局store实例,跨应用引入即可共享状态
- Jotai:原子化状态管理,通过导出原子对象实现跨应用共享
- 自定义全局状态容器:基于
EventEmitter实现状态变更通知,适合简单场景,无需引入第三方库
内容的提问来源于stack exchange,提问作者1mpos
相关产品推荐
相关产品推荐

