微前端大赏二-singlespa实践
微前端大赏二-singlespa实践
序
介绍singleSpa
singleSpa是一个javascript库
它可以让很多小页面、小的组件、不通架构的前端组件在一个页面应用程序中共存。
这里有一个演示: (https://single-spa.surge.sh/)
这个库可以让你的应用可以使用多个不同的技术栈(vue、react、angular等等),这样我们就可以做同步开发,最后再使用一个公用的路由即可实现路由完美切换。也可以使用一样的技术栈,分不同的团队进行开发,只需要最后使用这个库把它们整合在一起,设置不用的路由名称就可以了。
优点:
敏捷
独立开发和更快的部署周期: 开发团队可以选择自己的技术并及时更新技术栈。 一旦完成其中一项就可以部署,而不必等待所有事情完毕。风险下降
降低错误和回归问题的风险,相互之间的依赖性急剧下降。更小单元
更简单快捷的测试,每一个小的变化不必再触碰整个应用程序。持续交付
更快交付客户价值,有助于持续集成、持续部署以及持续交付。
缺点:
- 配置复杂
singlespa相对来说配置复杂,当然我们还有更简单一点的qiankun,也可以基于singlespa封装一套更适合自己的框架。 - 一定的资源浪费
由于核心逻辑还是在于请求manifest,拿到js文件后执行渲染,这个过程不可避免会产生一些冗余,对于C端的应用来说,这个问题比较致命,当然,对于B端来说,这个是可以接受的,在可控制的范围之内
singleSpa核心逻辑
几张图可以解决singleSpa的核心逻辑
第一张图,很显然,第一步,在我们的webpack应用里生成一个manifest.json文件,这个文件内容差不多如下:
{
"files": {
"static/js/0.chunk.js": "/static/js/0.chunk.js",
"static/js/0.chunk.js.map": "/static/js/0.chunk.js.map",
"static/js/1.chunk.js": "/static/js/1.chunk.js",
"static/js/1.chunk.js.map": "/static/js/1.chunk.js.map",
"main.js": "/static/js/main.chunk.js",
"main.js.map": "/static/js/main.chunk.js.map",
"runtime-main.js": "/static/js/bundle.js",
"runtime-main.js.map": "/static/js/bundle.js.map",
"index.html": "/index.html",
"static/media/logo.svg": "/static/media/logo.103b5fa1.svg"
},
"entrypoints": [
"static/js/bundle.js",
"static/js/0.chunk.js",
"static/js/main.chunk.js"
]
}
关键点在 entrypoints 这个属性,我们可以通过manifest拿到项目的依赖表并可以使用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标签把它放到主应用上,进行渲染
至此我们就可以完全搞清楚,为什么singlespa这么神奇了,接下来让我们搭建一个简易版的singlespa
搭建环境
vue main
由于我们需要使用webpack配置,而最新版本的vue-cli默认只有babel,我们用这个步骤来安装一个vue版本的main
1、装包
npm install @vue/cli @vue/cli-init -g
2、创建一个项目
vue init webpack demo-single
3、cd demo-single
4、装包
npm i single-spa single-spa-vue axios --save
5、在src目录创建一个singlespa配置文件 single-spa-config.js
// single-spa-config.js
import * as singleSpa from 'single-spa'; //导入single-spa
import axios from 'axios' /*
runScript:
一个promise同步方法。可以代替创建一个script标签,然后加载服务
*/
const runScript = async (url) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = reject;
const firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);
});
}; const getManifest = (url, bundle) => new Promise(async (resolve) => {
const { data } = await axios.get(url);
// eslint-disable-next-line no-console
const { entrypoints } = data; for (let i = 0; i < entrypoints.length; i++) {
await runScript('http://127.0.0.1:3000/' + entrypoints[i]).then(() => {
if (i === entrypoints.length - 1) {
resolve()
}
})
}
}); singleSpa.registerApplication( //注册微前端服务
'singleDemoVue', async () => {
let singleVue = null;
await getManifest('http://127.0.0.1:3000/asset-manifest.json').then(() => {
singleVue = window.singleReact;
});
return singleVue;
},
location => location.pathname.startsWith('/react') // 配置前缀
); singleSpa.start(); // 启动
注: 可以看到,runScript就是个创建script标签的方法,getManifest是一个简单的获取manifest并创建script的方法
6、在main.js里引入这个文件
import './single-spa-config'
7、运行
npm run dev
最终得到这样一个工程
这样我们就完成了一个入口的配置,当然它还很简单,更复杂的操作我们应该放在具体的工程上去做
react child
上面的代码可以看到,我们register了一个react应用 http://127.0.0.1:3000/asset-manifest.json 并且访问了它的manifest文件,现在我们需要创建一个react子应用,也是直接通过几个步骤来完成,我们使用create-react-app来快速搭建:
1、装包
npm install create-react-app -g
2、创建
npx create-react-app my-app
3、创建完成后,注意我们需要对webpack做一点修改,默认create-react-app会有一个git本地分支,让我们先提交到本地仓库一下
git status
git add ./
git commit -m ttt
4、拿到webpack配置文件,create-react-app默认隐藏了webpack配置文件
yarn eject 或 npm run eject
5、修改webpack文件
修改 /config/webpack.config.js 在output增加:
output: {
... 这里忽略了原有的
library: 'singleReact',
libraryTarget: 'window'
}
修改 /scripts/start.js文件,在const devServer = new ...这个地方,增加一个header的设置:
const devServer = new WebpackDevServer(compiler, {
...serverConfig,
// 这里上增加的header设置
headers: {
'Access-Control-Allow-Origin': '*',
} });
6、修改src/index.js
一个是要把root改为动态渲染,一个是注册生命周期
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import singleSpaReact, {SingleSpaContext} from 'single-spa-react'; const rootComponent = () => {
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>
,
document.getElementById('react-root')
);
} // ReactDOM.render(
// ,
// document.getElementById('root')
// ); const reactLifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent,
errorBoundary(err, info, props) {
// https://reactjs.org/docs/error-boundaries.html
console.error(err)
return (
<div>This renders when a catastrophic error occurs</div>
);
},
});
export const bootstrap = reactLifecycles.bootstrap;
export const mount = reactLifecycles.mount;
export const unmount = reactLifecycles.unmount; // If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
7、运行
npm run start
8、在main的vue那里,访问/react 你会看到下面有一个react渲染和vue的一起出现,大功告成
生命周期
生命周期函数共有4个:bootstrap、mount、unmount、update。生命周期可以传入 返回Promise的函数也可以传入 返回Promise函数的数组。
引用一个大佬完整的说明, 非常的详细:
https://github.com/YataoZhang/my-single-spa/issues/4
结论
single spa可以给我们提供一整套方案,去搭建一套微前端集成框架,但它并不是一个开箱即用的封装,它有很多的坑等着我们去踩。
一般情况下,我们选择使用qiankun,它的封装程度更好,api更加友好一些。待积攒足够多的使用经验,可以考虑自研一套自己的微前端框架,增加整体的前端研发效率。
下节我将给大家带来qiankun对singlespa的封装,在具体应用中的实践。待完结框架篇后,我们可以再深入探究singlespa的实现原理以及各种概念。
参考文章
single-spa 文档: https://single-spa.js.org/docs/getting-started-overview/
微前端 single-spa: https://juejin.cn/post/6844903896884707342
这可能是你见过最完善的微前端解决方案!: https://www.infoq.cn/article/o6GxRD9iHQOplKICiDDU
single-spa微前端: http://www.soulapp.tech/2019/09/25/single-spa微前端/
Single-Spa + Vue Cli 微前端落地指南 (项目隔离远程加载,自动引入) : https://juejin.cn/post/6844904025565954055
微前端大赏二-singlespa实践的更多相关文章
- 微前端框架 single-spa 技术分析
在理解微前端技术原理中我们介绍了微前端的概念和核心技术原理.本篇我们结合目前业内主流的微前端实现 single-spa 来说明在生产实践中是如何实现微前端的. single-spa 的文档略显凌乱,概 ...
- 微前端框架single-spa初探
前言 最近入职的一家公司采用single-spa这个微前端框架,所以自学了此框架. single-spa这个微前端框架虽然有中文文档,但是有些零散和晦涩. 所以我想在学习之余,写篇博客拉平一下这个学习 ...
- 极致简洁的微前端框架-京东MicroApp开源了
前言 MicroApp是一款基于类WebComponent进行渲染的微前端框架,不同于目前流行的开源框架,它从组件化的思维实现微前端,旨在降低上手难度.提升工作效率.它是目前市面上接入微前端成本最低的 ...
- 微前端框架 之 qiankun 从入门到源码分析
封面 简介 从 single-spa 的缺陷讲起 -> qiankun 是如何从框架层面解决 single-spa 存在的问题 -> qiankun 源码解读,带你全方位刨析 qianku ...
- vivo 商品中台的可视化微前端实践
一.背景 在电商领域内,商品是一个重要组成部分,与其对应的商品管理系统,则负责商品的新建.编辑.复制等功能.随着商品管理系统的成熟稳定和业务上的扩展需求,催化出了商品中台的诞生.它可以将现有商品功能最 ...
- 基于微前端qiankun的多页签缓存方案实践
作者:vivo 互联网前端团队- Tang Xiao 本文梳理了基于阿里开源微前端框架qiankun,实现多页签及子应用缓存的方案,同时还类比了多个不同方案之间的区别及优劣势,为使用微前端进行多页签开 ...
- 前端微服务初试(singleSpa)
1.基本概念 实现一套微前端架构,可以把其分成四部分(参考:https://alili.tech/archive/11052bf4/) 加载器:也就是微前端架构的核心,主要用来调度子应用,决定何时展示 ...
- 微前端框架 single-spa
单体应用对比前端微服务化 普通的前端单体应用 微前端架构 1.基本概念 实现一套微前端架构,可以把其分成四部分(参考:https://alili.tech/archive/11052bf4/) 加载器 ...
- 微前端 & 微前端实践 & 微前端教程
微前端 & 微前端实践 & 微前端教程 微前端 micro frontends https://micro-frontends.org/ https://github.com/neul ...
随机推荐
- Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道
Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道 背景 上一讲我们介绍了创建子进程的方式.我们都知道,创建子进程是为了与父进程协作(或者是为了执行新的程序,参考 Linux ...
- P5530 [BOI 2002]双调路径
题意描述 [BOI 2002]双调路径 题意描述的确实不是很清楚(出题人惜字如金). 给定一张有 \(n\) 个点,\(m\) 条边的无向图,每条边有两个权值,分别表示经过这个点的代价和时间. 同时给 ...
- (二)http请求方法和状态码
1.HTTP请求方法 根据 HTTP 标准,HTTP 请求可以使用多种请求方法. HTTP1.0 定义了三种请求方法: GET.POST 和 HEAD方法. HTTP1.1 新增了六种请求方法:OPT ...
- dhcp、tftp、httpd、pxe安装CentOS6.9
虚拟机网络设置 要xshell连接虚拟机注意设置VMware Network Adapter VMnet2在同一网段 1.利用光盘配置本地yum源 [root@ZYB ~]# mount -r /de ...
- 【Kata Daily 190912】Alphabetical Addition(字母相加)
题目: Your task is to add up letters to one letter. The function will be given a variable amount of ar ...
- ERP的权限管理的操作与设计--开源软件诞生24
赤龙ERP用户与权限管理讲解--第24篇 用日志记录"开源软件"的诞生 [进入地址 点亮星星]----祈盼着一个鼓励 博主开源地址: 码云:https://gitee.com/re ...
- Cassandra数据模型和模式(Schema)的配置检查
免责声明 本文档提供了有关DataStax Enterprise(DSE)和Apache Cassandra的常规数据建模和架构配置建议.本文档需要DSE / Cassandra基本知识.它不能代替官 ...
- 手动实现简单的tomcat服务器
手动实现tomcat服务器的流程: 分析具体的实现步骤: 1,浏览器和后端服务如何实现通信,首先传输的数据要遵循http协议,通过tcp也就是我们常说的套接字编程来实现,具体的底层数据传输肯定就是我们 ...
- ClassNotFoundException: java.util.ArrayList$SubList 错误
ClassNotFoundException: java.util.ArrayList$SubListjava.lang.RuntimeException: java.lang.ClassNotFou ...
- fork函数拓展
1.fork之后父子进程共享文件:文件引用计数的值改变,共享偏移. 在下面的例子中test.txt为parentchil.如果子进程没有睡眠,两个进程交叉执行,内容不可预测. 1 #include&l ...