探索微前端之体验一下single-spa

前言

众所周知,微前端方案中的qiankun是基于single-spa的,而single-spa是基于systemJs的,上文我们已经聊过systemJS了,并且简单实现了下核心的加载功能。那么现在就该到single-spa了,可以说只要了解了single-spa,那么微前端思想就基本通了,而qiankun只是在single-spa上层做了些功能的拓展,比如预加载,沙箱等。

那么好,我们开始进入正题吧。

single-spa

single-spa是什么,这个不用过多介绍,一个微前端库。

那single-spa如何使用呢,以及它如何运行的呢?我们直接着手体验一下就好了。

使用

  • 全局安装
lua 复制代码
npm install create-single-spa -g
  • 创建基座
lua 复制代码
create-single-spa xxx
  • 打开基座项目

入口代码:

看过上一篇关于systemJS的jym应该会觉得非常熟悉,这部分的代码和systemJS的入口文件长得非常像了,毕竟single-spa是基于systemJS的。

应用代码:

结合入口和应用的代码,整个single-spa跑起来逻辑如下("start": "webpack serve --port 9000 --env isLocal"):

执行start命令,访问localhost:9000

根应用 -> index.ejs -> @rippi/root-config -> rippi-root-config.js -> 匹配activeWhen

现在我们就能看到基座页面了。接下来我们创建子应用。

  • 创建子应用

直接采用single-spa提供的命令方式去创建,也可以自己创建项目,按照文档进行配置,最后接入协议即可。

  • 打开子应用

从目录就能看出来基座和子应用的区别,少了一个index.ejs但多了自己项目的内容文件,如root.component和root.component.test。

root.component:

root.component.test:

从文件内容上来看,他们的入口文件也是很不同的。

rippi-reactProject(这个文件名是基于创建子应用时填写的组织名和项目名的):

我们在图中,多次看到了export const { bootstrap, mount, unmount } = lifecycles;

这就是single-spa的接入协议,子应用必须向基座暴露出这bootstrap、mount和unmount这三个钩子,所以如果不通过single-spa提供的方式创建子应用,就要自行去实现这三个钩子,并暴露出去。

这三个钩子的具体作用就和他们的名字一样:

bootstrap:提供加载目标子应用的方法。

mount:提供挂载目标子应用的方法。

unmount:提供卸载目标子应用的方法。

  • 子应用的命令

命令也大不相同,子应用有这两种玩法,一种是独立起起来,执行start:standalone,另一种是作为子应用让基座加载,那就执行start。

那么我们就来分别执行这两种命令。

1、npm run start:standalone

独立起来就比较普通,就是项目本身的内容,没有什么特别的地方。我们重点关注start命令。

2、npm run start

如图所示,跑起来的这个页面给出了我们很多提示,一个是说明了本项目的访问地址,另一个是让我们去基座那里注册我们这个子应用。

我们先来访问下这个地址。

熟悉的配方了,完全符合systemJS规范的代码。

  • 在基座中注册子应用

在rippi-root-config.js(这个文件名是single-spa依据大家的组织名)中添加一个registerApplication。

在index.ejs中加入@rippi/reactProject的地址。

由于基座中没装react和reactdom,但single-spa默认认为这些为公共资源,所以需要删一下子应用的配置。

在子应用的webpack.config中删掉externals配置。

这里选择了最省事的方法进行删除。

  • 效果

最后的效果是,子应用起在了8080端口,但访问9000端口(基座)的/react能看到子应用,这就是注册成功了。

基于以上步骤,大家可以自行创建更多的子应用进行更多的体验,篇幅原因,这里就不进行第二个子应用的创建了。

简化

上面我们体验了下single-spa的基本使用,不过框架、打包等部分使得整个例子有点臃肿了,不好看出太多的东西,我们这里就来简化下,去掉框架和打包等东西。

  • 以一个简单的html作为基座,注册两个没有dom结构的子应用,极致的简化例子。
html 复制代码
<body>
  <script src="https://cdn.bootcdn.net/ajax/libs/single-spa/5.9.3/umd/single-spa.min.js"></script>

  <script>
    const { registerApplication, start } = singleSpa;
    console.log(singleSpa);
    const appA = {
      bootstrap: async () => {
        console.log('app1 bootstrap');
      },
      mount: async () => {
        console.log('app1 mount');
      },
      unmount: async () => {
        console.log('app1 unmount');
      }
    };
    const appB = {
      bootstrap: async () => {
        console.log('app2 bootstrap');
      },
      mount: async () => {
        console.log('app2 mount');
      },
      unmount: async () => {
        console.log('app2 unmount');
      }
    };

    registerApplication('a', async () => appA, (location) => location.hash.startsWith('#/a'));
    registerApplication('b', async () => appB, (location) => location.hash.startsWith('#/b'));

    start();
  </script>
</body>

我们从single-spa那里引入了两个核心的api ------ registerApplication 和 start。

然后创建了两个子应用 ------ appA 和 appB。

这两个子应用分别暴露了bootstrap、mount和unmount钩子。

然后调用registerApplication进行注册。

最后将基座启动。

  • 效果

打印了single-spa,了解下single-spa提供的方法。

访问a应用:

访问b应用:

再次访问a应用:

经过这个简化的例子,更清楚了解single-spa了。

一般来说通过基座来加载子应用,子应用要接入协议,在mount中进行挂载逻辑(如reactDOM的createRoot),在unmount中进行卸载逻辑。

基座基本就只是一个管理的作用,根据路由和子应用的匹配规则(registerApplication的第三个参数)进行子应用的切换(也就是执行相应的bootstrap、mount、unmount)。

那么就可以洞悉出来这两个主要的方法都大概做了什么。

registerApplication:注册子应用,记录匹配规则和子应用的接入协议以及子应用名。

start:通过当前路由和已注册的子应用的匹配规则进行匹配,然后调用相应的方法。

结尾

到此,本文的所有内容就结束了,不过single-spa的内容并没有结束,本文只是体验了下single-spa,并通过一个极简的例子说明single-spa核心的registerApplication和start都做了些什么,让我们对single-spa有了更深一点的理解,基于这些理解或者说基础,我们将在下一篇文章中实现一个简单的single-spa,敬请期待。

相关推荐
玩电脑的辣条哥2 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452182 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52352 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
画月的亮2 小时前
element-ui 使用过程中遇到的一些问题及解决方法
javascript·vue.js·ui
Moon.92 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
m0_526119402 小时前
点击el-dialog弹框跳到其他页面浏览器的滚动条消失了多了 el-popup-parent--hidden
javascript·vue.js·elementui
垚垚 Securify 前沿站2 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
工业甲酰苯胺5 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
lyj1689975 小时前
el-tree选中数据重组成树
javascript·vue.js·elementui
mosquito_lover17 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt