探索微前端之体验一下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,敬请期待。

相关推荐
文军的烹饪实验室20 分钟前
ValueError: Circular reference detected
开发语言·前端·javascript
Martin -Tang1 小时前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发1 小时前
解锁微前端的优秀库
前端
王解2 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录2 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁2 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂2 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐3 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成5 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽5 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习