小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
导读
填坑文,本文主要是填《【微前端】Qiankun 其实是一个项目重构的利器》里留的坑。因为 Qiankun 要求微应用修改自己 router 的 base,来达到 url 隔离的目的。这就造成使用微应用 router 的方法无法跳回主应用,也就无法直接跳到其他微应用。那么如何解决呢?
正文
解决跳转问题有两种方案,第一种比较简单,直接用 location.href 等方法进行 url 跳转即可。但是这个方案的缺点非常明显,那就是在跳转的时候会“白屏”,这就意味着废了大力气引入了微前端,得到的效果跟用 url 隔离一样(详见《【微前端】Qiankun 其实是一个项目重构的利器》一文背景部分的方案)。所以明显是不可取的。
(2021.11.04 补充,发现了一个更轻量的解决方法,直接调用 window.history.pushState 即可,当然,前提是路由系统底层用的是 history 模式)
第二种方案,也就是正式方案说穿了也很简单。在《重构的利器》一文中已经埋下了伏笔。截取一段多实例模式下的代码大家就了然了:
// 主应用
const microAppContainer = useRef(null);
const history = useHistory();
useEffect(() => {
let mainApp;
if (microAppContainer.current) {
// 手动加载微应用
mainApp = loadMicroApp({
name: "vue3 ts app",
entry: "//localhost:8081",
container: microAppContainer.current,
/* 将路由注入子应用 */
props: { mainAppRouter: history },
});
}
return () => {
// 别忘了卸载
mainApp.unmount();
};
}, []);
没错,把主应用的 history 以 props 的形式传给子应用即可,接下来子应用需要做的就是把它提供给全局使用。此处采用 Vue3 的语法来实现,如下:
// 入口改造
function render(props) {
const { container, maiAppRouter } = props;
app = createApp(App);
if (maiAppRouter) {
/* 用 provide 挂到全局 */
app.provide("maiAppRouter", maiAppRouter);
}
instance = app
.use(store)
.use(router)
.mount(container ? container.querySelector("#app") : "#app");
}
// 组件使用
import { inject } from "vue";
const mainAppRouter = inject("maiAppRouter");
mainAppRouter.push('/'); // 等于 history.push('/')
单实例模式的改造就显而易见了。在子应用中没有任何差别,只是在主应用注册时传入 props 即可,不过因为 useHistory 必须在 React 组件中调用,所以需要换一下,如下:
/* 不能有 hooks,用 createBrowserHistory 替换 */
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
// 注册微任务
registerMicroApps([
{
name: "vue2 app", // app name registered
entry: "//localhost:8080",
container: "#vue2Container",
activeRule: "/app-vue",
props: { mainAppRouter: history },
},
]);
最后再附上 Vue2 版本的初始化 provide 代码:
instance = new Vue({
router,
store,
provide: { mainAppRouter }, // 初始化时直接挂载到实例
render: (h) => h(App),
}).$mount(container ? container.querySelector("#app") : "#app");
结语
微前端的坑终于填完了。目前还没有在项目中使用,但是相信很快就会有实践机会了,因为有个老系统需要重构,到时候应该还会遇到一些坑。到时候再补充吧。
当你感觉需要撰写注释,请先尝试重构,试着让所有注释都变得多余。——Martin Fowler