我的GitHub
0%

无星的微前端之旅(二)—— qiankun的一些预知项

这里是一些很浅很浅的东西,大佬们不要喷我=。=。

qiankun将应用分为两种:主应用,微(子)应用

一.主应用是一个基座

主应用是一个基座,承载着各个子应用。

主应用负责各个应用之间的加载,通信和调度。

带🔥都说,这是微服务在前端的应用,不过我没做过服务端,对微服务不是很了解,因此不敢乱说。

我只做过客户端,从客户端的角度来看,这看上去就类似于iOS的组件化。将模块解耦后,通过主工程进行加载调用。这样一来有客户端背景的同学是不是就比较好理解了。

二.主应用通过注册好的配置表,去分别加载各自子应用的资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
{
// 子应用的名称,需要唯一
name: 'reactApp',
// 需要加载资源的地址
entry: '//localhost:3000',
// 用于替换dom的id
container: '#container',
// 激活规则
activeRule: '/app-react',
},
{
name: 'vueApp',
entry: '//localhost:8080',
container: '#container',
activeRule: '/app-vue',
},
{
name: 'angularApp',
entry: '//localhost:4200',
container: '#container',
activeRule: '/app-angular',
},
]);
// 启动 qiankun
start();

这里可以看到两步:注册,启动

换句话说,注册和启动是可以分开的。

并且本身手动加载loadMicroApp

这意味着,配置表可以从远端请求下来,进行动态修改,这就能做一些非常有意思的操作了[旺柴]:比如:无星的微前端之旅(四)——qiankun线上服务代理到本地

三.entry

entry虽然写的是一个地址,但实际上

指向的应该是具体的html!

指向的应该是具体的html!

指向的应该是具体的html!

重要的话说三遍

本地开发的时候,//localhost:3000 其实就是加载public文件夹中的html了。

而配置nginx上线的时候,一般都会加上

1
2
3
4
location / {
root xxxx/xxx/;
index index.html index.htm;
}

其实指向的就是html。

因为无论是开发还是打包,spa类型项目都是加载html,html再去加载js,然后再来接管前端路由的。

为什么要强调这个?

因为可能在某些场景下,不让配置nginx。

比如,将前端产物放到springboot的静态文件夹里上线,这种时候你可能就不知道这里填啥了,这里填子应用对应的html地址就行。

container

微应用的容器节点的选择器或者 Element 实例。

其dom节点内会被插入一个dom节点,用于展示子应用的html内容。

如下图,sub-apps是主应用提供的dom节点

1
2

这意味这,如果你的某些子应用是路由不敏感的,配合activeRule完全可以同屏展示。

同时,另一方面,一些需要通过cdn引入的资源依赖,只需要在主应用引入即可,子应用不需要再引入,比如阿里的iconfont等。

如果子应用有单独访问的需求,可以在script标签添加一个ignore属性。这样主应用访问的时候,就不会引入两次。公共依赖处理等,都可以使用这种方式,详细可以往下看五.公共依赖相关

activeRule

这就是子应用的激活规则。

别看大量的demo中这里填写的都是路由地址,你就认为这里写的是路由。

其实不然,它只表示激活规则,具体请看文档

这意味这,如果使用function,返回true,配合不同的container,就能同时激活两个子应用。

1
一般情况下,最佳实践,仍然是使用子应用的packagename作为前缀来制定路由激活规则,方便部署,也方便划分。

另外使用hash路由,需要注意,path前面需要加上#/,并且最好加上如下方法,而不要直接使用string

1
const getActiveRule = (hash) => (location) => location.hash.startsWith(hash);

例如,有个子应用使用hash路由,前缀为sub-login,则写法如下,以避免某些情况下路由正确却不激活子应用,文档

1
2
3
4
5
6
{
name: 'sub-login',
entry: '//xxx',
container: '#container',
activeRule: getActiveRule('#/sub-login'),
},

四.子应用的js加载后怎么执行的

请求到子应用以后,通过eval直接执行子应用代码。这个大家起一个子应用,然后打个断点,在浏览器中断点滚到最上面就能看到eval的包裹了。

五.公共依赖相关

其实在我司的项目中,并没有做对应处理,但是也了解了一下相关的。

首先说这种微前端的设计预期:既然最大的价值是技术栈无关,那么还要做公共依赖,自然是不符合原本的设计预期的。

当然,也不是不能做。

结合实现方式分析一下,主应用本身是基座,那么主应用的依赖,必定是全部会被加载的,那么公共依赖,应当是加载主应用的依赖以后,就不需要加载子应用的了。

所以如果有相同依赖的情况下,子应用只需要打包的时候剔除,在主应用加载子应用的时候,子应用其实就能读到相同依赖。

但是这时候需要考虑另一个问题:子应用独立运行访问。

考虑到上述html的加载,实际上是把子应用的html内容加载到主应用的容器节点下,那意味着,如果子应用使用script标签做cdn加载,就能在子应用独立访问时,能够获取到对应依赖。

但是这样,前面的剔除操作不就白做了吗?我们需要对cdn加载的script标签添加一个ignore属性,这样在主应用中,就依然不会加载该资源了。

来自issuse


沙箱和css隔离我暂时还没有用到,所以没有什么要写的。

我是阿星,阿星的阿,阿星的星!