一种相互独立的前端应用程序组成一个更大的应用程序的架构风格。
如何让这些独立的前端应用程序组成一个整体?
大概有5种方式来做集成:
根据请求的路由不同,在服务端组合模版、返回html资源到客户端。
此时把各子应用程序作为一个包。主应用把它们作为依赖。打包主应用后,便能得到完整的应用程序。
其实这种方式可以算作是微前端的前身,iframe天然具有样式隔离、运行时隔离的特性。但iframe方式在交互、路由管理方面是有劣势的。
这种方式,把子应用的js入口文件引入到主应用,并暴露一系列声明周期函数让主应用去控制。这也是目前主流的集成方式。single-spa和基于single-spa的qiankun都是这种方式。
<html>
<head>
<title>Feed me!</title>
</head>
<body>
<h1>Welcome to Feed me!</h1>
<!-- 暴露生命周期函数 -->
<script src="https://browse.example.com/bundle.js"></script>
<script src="https://order.example.com/bundle.js"></script>
<script src="https://profile.example.com/bundle.js"></script>
<div id="micro-frontend-root"></div>
<script type="text/javascript">
// 路由和入口函数的映射
const microFrontendsByRoute = {
'/': window.renderBrowseRestaurants,
'/order-food': window.renderOrderFood,
'/user-profile': window.renderUserProfile,
};
const renderFunction = microFrontendsByRoute[window.location.pathname];
// 适时渲染特定的子应用到容器
renderFunction('micro-frontend-root');
</script>
</body>
</html>
这种方式把微应用作为一个自定义元素,需要把自定义元素的js定义引入。无需暴露生命周期函数,把微应用元素作为普通元素去操作。 MicroApp 是基于这种方式。
<html>
<head>
<title>Feed me!</title>
</head>
<body>
<h1>Welcome to Feed me!</h1>
<!-- 每个js文件和自定义元素关联 -->
<script src="https://browse.example.com/bundle.js"></script>
<script src="https://order.example.com/bundle.js"></script>
<script src="https://profile.example.com/bundle.js"></script>
<div id="micro-frontend-root"></div>
<script type="text/javascript">
// 路由和自定元素的映射
const webComponentsByRoute = {
'/': 'micro-frontend-browse-restaurants',
'/order-food': 'micro-frontend-order-food',
'/user-profile': 'micro-frontend-user-profile',
};
const webComponentType = webComponentsByRoute[window.location.pathname];
//适时将自定义元素渲染到容器
const root = document.getElementById('micro-frontend-root');
const webComponent = document.createElement(webComponentType);
root.appendChild(webComponent);
</script>
</body>
</html>
css天生就是全局的,行内样式又会让页面结构和表现混合。为了解决样式隔离的问题,社区想出了各种方式。这些方式都适用于微前端架构。
除了这些通用的解决方案,微前端架构还可以通过在主应用改写所有子应用的样式。比如子应用的所有类名加个属性选择器来做区分。qiankun就是这样做的。
div[data-qiankun="0000000000000000000"]{
color: red;
}