这才2月中旬,广州就已经渐渐地进入了夏季,——夏天总是让人焦虑的。过年闲暇时间写下了微前端这系列的终章,欢迎拍砖。如果你习惯直接上手代码,不妨跳到实践一节,直接上代码教程玩一玩。

qiankun原理和API介绍

qiankun是基于singlespa框架的一个上层应用,它提供了完整的生命周期,和一些钩子函数,通过路由匹配来动态加载注册微应用,同时提供了一系列api对微应用做管理和预加载等,它相对singlespa来说进步是比较大的。

所以---qiankun实质上是singlespa的一个封装,基于我们在上一节看到的,singlespa是通过输出一个manifest.json 通过标识入口信息动态构造script渲染实现的微前端应用,类似下面的图:

回顾一下singlespa在渲染过程中的核心逻辑
1、 首先我们有 main(主app) child(子app),主app只有一个,子app可以有多个
2、 其次,主app上一般我们可以在index.html里面,写多几个空间,也就是多几个div
例如:

<div id=”react-app”></div>
<div id=”vue-app”></div>

3、然后,在我们的child上,我们要用webpack插件,生成一个带有所有需要加载的依赖文件的manifest.json

4、主应用去加载这个manifest.json,获取到具体的js,使用script标签把它放到主应用上,进行渲染

在qiankun中对这套逻辑做了基本的封装, 让我们只需要经过简单的几个api就可以控制singlespa中比较复杂的配置和概念。

注册

import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'react app', // 应用名称
entry: '//localhost:7100', // 应用入口,应用需要增加cors选项
container: '#yourContainer', // 应用单独的appid的div
activeRule: '/yourActiveRule', // 匹配路由
},
{
name: 'vue app',
entry: { scripts: ['//localhost:7100/main.js'] },
container: '#yourContainer2',
activeRule: '/yourActiveRule2',
},
]);
start();

main

main是一个qiankun的主体部分,它也是不限制框架种类的,可以用react也可以用vue和angular,只需要在entry.js里面注册它就可以了。

一般情况下main的作用是存放公共代码,例如:
1、消息触发器
2、公共路由
3、权限触发器
4、存放例如全局管理、皮肤、用户管理等公共页面

你也可以把站点的首页写在这里,可以加快主体加载速度

生命周期

bootstrap

boostrap相当于init,子应用在第一次加载的时候会调用这个方法, 一般可以在里面做一些项目的初始化操作,例如

mount

每次在加载到子应用的时候都会调用它,就像是componentDidMount,一般情况下我们要把ReactDOM.render这样的初始化函数写在里面,每次mount时调用render

unmount

这个跟mount正好相反,每一次注销/切换子应用的时候会调用它,一般我们在这里 ReactDOM.unmountComponentAtNode 注销这个应用,然后把整个项目的容器让出来

update

这是个可选的生命周期,子应用发生变化的时候会调用。

路由匹配

路由规则有两种,需要手动调用对应的子应用渲染就行了,通过一个叫loadMicroApp的方法挂载一个子应用组件,这样就可以在main中像配置一个正常的应用那样配置子应用的view了。

import { loadMicroApp } from 'qiankun';
import React from 'react';
class App extends React.Component {
containerRef = React.createRef();
microApp = null;
componentDidMount() {
this.microApp = loadMicroApp(
{ name: 'app1', entry: '//localhost:1234', container: this.containerRef.current, props: { name: 'qiankun' } },
);
}
componentWillUnmount() {
this.microApp.unmount();
}
componentDidUpdate() {
this.microApp.update({ name: 'kuitos' });
}
render() {
return <div ref={this.containerRef}></div>;
}
}

处理样式

沙箱

qiankun的沙箱模式是在start的api配置项里面开启的

sandbox 选项可选

start({
sandbox: true // true | false | { strictStyleIsolation?: boolean, experimentalStyleIsolation?: boolean }
})

默认情况下沙箱可以确保单实例场景子应用之间的样式隔离,但是无法确保主应用跟子应用、或者多实例场景的子应用样式隔离。当配置为 { strictStyleIsolation: true } 时表示开启严格的样式隔离模式。这种模式下 qiankun 会为每个微应用的容器包裹上一个 shadow dom 节点,从而确保微应用的样式不会对全局造成影响。
shadow dom coco大神写过一篇文章介绍这个,我就不班门弄斧了
https://www.cnblogs.com/coco1s/p/5711795.html

样式冲突解决方案

qiankun 会自动隔离微应用之间的样式(开启沙箱的情况下),你可以通过手动的方式确保主应用与微应用之间的样式隔离。比如给主应用的所有样式添加一个前缀,或者假如你使用了 ant-design 这样的组件库,你可以通过这篇文档中的配置方式给主应用样式自动添加指定的前缀。

以 antd 为例:

配置 webpack 修改 less 变量

{
loader: 'less-loader',
+ options: {
+ modifyVars: {
+ '@ant-prefix': 'yourPrefix',
+ },
+ javascriptEnabled: true,
+ },
}

配置 antd ConfigProvider

import { ConfigProvider } from 'antd';
export const MyApp = () => (
<ConfigProvider prefixCls="yourPrefix">
<App />
</ConfigProvider>
);

webpack配置的问题

微应用的打包工具还需要增加如下配置:

  const packageName = require('./package.json').name;
module.exports = {
output: {
library: `${packageName}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${packageName}`,
},
};

qiankun实践-react微前端应用

起始,准备2个react应用

直接用create-react-app创建两个app应用

npx create-react-app main-app
npx create-react-app micro-app

可以得到一个文件夹里有两个项目

我们用main做主应用,micro做子应用,按照我们的api,子应用只需要配置一个register就可以引入子应用了
其中子应用需要调出webpack配置,create-react-app默认是不允许手动配置的,使用命令就可以了
进入micro-app的文件夹目录运行(create-react-app也有overload的办法更改配置,这里为了方便直接用命令调出来):

npm run eject

这样项目的准备工作就做好了。

子应用配置

配置子应用两个步骤,一个是生命周期的配置。 我们把生命周期函数写好放到main.js中:

然后我们把reactDom.render放到mount生命周期里调用,让qiankun在准备好加载mount的时候再去初始化应用:

unmount的注销操作也不能忘记:

我们更改一下子应用的根节点id,在父应用中再去引用它(不要忘了html里也需要更改):

最后再把webpack中的配置修改一下:
1、修改devserver支持cors 修改端口
headers: { 'Access-Control-Allow-Origin': '*', }


2、修改增加bundle的导出,在webpack.config.js增加配置:

父应用配置

然后我们就可以去在main应用中,注册了首先要

npm install qiankun --save

然后在main文件index.js中注册子应用:

别忘了我们还需要在public/index.html中写一个div容器,id是我们子应用的那个id,用来承载子应用的渲染:

然后我们就可以开始运行看一看了:

运行成功,随便改一下micro的样式看看效果:

接下来我们需要处理一下路由跳转的问题。

路由的处理实践

前文有提到,在react中使用qiankun可以使用apiloadMicroApp,这里我们也用它来处理路由的跳转。
我们主要是在main-app中操作:
首先新建micro-app的view文件(每多一个子应用就新建一个):

然后使用react-router直接配置:
由于create-react-app默认没有直接提供react-router,我们手动下一个

npm install react-router react-router-dom --save

改完index.js长这样:

再试一下:

大功告成!

结论和源码

相比较上一次我们看见的 singlespa的配置要简单了很多,而且更加直白,新增子应用更加无缝。
需要demo源码的同学私信我哦

应用场景和坑

坑-静态资源问题解决

微应用打包之后 css 中的字体文件和图片加载如果使用的加载路径是相对路径,会导致css 中的字体文件和图片加载 404。

而 css 文件一旦打包完成,就无法通过动态修改 publicPath 来修正其中的字体文件和背景图片的路径。

主要有三个解决方案:

  • 所有图片等静态资源上传至 cdn,css 中直接引用 cdn 地址(推荐)
  • 借助 webpack 的 url-loader 将字体文件和图片打包成 base64(适用于字体文件和图片体积小的项目)(推荐)
  • 使用绝对地址,nginx中设置静态目录

结束语

qiankun整体的思路是比较ok的,它大大简化了singlespa的使用逻辑,让微前端的门槛变得更低,但它仍然有一些缺点,例如部分api总是会有莫名其妙的问题,例如api文档不是特别的直观等,这些都是待改进的地方。而对于微前端来说,做到能够技术栈无关、渐进升级旧项目、分离不同业务等功能就已经能发挥它的最大价值了。

【微前端】微前端最终章-qiankun指南以及微前端整体探索的更多相关文章

  1. 初步认识微前端(single-spa 和 qiankun)

    初步认识微前端 微前端是什么 现在的前端应用,功能.交互日益复杂,若只由一个团队负责,随着时间的推进,会越来越庞大,愈发难以维护. 微前端这个名词,第一次提出是在2016年底.它将微服务(将单一应用程 ...

  2. 【使用指南】WijmoJS 前端开发工具包

    为方便广大前端开发人员更好的使用 WijmoJS 前端开发工具包,葡萄城专门推出了 WijmoJS 使用指南,该指南详细地介绍了如何把 WijmoJS 各种强大的功能应用到您自己的 Web 项目中,助 ...

  3. 零基础转行web前端,如何高效的去学习web前端

    web前端开发要学的知识内容涉及的会很宽泛,虽然说主要是HTML.CSS和JavaScript这些基础知识点,但学前端开发除了要学这些基础知识外,学员还要在这之上进行延伸和深入的去学,而且互联网时代不 ...

  4. web前端学习部落22群分享给需要前端练手项目

    前端学习还是很有趣的,可以较快的上手然后自己开发一些好玩的项目来练手,网上也可以一抓一大把关于前端开发的小项目,可是还是有新手在学习的时候不知道可以做什么,以及怎么做,因此,就整理了一些前端项目教程, ...

  5. Chris Richardson微服务翻译:重构单体服务为微服务

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服务部署 ...

  6. Web前端开发最佳实践(1):前端开发概述

    引言 我从07年开始进入博客园,从最开始阅读别人的文章到自己开始尝试表达一些自己对技术的看法.可以说,博客园是我参与技术讨论的一个主要的平台.在这其间,随着接触技术的广度和深度的增加,也写了一些得到了 ...

  7. Web前端开发最佳实践(2):前端代码重构

    前言 代码重构是业内经常讨论的一个热门话题,重构指的是在不改变代码外部行为的情况下进行源代码修改,所以重构之前需要考虑的是重构后如何才能保证外部行为不改变.对于后端代码来说,可以通过大量的自动化测试来 ...

  8. Web前端开发最佳实践(3):前端代码和资源的压缩与合并

    一般在网站发布时,会压缩前端HTML.CSS.JavaScript代码及用到的资源文件(主要是图片文件),目的是加快文件在网络中的传输,让网页更快的展现.当然,CDN分发.缓存等方式也是加快代码或资源 ...

  9. 前端MVC Vue2学习总结(八)——前端路由

    路由是根据不同的 url 地址展示不同的内容或页面,早期的路由都是后端直接根据 url 来 reload 页面实现的,即后端控制路由. 后来页面越来越复杂,服务器压力越来越大,随着AJAX(异步刷新技 ...

随机推荐

  1. Golang之如何(优雅的)比较两个未知结构的json

    这是之前遇到的一道面试题,后来也确实在工作中实际遇到了.于是记录一下,如何(优雅的)比较两个未知结构的json. 假设,现在有两个简单的json文件. { "id":1, &quo ...

  2. 网络地址转换(NAT)和默认路由

    我们要连接外网时,外网的网段很多很多,我们该如何愉快地连接外网?下面我们通过Cisco packet模拟环境,并了解NAT和默认路由的使用: NAT(Network Address Translati ...

  3. 真正云原生的智能运维体系,阿里云发布ECS自动化运维套件

    云计算的发展,推动了自动化运维.DevOps.AIOps 等趋势的兴起,在业务快速变化的今天,企业希望通过一套自动化运维的专家系统提高运维效率,为业务提供支撑. 传统的方式下,打造一套成熟的 DevO ...

  4. Watering Grass(贪心算法)

    给定一条草坪.草坪上有n个喷水装置.草坪长l米宽w米..n个装置都有每个装置的位置和喷水半径..要求出最少需要几个喷水装置才能喷满草坪..喷水装置都是装在草坪中间一条水平线上的. n sprinkle ...

  5. 2019牛客暑期多校训练营(第七场)E-Find the median(思维+树状数组+离散化+二分)

    >传送门< 题意:给n个操作,每次和 (1e9范围内)即往数组里面插所有 的所有数,求每次操作后的中位数思路:区间离散化然后二分答案,因为小于中位数的数字恰好有个,这显然具有单调性.那么问 ...

  6. hdu 4352 XHXJ's LIS(数位dp+状压)

    Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then carefull ...

  7. 2020牛客暑期多校训练营(第八场) Kabaleo Lite

    传送门:Kabaleo Lite 题意 有n道菜,1≤n≤105,a[i]是每道菜可以赚的钱,−109≤ ai ≤109,b[i]是这道菜的个数,1≤bi≤105,你每次只能选从1开始连续的菜,然后问 ...

  8. Traveling Salesman among Aerial Cities 旅行商(TSP)问题

    题目链接:点我 问题: 给你n个点的坐标(x,y,z).从点(a,b,c) 到另一个点 (p,q,r) 的距离是:|p−a|+|q−b|+max(0,r−c) 问你从一个点为起点,找一条能经过其他所有 ...

  9. HDU 2176 取(m堆)石子游戏 && HDU1850 Being a Good Boy in Spring Festivaly

    HDU2176题意: m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子. 通过 SG定理 我们可以知道每一个数的SG值,等于这个数到达不了的前面数 ...

  10. zoj3299 Fall the Brick

    Time Limit: 3 Seconds      Memory Limit: 32768 KB Now the God is very angry, so he wants to punish t ...