Vue3+Webpack模块联邦:登录后加载微前端组件的方案问询
解决方案:延迟微前端 RemoteEntry 加载至登录后
核心思路
当前问题出在 Module Federation 的 remotes 配置中,Promise 会在主应用初始化时立即执行,导致 RemoteEntry 脚本提前加载。我们需要将 RemoteEntry 的加载逻辑与登录状态绑定,确保只有在拿到 Access Token 后才触发加载。
方案一:动态注册微前端(推荐,灵活性更高)
放弃在 Webpack 配置中提前声明 remotes,改为登录成功后手动注册微前端容器。
1. 修改 Webpack Module Federation 配置
new ModuleFederationPlugin({ name: 'my-app', filename: 'remoteEntry.js', remotes: {}, // 清空预配置的 remotes shared: [require('./package.json').dependencies], }),
2. 编写动态注册函数
// 动态加载并注册单个微前端 async function registerRemote(remoteName, remoteEntryUrl) { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = remoteEntryUrl; script.type = 'text/javascript'; script.onload = () => { // 初始化远程容器,同步共享依赖 window[remoteName].init(__webpack_share_scopes__.default); resolve(window[remoteName]); }; script.onerror = () => reject(new Error(`Failed to load ${remoteName} remote entry`)); document.head.appendChild(script); }); } // 登录成功后执行的逻辑 async function handlePostLogin() { // 假设已通过登录接口获取到 token 并存储 const token = await yourLoginApi(); localStorage.setItem('access_token', token); // 批量注册所有微前端 await Promise.all([ registerRemote('first_mfe', 'http://localhost:8000/remoteEntry.js'), registerRemote('second_mfe', 'http://localhost:8001/remoteEntry.js') ]); // 注册完成后跳转至主页面 router.push('/main'); }
3. 路由配置中延迟加载微前端组件
通过路由守卫拦截未登录状态,且微前端组件仅在注册后才动态导入:
const routes = [ { path: '/login', component: () => import('./views/Login.vue') }, { path: '/first-mfe', component: async () => { // 确保远程容器已注册 const remoteContainer = window.first_mfe; const { default: MfeComponent } = await remoteContainer.get('./App.vue'); return MfeComponent; }, beforeEnter: (to, from, next) => { // 路由守卫:未登录则跳转登录页 if (!localStorage.getItem('access_token')) { next('/login'); } else { next(); } } } ];
方案二:修改原有 Promise 逻辑,等待登录事件
基于你现有的代码改造,让 Promise 等待登录成功信号后再加载 RemoteEntry。
1. 修改 getUrl 函数
const getUrl = (resolve) => { // 加载 RemoteEntry 脚本的核心逻辑 const loadRemoteScript = () => { const script = document.createElement('script'); script.src = 'http://localhost:8000/remoteEntry.js'; // 根据微前端名称动态调整 script.type = 'text/javascript'; script.onload = () => { const module = { get: (request) => window.first_mfe.get(request), init: (arg) => { try { return window.first_mfe.init(arg); } catch (e) { console.log('Auth has already been loaded'); } }, }; resolve(module); }; document.head.appendChild(script); }; // 检查是否已登录 if (localStorage.getItem('access_token')) { loadRemoteScript(); } else { // 监听自定义登录成功事件 window.addEventListener('login-success', loadRemoteScript, { once: true }); } };
2. 登录成功后触发事件
async function login() { const token = await yourLoginApi(); localStorage.setItem('access_token', token); // 触发登录成功事件,通知加载 RemoteEntry window.dispatchEvent(new CustomEvent('login-success')); }
内容的提问来源于stack exchange,提问作者golia
相关产品推荐
相关产品推荐

