关于微前端:微前端选择qiankun还是iframe

前言微前端是什么?微前端是一种架构模式,将整个利用拆分成多个独立的模块,这些模块能够独立开发、部署。我在业务中遇到的2次都是先开发了多个小我的项目,而后这些小我的项目在业务上有肯定的分割,都属于同一类,产品就心愿能够聚合成一个大我的项目,有一个对立的入口。 技术选型技术选型大略有2种,一种是应用框架,比方qiankun、无界等,一种是应用iframe引入子项目。那如何抉择适宜本人我的项目的计划呢?这2种我都用过,应用之后的感触总的来说就是,优先思考iframe,如果iframe满足不了或满足起来比拟麻烦那就应用框架。 iframe的毛病: iframe性能耗费大,过多iframe会造成页面卡顿;子利用切换须要从新加载资源,慢;奴才页面通信艰难;cookie无奈跨域携带,子利用想应用主利用的登录信息麻烦;浏览器刷新,单页利用中url回到首页;毛病1,把子利用动静加载,每次只加载一个子利用。毛病2,不在乎切换子利用会从新加载。毛病3,须要通信的数据只有token,寄存在cookie中,奴才利用共享。权限判断在主利用中实现。毛病4,同3。毛病5,记录下url,刷新页面时先加载这个url对应的子利用; 总结综上所述,如果iframe的毛病无伤大雅那就应用iframe,否则应用框架。

September 11, 2023 · 1 min · jiezi

关于微前端:微前端下elementui弹框偏移问题解决

本章次要是解决无界微前端环境下element-ui弹框偏移问题,如果你用的是其余微前端框架,且提供了jsloader这种预处理器,则能够触类旁通解决同样的问题。首先,我应用的是无界官网源码,下载地址:无界微前端源码如图曾经下载到本地了:应用pnpm i装置一下依赖如果报错,请更新你的nvm或者应用16.19.0版本的node启动官网例子:npm run start,正确启动的话能够看到一下页面:点击进入vue2的dialog页面。咱们关上examples\vue2\src\main.js,在顶部任意中央退出: import Row from "element-ui/lib/row";import Col from "element-ui/lib/col";import "element-ui/lib/theme-chalk/row.css";import "element-ui/lib/theme-chalk/col.css";[Row, Col].forEach((element) => Vue.use(element));如图: 关上examples\vue2\src\views\Dialog.vue,写入代码: <template><a-button @click="fullDialogVisible = true" style="margin-left: 20px">点击关上全屏弹窗</a-button> <el-dialog title="全屏弹窗" fullscreen :visible.sync="fullDialogVisible" width="30%"> <el-row type="flex" justify="space-between"> <el-col :span="6" ><div class="grid-left"> <el-select v-model="value" placeholder="el-select"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select></div ></el-col> <el-col :span="6" ><div class="grid-center"> <el-select v-model="value" placeholder="el-select"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select></div ></el-col> <el-col :span="6" ><div class="grid-right"> <el-select v-model="value" placeholder="el-select"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select></div ></el-col> </el-row> <span slot="footer" class="dialog-footer"> <el-button @click="fullDialogVisible = false">取 消</el-button> <el-button type="primary" @click="fullDialogVisible = false">确 定</el-button> </span> </el-dialog></template><script>...data() { return { fullDialogVisible: false }}...</script>以上代码就是为了写一个弹框,且弹框内有左中右三个下拉框,来显示下拉框是否地位失常。5. 【全文重点】 关上examples\main-vue\src\views\Vue2-sub.vue此文件,写入: ...

August 29, 2023 · 1 min · jiezi

关于微前端:你想要的微前端都在这里了

作者:京东批发 郑炳懿 开篇: 如果你不晓得微前端是什么,或者不晓得微前端能解决什么问题,那么你可能不须要微前端。 在我看来,对于每一个没有应用过的新技术,都应该有以下几个过程: 1、调研该技术,产出相应的调研文档。 2、输入技术Demo,根本的框架结构。 3、试着在我的项目中应用它,这一步坑会很多。 4、把它推动到线上实现真正的技术升级。 一、调研微前端1.1 业务背景某次遇到一个从0到1的大型项目,该我的项目波及两个端,除了鉴权和局部业务逻辑不同外,页面UI和其余逻辑简直统一,遇到这种我的项目,该如何架构?既能保障我的项目顺利开发实现,又能保障前期的迭代、保护、可扩大? 1.2 初步计划首先,想到的技术计划有这么两种: 1、复用同一套代码,通过判断不同的权限,服务端下发标识,解决异同的业务逻辑。 2、开发两套代码,两套鉴权各走各的,页面雷同局部从右边Copy到左边。 其次,回过头来想了想,这两种计划都有缺点: 1、复用同一套代码,前期迭代的过程中,业务差别越来越大的时候,就会造成“屎山”。 2、开发两套代码,前期迭代的过程中,如果业务仍然高度类似,那么每次都要把A我的项目中的代码Copy到B我的项目中;如果业务逐步有了各自的格调,那么两套代码的计划显然是更佳的。 最初,除此之外,还有别的更好的计划吗? 1.3 什么是微前端?微前端的概念是由 ThoughtWorks 在2016年提出的,它是一种前端架构格调,将一个宏大的前端利用拆分成多个独立灵便的小型利用,每个利用都能够独立开发、独立运行、独立部署,再将这些小型利用交融为一个残缺的利用,或者将本来运行已久、没有关联的几个利用交融为一个利用。微前端既能够将多个我的项目交融为一,又能够缩小我的项目之间的耦合,进步开发效率和可维护性。微前端的外围在于解耦,通过拆分和集成来实现前端利用的可扩展性和灵活性。 图片来源于micro-app官网 二、初识微前端2.1 微前端能力1、独立开发:微前端能够将一个宏大的前端利用拆分成多个小型利用,每个利用都能够独立开发,不会影响其余利用的开发进度。 2、独立部署:每个小型利用都能够独立部署,不会影响其余利用的部署进度。这也意味着能够应用不同的技术栈、不同的部署形式、不同的版本控制工具等。 3、独立运行:每个小型利用都能够独立运行,不会影响其余利用的运行状态。这也意味着能够应用不同的框架、不同的库、不同的语言等。 4、集成灵便:微前端框架能够将多个小型利用集成为一个残缺的前端利用,或者将本来运行已久、没有关联的几个利用交融为一个利用。这也意味着能够依据须要动静地减少或删除利用。 5、解耦:微前端能够将前端利用拆分成多个小型利用,每个利用都有本人的职责和业务逻辑,能够缩小利用之间的耦合,进步可维护性和可扩展性。 6、增量降级:微前端能够实现增量降级,只须要降级须要更新的小型利用,而不须要降级整个前端利用。这能够缩小降级带来的危险和老本。 2.2 微前端外围1、拆分:将前端利用拆分成多个小型利用,每个利用都有本人的职责和业务逻辑。这样能够缩小利用之间的耦合,使得每个利用都能够独立开发、独立部署和独立运行。 2、集成:通过微前端框架将多个小型利用集成为一个残缺的前端利用。这样能够依据须要动静地减少或删除利用,实现灵便的集成。 3、通信:通过定义接口和事件等形式,实现小型利用之间的通信。这样能够保障各个利用之间的合作和交互,同时又不会影响利用之间的耦合。 4、款式隔离:通过应用款式隔离技术,使得每个小型利用都能够应用本人的款式,不会影响其余利用的款式。这样能够保障各个利用之间的款式不会相互烦扰,同时又不会影响利用之间的耦合。 总之,微前端的外围是解耦,通过拆分、集成、通信和款式隔离等形式,实现前端利用的解耦,进步可维护性和可扩展性。 2.3 微前端平台1、single-spa 是一个将多个单页面利用聚合为一个整体利用的 JavaScript 微前端框架。 2、qiankun 蚂蚁金服出品,基于 single-spa 封装的微前端框架。 3、MicroApp 京东出品,一款基于WebComponent的思维,轻量、高效、功能强大的微前端框架。 因为我的项目应用的 umi + react +ts 的技术栈,而 qiankun 天生就集成在 umi 框架中了,只须要一些配置就能够应用微前端技术,留神,我这里说的是一些配置,就是这一些配置,让我放弃了 qiankun 微前端框架,因为 single-spa 要求子利用批改渲染逻辑并暴露出三个办法:bootstrap、mount、unmount,别离对应初始化、渲染和卸载,这也导致子利用须要对入口文件进行批改。而 qiankun 是基于single-spa进行封装,所以这些特点也被 qiankun 继承下来,并且须要对 webpack 配置进行一些批改,老本绝对较高。 ...

May 4, 2023 · 2 min · jiezi

关于微前端:如何将微前端项目部署在同一台服务器同一个端口下

作者:京东科技 高飞 前言本文旨在通过部署微前端我的项目的实际过程中积淀出一套部署计划,现就一些重点步骤、碰到的问题做了一些总结。 部署程序因为线上部署主利用时须要用到子利用的线上可拜访地址,因而部署程序应该是先部署子利用,保障子利用可能线上可拜访后,再将子利用的线上可拜访地址配置到主利用,最初再将主利用部署到线上环境。 部署分支线上环境部署对立用master分支的代码 利用构建打包主利用构建打包主利用csd-tech-main-app基于ant-design-pro,须要在config目录中配置微前端我的项目的拜访地址。 在config目录下配置config.test.ts用于测试环境的打包配置,生产环境打包配置放在在config.prod.ts中。如果部署到测试环境,或者生产环境,能够换成对应的拜访地址。 测试环境打包配置:// config/config.test.ts 用于本地或者测试环境构建测试export default defineConfig({ define: { DATALINK_MICRO_APP_HOST: '/dlink/', // 本地环境调度零碎拜访地址 DATAX_MICRO_APP_HOST: '/dx2/', // 本地环境数据迁徙零碎拜访地址 LABEL_SYSTEM_MICRO_APP_HOST: '/ls/', // 本地环境标签零碎拜访地址 KINESISLINK_MICRO_APP_HOST: '/ksl/', // 本地环境监控零碎拜访地址 },});生产环境配置打包配置:// config/config.prod.ts 用于生产环境构建测试export default defineConfig({ define: { DATALINK_MICRO_APP_HOST: '/dlink/', // 本地环境调度零碎拜访地址 DATAX_MICRO_APP_HOST: '/dx2/', // 本地环境数据迁徙零碎拜访地址 LABEL_SYSTEM_MICRO_APP_HOST: '/ls/', // 本地环境标签零碎拜访地址 KINESISLINK_MICRO_APP_HOST: '/ksl/', // 本地环境监控零碎拜访地址 },});而后,咱们须要在微利用注册信息中,将咱们加载微利用的地址换成咱们配置的地址,代码实现如下: // src/app.tsxconst microAppsOptions = [ { name: 'datalink', entry: DATALINK_MICRO_APP_HOST, container: '#subapp-container', loader, activeRule: '/datalink', className: 'data-link-child-app', }, { name: 'datax', entry: DATAX_MICRO_APP_HOST, container: '#subapp-container', loader, activeRule: '/datax', className: 'datax-child-app', }, { name: 'subls', entry: LABEL_SYSTEM_MICRO_APP_HOST, container: '#subapp-container', loader, activeRule: '/subls', className: 'label-child-app', }, { name: 'subksl', entry: KINESISLINK_MICRO_APP_HOST, container: '#subapp-container', loader, activeRule: '/subksl', className: 'kinesislink-child-app', },];最初,咱们在 package.json 中,通过不同的命令辨别不同环境,代码实现如下: ...

April 11, 2023 · 3 min · jiezi

关于微前端:微前端项目部署方案

作者:京东科技 高飞 前言本文旨在通过部署微前端我的项目的实际过程中积淀出一套部署计划,针对我的项目别离部署在不同的服务器上的场景,就一些重点步骤、碰到的问题做了一些总结。 部署程序因为线上部署主利用时须要用到子利用的线上可拜访地址,因而部署程序应该是先部署子利用,保障子利用可能线上可拜访后,再将子利用的线上可拜访地址配置到主利用,最初再将主利用部署到线上环境。 部署分支线上环境部署对立用master分支的代码 利用构建打包主利用构建打包主利用csd-tech-main-app基于ant-design-pro,须要在config目录中配置微前端我的项目的拜访地址。 在config目录下配置config.test.ts用于测试环境的打包配置,生产环境打包配置放在在config.prod.ts中。因为本次部署是在本地机器测试部署,因而子利用拜访地址都用localhost,如果部署到测试环境,或者生产环境,能够换成对应的拜访地址。 测试环境打包配置:// config/config.test.ts 用于本地或者测试环境构建测试export default defineConfig({ define: { DATALINK_MICRO_APP_HOST: '//localhost:8888', // 本地环境调度零碎拜访地址 DATAX_MICRO_APP_HOST: '//localhost:9528', // 本地环境数据迁徙零碎拜访地址 LABEL_SYSTEM_MICRO_APP_HOST: '//localhost:8080', // 本地环境标签零碎拜访地址 KINESISLINK_MICRO_APP_HOST: '//localhost:6001', // 本地环境监控零碎拜访地址 },})生产环境打包配置:// config/config.prod.ts 用于生产环境构建测试export default defineConfig({ define: { DATALINK_MICRO_APP_HOST: 'xxxx', // 生产环境调度零碎拜访地址 DATAX_MICRO_APP_HOST: 'xxxx', // 生产环境数据迁徙零碎拜访地址 LABEL_SYSTEM_MICRO_APP_HOST: 'xxxx', // 生产环境标签零碎拜访地址 KINESISLINK_MICRO_APP_HOST: 'xxxx', // 生产环境监控零碎拜访地址 },});而后,咱们须要在微利用注册信息中,将咱们加载微利用的地址换成咱们配置的地址,代码实现如下: // src/app.tsxconst microAppsOptions = [ { name: 'datalink', entry: DATALINK_MICRO_APP_HOST, container: '#subapp-container', loader, activeRule: '/datalink', className: 'data-link-child-app', }, { name: 'datax', entry: DATAX_MICRO_APP_HOST, container: '#subapp-container', loader, activeRule: '/datax', className: 'datax-child-app', }, { name: 'label-system', entry: LABEL_SYSTEM_MICRO_APP_HOST, container: '#subapp-container', loader, activeRule: '/label-system', className: 'label-child-app', },];最初,咱们在package.json中,通过不同的命令辨别不同环境,代码实现如下: ...

April 10, 2023 · 4 min · jiezi

关于微前端:无界微前端环境中wangEditor-QuillEditor富文本编辑器无法正常使用问题解决

微前端环境中:问题: wangEditor: 无奈批改,且无奈粘贴复制QuillEditor:无奈应用工具栏,随便点击后,控制台报错对于wangEditor解决办法: plugins: [ { jsBeforeLoaders: [ { content: `window.Selection = window.parent.Selection`, }, ], jsLoader: (code) => { return code .replace("n.isCollapsed", "n.baseOffset === n.focusOffset") .replace("n.collapsed", "n.startOffset === n.endOffset"); }, }, ],具体原理:子利用运行在 iframe内,dom在主利用的shadowdom中,入选中文字时,在主利用监听selectionchange,并且通过 document.getSelection()获取选中的selection,在wangEditor中 会判断这个 selection instanceof window.Selection,很显著主利用的selection 不可能是 iframe 外面window Selection的实例,所以罗唆将主利用的 Selection赋值给 iframe 的 SelectionshadowDom 大坑,详见 stackoverflow,在shadowDom中 Selection.isCollapsed永远为true,相当于永远没有选中,所以只能批改 wangEditor 的代码,让读取 isCollapsed 批改成 baseOffset 和 focusOffset的比照,就晓得是否选中了文字了留神:n.isCollapsed 和 n.collapsed 相当于是做wangEditor 压缩代码的替换,具体代码在这个中央:

March 30, 2023 · 1 min · jiezi

关于微前端:微前端框架singlespa子应用加载解析

作者:京东物流 宁冲1 前言什么是微前端? 微前端是指存在于浏览器中的微服务。 本文次要通过对微前端框架single-spa的基座利用加载子利用的single-spa-vue函数库进行剖析,通过代码维度剖析让大家理解在single-spa加载子利用的时候都做了哪些事件。如何通过优化single-spa-vue函数库放弃子利用的状态。 因为是在代码维度进行剖析,要求读者对single-spa有肯定的理解,浏览成果会更好。 2 single-spa加载子利用的过程基座利用中配置的加载子利用配置,在配置子利用对象的app办法中会把子利用chunk-vendors.js、app.js插入到页面,并且执行chunk-vendors.js、app.js两个子利用依赖的js。 app办法执行完结当前,子利用依赖的js插入页面当前的dom构造。 由下面app办法的执行过程,咱们能够看出基座利用加载子利用,和vue框架打包后加载js资源的形式相似。那么为什么只须要加载子利用的app.js和chunk-vendors.js就能够把子利用渲染到页面下面。上面咱们再来看看子利用的入口文件main.js办法中是如何进行配置的。 3 子利用的main.js中的配置在子利用main.js中咱们能够看到,把惯例的配置1替换为配置2的格局。 在配置2中咱们会把以后vue的配置传给single-spa-vue函数库中。包含el、render办法、Vue对象。通过singleSpaVue的包装,返回single-spa生命周期办法bootstrap、mount、unmount。 bootstrap:疏导函数,利用内容首次挂载到页背后调用,只会执行一次。mount:挂载函数,子利用每次被挂载的时候都会执行。unmount:卸载函数,子利用每次被卸载的时候都会执行。也就是说基座利用在加载子利用的时候就是通过single-spa-vue函数的解决,生成了single-spa的各个生命周期,给基座利用在加载子利用的时候调用。 上面咱们来看看single-spa-vue到底是如何生成各种生命周期函数的。 4 single-spa-vue源码构造single-spa-vue函数库能够帮忙咱们来生成加载子利用的生命周期。你能够通过上面链接:single-spa-vue GIT地址,下载single-spa-vue函数库的源码。 single-spa-vue的源码非常简单,只有几个生成single-spa生命周期的函数。 single-spa-vue办法:single-spa-vue函数库对外提供服务的惟一一个办法,用来接管配置项,并且返回一个蕴含各个single-spa生命周期的对象。single-spa-vue中的其余办法bootstrap、mount、update、unmount是用来生成single-spa对应生命周期函数的办法。上面咱们具体介绍一下这几个办法的作用和实现。 5 single-spa-vue源码解析single-spa-vue中提供的singleSpaVue办法会接管userOpts配置信息,配置信息会和默认的配置项defaultOpts合并当前再进行进行后续解决。 5.1 配置项defaultOpts对于默认的配置项会有上面这几项,这里只介绍一下必填项,appOptions、Vue/createApp。其中的template在并没有在single-spa-vue中被用到,然而在single-spa-html中有应用到。 // 默认配置项列表const defaultOpts = {// required optsappOptions: null,template: null,// sometimes require optsVue: null,createApp: null,handleInstance: null}1)appOptions配置项介绍 appOptions:利用的配置项,会在初始化Vue实例的时候作为参数传给Vue办法,上面具体介绍一下appOptions中的配置项。el:子利用须要挂载的基座dom,即vue须要挂载的dom。render/template:vue的render/template配置项。data:初始化的参数对象,会在执行挂载函数mount的时候间接挂载到vue实例上。2)Vue/createApp配置项介绍 Vue/createApp配置项是用来生成vue实例的,single-spa-vue函数库能够通过传入的Vue对象在mount办法中来生成vue实例。也能够传入createApp办法,由子利用在createApp办法中返回vue实例。 上面咱们会在生命周期生成办法中看到这些配置项的作用 5.2 入口办法:singleSpaVuesingleSpaVue办法会对入参先进行下列有效性校验,具体校验的内容有一下四项。 配置项userOpts是否为对象。用来创立vue实例的配置Vue/createApp是否存在。用来生成vue实例的配置项appOptions是否存在。vue实例挂载的dom是否正确appOptions.el有效性校验。 有效性校验通过当前,会调用bootstrap、mount、unmount、update办法用来别离生成single-spa加载子利用的生命周期函数。 上面具体介绍一下各个生命周期函数是如何生成的。 5.3 疏导函数:bootstrap疏导函数bootstrap,当利用内容首次挂载到页背后调用。 bootstrap函数,会先判断一下是否在配置项中存在loadRootComponent。配置项loadRootComponent笔者了解是能够用来加载以后子利用依赖的父级利用或者其余的依赖资源。 比方A页面依赖B组件,那在加载A页面的时候能够loadRootComponent办法中把B组件的动态资源加载下来,并且渲染到页面上,A页面就能够间接应用B组件中提供的一些资源或者dom。 如果未配置loadRootComponent,则间接返回,不做任何解决。 5.4 子利用挂载生命周期:mount在子利用每次被挂载到页面上的时候,single-spa会执行mount生命周期函数,single-spa-vue在mount函数中用来初始化子利用的vue实例,并且把实例挂载到页面上。 mount函数会接管三个参数,别离是singleSpaVue传入的参数opts,single-spa-vue以后全局挂载的子利用实例列表mountedInstances,在基座利用中注册的以后子利用的single-spa实例props props入参接管的数据,这里只用到了props的name属性,用来标识以后挂载的子利用。 在mount办法中次要做了以下几件事 1)格式化利用配置项appOptions mount办法中会通过resolveAppOptions办法来格式化利用的配置项appOptions。 在resolveAppOptions办法来中如果appOptions是一个办法的话,则执行办法,并且传递基座利用通过customProps参数传入的参数props。 子利用能够在appOptions办法中获取父利用传递的参数、依据父利用的状态做不同的解决等。 2)初始化子利用须要挂载的DOM对象。 ...

March 28, 2023 · 1 min · jiezi

关于微前端:无界微前端子应用使用原生js绑定事件后获取etarget为null解决办法

当咱们应用微前端时候,不得不用原生js绑定事件,且要获取以后绑定事件的dom时候,发现没在微前端环境中e.targe是有值的,但放到微前端环境下e.target就成了null, 导致后续操作没法实现,影响应用,因而能够应用一下形式解决。问题:document.getElementById('rightMenu').onmouseleave = function (e) { console.log(e.target) // 在非微前端环境中打印成果为:以后绑定事件的dom // 在微前端环境中打印成果为: null}解决办法:document.getElementById('rightMenu').onmouseleave = function (e) { var composedTarget = (e.composed && e.composedPath()) var target = composedTarget[0] if (target) { // 你要解决的事件 } else { console.error('target没有获取到') } console.log(target) // 在非微前端环境中打印成果为:以后绑定事件的dom // 在微前端环境中打印成果为: 以后绑定事件的dom }如果你比拟仔细想辨别是否在微前端环境中,再应用不同的形式获取e.target的话,就按上面形式:找到以后微前端的shadowRoot(这里以无界微前端为例, 其余微前端环境:例如:乾坤,MicroApp) // 无界:window.__POWERED_BY_WUJIE__, 乾坤:window.__POWERED_BY_QIANKUN__, MicroApp: window.__MICRO_APP_ENVIRONMENT__if (window.__POWERED_BY_WUJIE__) { window.$wujie.shadowRoot.querySelector('#rightMenu').addEventListener('mouseleave', e => { var composedTarget = (e.composed && e.composedPath()) var target = composedTarget[0] if (target) { // 你要解决的事件 } else { console.error('target没有获取到') } })}

March 23, 2023 · 1 min · jiezi

关于微前端:无界微前端环境下MonacoEditor鼠标错误问题解决办法

在应用wujie微前端框架内的子利用MonacoEditor会呈现光标标谬误问题。起因是因为:MonacoEditor 的 document.caretRangeFromPoint 在无界中无奈兼容。MonacoEditor 其实曾经思考到了 shadowRoot 的状况,然而 MonacoEditor 和 无界没有兼容的中央在于 MonacoEditor 认为shadowRoot 肯定在 document.body 外部,而无界子利用 document.body 在 shadowRoot 外部导致 MonacoEditor 认为编辑器不在 shadowRoot内。因而解决办法:找到以下源码地位: 按以上内容批改即可。

February 17, 2023 · 1 min · jiezi

关于微前端:无界微前端作为子应用引入高德或百度地图removeChild报错问题解决

高德或者百度地图的外链script触发了高德地图的回调函数。回调函数里的有document.body.removeChild的逻辑,要删除高德的外链script。但在wujie插件中配不配置置jsIgnores,高德地图的回调函数removeChild都无奈删除呈现以上问题咱们能够应用一下办法解决: const { bus,setupApp,preloadApp,destroyApp ] = WujieVue;preloadApp({ name: 'vite', url: hostMap("vite"), exec: true, plugins:[ { jsIgnores: [/baidu/], // [/amap\.com/] // _element为真正插入的元素, _iframeWindow为子利用的window,rawElement为原始插入元素 appendOrInsertElementHook(_element: any, _iframeWindow: any, rawElement: any) { // 以下函数也能够用此行代替 _iframeWindow.document.body.removeChild=() => null if (rawElement) { Object.defineProperty(rawElement,'parentNode', { get: () => ({ removeChild: () => null }) }) } } } ]})同理也能够触类旁通遇到相似的问题,都能够通过此操作来避免报错如果下面的内容复制进页面后无奈起作用,可能是我拼写错误导致的,请仔细检查。

February 15, 2023 · 1 min · jiezi

关于微前端:为iframe正名你可能并不需要微前端

作者:刘显安(码怪) 任何新技术、新产品都是有肯定实用场景的,它可能在当下很风行,但它不肯定在任何时候都是最优解。前言最近几年微前端很火,火到有时候我的项目外面用到了iframe还要偷偷摸摸地藏起来惟恐被他人晓得了,因为放心被人质疑:你为什么不必微前端计划?直到最近笔者接手一个我的项目,须要将现有的一个零碎整体嵌入到另外一个零碎(一共20多个页面),在被微前端坑了几次之后,回过头发现,iframe真香! qiankun的作者有一篇《Why Not Iframe》 介绍了iframe的优缺点(不过作者还有一篇《你可能并不需要微前端》给微前端降降火),诚然iframe的确存在很多毛病,然而在抉择一个计划的时候还是要具体场景具体分析,它可能在当下很风行,但它不肯定在任何时候都是最优解:iframe的这些毛病对我来说是否可能承受?它的毛病是否有其它办法能够补救?应用它到底是利大于弊还是弊大于利?咱们须要在优缺点之间找到一个均衡。 优缺点剖析 iframe适宜的场景因为iframe的一些限度,局部场景并不适宜用iframe,比方像上面这种iframe只占据页面两头局部区域,因为父页面曾经有一个滚动条了,为了避免出现双滚动条,只能动静计算iframe的内容高度赋值给iframe,使得iframe高度齐全撑满,但这样带来的问题是弹窗很难解决,如果居中的话个别弹窗都绝对的是iframe内容高度而不是屏幕高度,从而导致弹窗可能看不见,如果固定弹窗top又会导致弹窗追随页面滚动,而且稍有不慎iframe内容高度计算有一点点偏差就会呈现双滚动条。 所以: 如果页面自身比较简单,是一个没有弹窗、浮层、高度也是固定的纯信息展现页的话,用iframe个别没什么问题;如果页面是蕴含弹窗、信息提醒、或者高度不是固定的话,须要看iframe是否占据了全副的内容区域,如果是像下图这种经典的导航+菜单+内容构造、并且整个内容区域都是iframe,那么能够放心大胆地尝试iframe,否则,须要慎重考虑计划选型。 为什么肯定要满足“iframe占据全部内容区域”这个条件呢?能够设想一下上面这种场景,滚动条呈现在页面两头应该大部分人都无奈承受: 实战:A零碎接入B零碎满足“iframe占据全部内容区域”条件的场景,iframe的几个毛病都比拟好解决。上面通过一个理论案例来具体介绍将一个线上在运行的零碎接入到另外一个零碎的全过程。以笔者前段时间刚实现的ACP(全称Alibaba.com Pay,阿里巴巴国内站旗下一站式寰球收款平台,下称A零碎)接入生意贷(下称B零碎)为例,已知: ACP和生意贷都是MPA页面;ACP零碎在此之前没有接入其余零碎的先例,生意贷是第一个;生意贷作为被接入零碎,本次须要接入的一共有20多个页面,且服务端蕴含大量业务逻辑以及跳转管制,有些页面想看看长什么样子都十分艰难,须要在Node层mock大量接口;接入时须要做性能删减,局部接口入参须要调整;生意贷除了接入到ACP零碎中,之前还接入过AMES零碎,本次接入须要兼容这部分历史逻辑;咱们心愿的成果: 假如咱们新增一个页面 /fin/base.html?entry=xxx 作为咱们A零碎承接B零碎的地址,A零碎有相似如下代码: class App extends React.Component { state = { currentEntry: decodeURIComponent(iutil.getParam('entry') || '') || '', }; render() { return <div> <iframe id="microFrontIframe" src={this.state.currentEntry}/> </div>; }}暗藏原零碎导航菜单因为是接入到另外一个零碎,所以须要将原零碎的菜单和导航等都通过一个相似“hideLayout”的参数去暗藏。 后退后退解决须要特地留神的是,iframe页面外部的跳转尽管不会让浏览器地址栏发生变化,然而却会产生一个看不见的“history记录”,也就是点击后退或后退按钮(history.forward()或history.back())能够让iframe页面也后退后退,然而地址栏无任何变动。 所以精确来说后退后退无需咱们做任何解决,咱们要做的就是让浏览器地址栏同步更新即可。 如果要禁用浏览器的上述默认行为,个别只能在iframe跳转时告诉父页面更新整个<iframe />DOM节点。URL的同步更新让URL同步更新须要解决2个问题,一个是什么时候去触发更新的动作,一个是URL更新的法则,即父页面的URL地址(A零碎)与iframe的URL地址(B零碎)映射关系的保护。 保障URL同步更新性能失常须要满足这3种状况: case1: 页面刷新,iframe可能加载正确页面;case2: 页面跳转,浏览器地址栏可能正确更新;case3: 点击浏览器的后退或后退,地址栏和iframe都可能同步变动;什么时候更新URL地址首先想到的必定是在iframe加载完发送一个告诉给父页面,父页面通过history.replaceState去更新URL。 为什么不是history.pushState呢?因为后面提到过,浏览器默认会产生一条历史记录,咱们只须要更新地址即可,如果用pushState会产生2条记录。B零碎: <script>var postMessage = function(type, data) { if (window.parent !== window) { window.parent.postMessage({ type: type, data: data, }, '*'); }}// 为了让URL地址尽早地更新,这段代码须要尽可能前置,例如能够间接放在document.head中postMessage('afterHistoryChange', { url: location.href });</script>A零碎: ...

January 5, 2023 · 4 min · jiezi

关于微前端:nuxt作为主应用接入qiankun的实践附代码

上半年始终在倒腾qiankun,在应用nuxtjs接入qiankun时遇到了一些坑,记录并分享进去,心愿能帮忙到大家。代码地址:nuxtjs-qiankun-demo Nuxtjs接入qiankun须要次要的事项:qiankun只能在客户端运行,所以须要将qiankun的逻辑放到一个只在客户端执行的plugin中: //nuxt.config.js plugins: [ '@/plugins/element-ui', { src: '@/plugins/qiankun', ssr: false }],能够通过自定义路由的形式增加子利用的路由: //nuxt.config.js router: { extendRoutes (routes, resolve) { routes.push({ path: '/vueSubApp', component: resolve(__dirname, 'components/pages/VueSubApp.vue'), children: [ { path: '*', component: resolve(__dirname, 'components/pages/VueSubApp.vue') } ] }) } },nuxtjs中的路由组件<nuxt/>是对vue-router中<router-view/>的封装:(最大的坑点) //packages/vue-app/template/components/nuxt-child.js<% if (features.transitions) { %> return h('transition', { props: transitionProps, on: listeners }, [routerView]) <% } else { %> return routerView <% } %>能够看到nuxt反对配置来给路由加载过渡成果,切默认mode为out-in,然而这个动画模式会导致子利用激活时无奈获取子利用加载的容器dom:Application died in status NOT_MOUNTED: Target container with #container not existed while xxx mounting! ...

November 30, 2022 · 1 min · jiezi

关于微前端:为什么-qiankun-不能和-vite-一起使用

qiankun 简介qiankun 是蚂蚁金服开源的欠缺的微前端解决方案,禁受过大量的线上零碎的考验及打磨,是国内使用率较高的微前端框架之一,它具备不限度技术栈、齐备的款式隔离、js 沙箱与资源预加载等特点,如其官网所说的一样: 可能是你见过最欠缺的微前端解决方案qiankun 为什么不能和 vite 一起应用?在 qiankun 官网上,能够找到如何疾速接入 qiankun 的教程,但仅有 webpack 的示例而没有 vite 的,根本原因在于 vite 与 qiankun 无奈很好的联合在一起,其起因次要有以下两方面: vite2 不反对 runtime publicPath,这项能力在 webpack 中由内置变量__webpack_public_path__提供,runtime publicPath是 qiankun 加载子利用的外围 (由 import-html-entry 模块提供) ,用于预加载及引入异步脚本esm 会使 qiankun 的 js 沙箱生效,qiankun 外部的 js 沙箱应用将 window 对象进行了代理,以避免全局作用域被净化,但 esm 模块始终具备本人独立的顶级作用域,也就是说它拜访到的 window 是全局作用域下的,而不是 qiankun 沙箱中提供的代理 window,尽管能够通过在生产环境打包为 umd 格局的形式来防止应用 esm,但有些轻重倒置了解决方案社区为了解决以上问题,社区中涌现出了诸如 vite-plugin-qiankun、vite-plugin-qiankunjs、vue-cli-plugin-vite-qiankun 等解决方案,以其中用户量最多的 vite-plugin-qiankun 来看,它对于以上两个问题的解决方案如下 将 base 写死以解决预加载及动静导入的问题,此计划治标不治本,只能通过给定的 base 拜访,子利用部署的一旦变动就须要进行更改提供 helper 裸露主利用传递的 代理 window 变量尝试针对 vite不反对 runtime publicPath的问题,我也曾试着去解决过,这就是 @sh-winter/vite-plugin-qiankun,此我的项目中,通过批改 vite2 中外部注入的 __VITE_ASSET__、__VITE_PRELOAD__标记,实现了 runtime publicPath,然而此形式侵入了 vite 的外部解决逻辑,随着 vite 的更新,随时可能会生效,所以不举荐应用 ...

November 3, 2022 · 1 min · jiezi

关于微前端:无界微服务框架子应用动态script加载的js无法访问到上一个js内的全局变量问题解决

无界前端微服务框架,子利用通过script加载的js,在加载实现后,又通过动静生成script标签形式加载的js无法访问到上一个js内的全局变量问题如下 如何解决把动静加载的这个js的script 的type 改成 type="text/module" 即可解决。既: var script=document.createElement('script’);script.setAttribute('type’,text/module')最终行程这种模式即可: <script src="xxx.js" type="text/module"></script>

October 26, 2022 · 1 min · jiezi

关于微前端:记一次微前端技术选型

我的项目背景:app下架须要把所有页面都迁徙到企业微信h5布局架构:主利用提供菜单组件和专用办法,而后微利用须要渲染到指定的容器。所以要求微前端框架提供隔离款式的性能、以及通信性能。只给了一个月来接入主利用和子利用。子利用须要推动各部门来配合接入,月初提需要,月底上线第一批利用技术选型规范基于工夫紧迫,须要筛选可用,且接入成本低,社区活跃度高,遇到问题能够找到对应的解决方案的微前端框架维度与评分 老本 接入老本(接入微前端框架要改变的货色)革新老本(基于这个微前端框架不反对的性能,须要本人实现的难度评估)收益 微前端运行时性能完整性微前端工程化微前端运维危险 社区活跃度(github star数量、已解决issue数量)可维护性(文档是否齐全、在技术社区是否能够找到对应的技术分享文章)可扩展性(随着越来越多的微利用接入,是否会导致治理上的不便)iframeiframe有人造的隔离性,然而隔离性太强,导致以下问题: 刷新后iframe的url状态失落,无法控制iframe页面的后退后退;想实现子利用免登录须要跨域共享cookie,反而导致安全性升高;全局弹窗无奈实现企业微信h5的iframe不反对跨域申请页面,详见这里因为 微前端运行时性能完整性 不能满足根本业务需要,间接放弃该计划。 single-spa性能上: 兼容多框架html entry加载和渲染原理:路由劫持,下载入口html,渲染到指标容器不反对js隔离、款式隔离不反对利用间通信不反对预加载没有思考微前端工程化和运维老本:接入老本: 子利用须要装置依赖,以及注册生命周期函数主利用须要本人编写加载子利用的逻辑革新老本: 须要本人实现js隔离、款式隔离须要本人实现预加载须要本人实现利用间通信危险: 社区活跃度 github star数量 11.3k、已解决issue数量 532(2022.6.27)文档齐全,demo多小结: 性能上,只做了路由劫持、提供参数填写加载微利用的逻辑。须要本人实现利用隔离、预加载和利用间通信。微前端运行时性能完整性 低,得1分。没有思考 微前端工程化 和 微前端运维 相干的性能。所以在收益这个维度,得分 1/9老本上,接入须要本人手写加载微利用的逻辑,且子利用须要额定装置依赖,接入老本高,得1分。须要本人实现利用隔离、通信、以及预加载等,革新老本高,得1分。所以在老本这个维度得分 2/6。社区活跃度高,可维护性高;qiankun性能上: 基于single-spa欠缺以下性能: a. 利用隔离 js沙箱,依据Proxy的反对度以及是否多例,反对三种沙箱实现形式款式隔离:反对shadow dom计划,以及试验式款式隔离全局办法(setInterval、clearInterval、addEventListener、removeEventListener)劫持b. 反对预加载 c. 基于props来实现父子通信 没有思考工程化问题:如专用依赖,组件复用没有思考到微前端平台运维老本上: 接入老本:子利用须要接入生命周期代码;主利用须要接入注册微利用代码;革新老本:须要本人思考微前端工程化问题,以及微前端平台运维。危险上: 社区活跃度:github star 数量 12.8k (统计工夫20220622)文档齐全,demo多emp性能上: 思考了微前端的工程化问题,基于webapck5 MF性能解决公共依赖的问题,以及能够实现微组件共享。不反对款式隔离和js隔离它的设计是去中心化,每个子利用都能够再接入子利用,老本上:接入老本: 所有利用都要迁徙到webpack5monorepo组织几个代码仓库革新老本: 基于webpack5 MF实现公共依赖和组件共享,须要另外做基建来对立引入这些包的入口。还有公建文档的问题。微组件共享是基于vuera这个库来实现的,只反对vue和react的组建共享须要本人实现利用隔离危险上: 社区活跃度:社区活跃度不高 star 1.8k (统计工夫20220622)文档不欠缺小结:emp比拟适宜大型且处于立项初期时选用。须要事先做monorepo的布局、款式统一规划。 microapp性能上: 摈弃了路由劫持的思路,选用类web component的计划基于CustomElement和款式隔离、js隔离来实现微利用的加载,所以子利用无需改变就能够接入反对利用隔离通过劫持底层接口实现了元素隔离提供了插件零碎反对预加载没有思考工程化问题:如专用依赖,组件复用没有思考到微前端平台运维老本:接入老本:子利用无需改变,主利用须要接入微利用代码革新老本:须要本人思考微前端工程化问题,以及微前端平台运维。 危险: 这个框架基于CustomElement和Proxy API,前者针对低版本有polyfill,但后者没有,且目前官网文档说没有做兼容的打算社区活跃度 star 2.7k(统计工夫20220622)文档齐全总结iframe、single-spa 在功能完善度上有余,所以放弃抉择;emp 比拟适宜在我的项目初期选型应用,用约定来躲避款式隔离和js隔离(所以 emp 没有把利用隔离思考进去),比拟适宜在大型项目中应用;microapp 和qiankun,性能残缺度上比拟好,只管 microapp 比 qiankun 多了元素隔离性能、插件零碎,且应用了类web component的思路升高子利用的接入老本。但基于 microapp 对 Proxy目前不思考兼容,且社区活跃度上,qiankun 更胜一筹,工期短须要有肯定的保障,所以最初选了qiankun ...

July 3, 2022 · 1 min · jiezi

关于微前端:Elux从微前端到微模块

前言:作为“前端微模块”这个概念有点新,之前尽管也有人提过这个词(可百度),但都只是简略的将其等同于动静加载模块,并没有赋予其更大的意义,如同也没有看到具体的落地计划。小弟也是突发奇想,摸着石头过河,想和大家讨论一下“前端微模块”会不会成为一片广大的天空? 微前端够用吗?从产品的角度某个大型利用蕴含A,B,C,D,E,F,G等若干性能,原来始终是整体打包发售... 随着用户需要的多样化,有的用户仅须要局部性能,于是聪慧的前端架构师“小李”利用时下风行的微前端技术,将利用拆分成了 3 个子利用: 【根底利用】蕴含性能:A【子利用A】蕴含性能:B,C,D【子利用B】蕴含性能:E,F,G这样等于有 3 个套餐能够供客户抉择: 套餐A:根底利用 + 子利用A套餐B:根底利用 + 子利用B套餐C:根底利用 + 子利用A + 子利用B然而用户的需要越来越精细化,有的须要ABCD,有的须要ACEG,有的须要ABDF,而且同一个性能可能还存在需要版本的不同,这让“小李”无可适从。 “微前端”还不足够灵便、粒度不足够细。从开发的角度对于“发送短信验证码”、“遗记明码”等某些通用的业务流程和性能,如果多个工程都须要,你是如何跨工程共享和保护的呢?是简略的复制粘贴?还是一股脑全放基座外面? “微前端”并没有解决工程之间代码的复用和保护的问题。将业务性能放进模块对于后端开发来说,按业务性能来划分模块简直是业界共识,而在前端开发中往往是按UI界面来切割模块,这样的前端模块实际上只是Component组件,不具备独立性与完整性。 如果咱们将残缺的业务性能(包含UI组件、款式、图片、交互流程、业务逻辑、API申请、数据管理等)都打包到一个NPM包中,并利用NPM的版本和依赖管理机制来保护客户需要,岂不美哉? 试想一下,某客户须要 A,C1(C性能的某个版本),E2(E性能的某个版本),G 性能,咱们只须要装置相应版本的NPM包: npm install A C@1 E@2 G业务模块变成了NPM包,版本号被关联至需要。 Great!咱们称这些蕴含残缺业务性能的模块为前端微模块,可见所谓的微模块其实就是蕴含业务性能的NPM模块。 微模块的划分微模块是实现特定业务性能所需资源的汇合: 划分视角: 业务性能(非UI界面)划分准则: 高内聚、低耦合(有清晰的边界)请留神"高内聚、低耦合"是惟一的划分规范,并不要求繁多职责,所以一个微模块中可能蕴含多个性能点、多个UI组件,一组相干视图。 如果二个微模块之间严密依赖,交互亲密,请不要宰割它们,这样会使问题复杂化。一种罕用思路是借助于后端Restful理念,将每种资源的保护(增删改查封)装成一个独立的微模块。 微模块与UI组件的区别微模块和UI组件都是一个NPM包,仿佛有点类似,但其实它们有实质的区别: UI组件是一种单体的封装;而微模块是一种资源的汇合。UI组件为复用而生,可能在多处被实例化,通常不蕴含具体的业务逻辑;而微模块并不谋求通用性,它蕴含具体的业务逻辑,通常只须要初始化一次。微模块可能蕴含多个UI组件、视图、Model等,也可能只是逻辑,不蕴含任何UI。微模块的开发和保护微模块的开发和保护就是对NPM包的开发和保护,并不附加任何新的学习老本,你须要做的只是保护它的依赖关系,并对外封装API,以保障独立性与易用性。 微模块的部署通常有2种形式应用和部署微模块: 动态编译:微模块作为一个NPM包被装置到工程中,通过打包工具(如webpack)失常编译打包即可。这种形式的长处是代码产物失去打包工具的各种去重和优化;毛病是当某个模块更新时,须要整体从新打包。动静注入:利用打包工具的动静加载性能(如webpack5 的 Module Federation)将微模块作为子利用部署(与时下风行的微前端相似)。这种形式的长处是各子利用独立部署运行,当某子利用中的微模块更新时,其它利用无需从新编译,刷新浏览器即可动静获取最新模块;毛病是没有打包工具的整体编译与优化,代码和资源容易反复加载或抵触。Elux对以上二种部署形式都有反对和示例。Elux中的微模块咱们先看一下时下风行的前端工程目录,假如有独立的性能ModuleA和ModuleB: src├── assets├── consts│ ├── ModuleA│ │ ├── Const1.ts //A中应用的一些常量│ ├── ModuleB│ ├── Const2.ts //B中应用的一些常量├── utils├── components│ ├── ModuleA│ │ ├── Component1.ts //A中应用的一些UI组件│ ├── ModuleB│ ├── Component2.ts //B中应用的一些UI组件├── containers├── pages│ ├── ModuleA│ │ ├── Page1.ts //A中应用的一些页面│ ├── ModuleB│ ├── Page2.ts //B中应用的一些页面├── models│ ├── ModuleA│ │ ├── Store1.ts //A中应用一些状态定义│ ├── ModuleB│ ├── Store2.ts //B中应用一些状态定义│其特点是以“文件职能”作为一级分类、“功能模块”作为次级分类。 ...

June 24, 2022 · 1 min · jiezi

关于微前端:微前端

微前端微前端如何解决业务场景的痛点,并以qiankun为例微前端的外围实现原理,并手把手实现简略微前端背景微前端最早于2016年在Micro-Frontends被提出,并建⽴了晚期的微前端模型。微前端的命名和能 ⼒和微服务有类似之处,微服务与微前端,都是心愿将某个单⼀的单体应⽤,转化为多个能够独⽴运 ⾏、独⽴开发、独⽴部署、独⽴保护的服务或者应⽤的聚合,从⽽满⾜业务疾速变动及分布式多团队并 ⾏开发的需要。如康威定律(Conway’s Law)所⾔,设计零碎的组织,其产⽣的设计和架构等价于组织间 的沟通构造;微服务与微前端不仅仅是技术架构的变动,还蕴含了组织⽅式、沟通⽅式的变动。微服务 课程⼤纲 2 与微前端原理和软件⼯程,⾯向对象设计中的原理同样相通,都是遵循单⼀职责(Single Responsibility)、关注拆散(Separation of Concerns)、模块化(Modularity)与分⽽治之(Divide & Conquer)等根本的准则。 什么是微前端一种相似于微服务的架构,是一种由独立交付的多个前端利用组成整体的架构格调,将前端利用合成一些更小、更简略的可能独立开发、测试、部署的利用,而在用户看来依然是内聚的单个产品 古代web利用面临的问题DX(developer experience) 多个零碎在一个仓库利用中,不同子利用独立SPA模式零碎分为多个仓库,独立上线部署,采纳MPA模式(公司采纳这种)UX(user experience) 性能体验页面跳转和用户体验问题微前端的意义微前端的次要特点:低耦合:当下前端畛域,单⻚⾯应⽤(SPA)是⾮常流⾏的项⽬状态之⼀,⽽随着工夫的推移以及 应⽤性能的丰盛,单⻚应⽤变得不再单⼀⽽是越来越庞⼤也越来越难以保护,往往是改⼀处⽽动全 身,由此带来的发版老本也越来越⾼。微前端的意义就是将这些庞⼤应⽤进⾏拆分,并随之解耦, 每个局部能够独自进⾏保护和部署,晋升效率。不限技术栈:在不少的业务中,或多或少会存在⼀些历史项⽬,这些项⽬⼤多以采⽤⽼框架相似 (Backbone.js,Angular.js 1)的B端管理系统为主,介于⽇常经营,这些零碎须要联合到新框架 中来使⽤还不能摈弃,对此咱们也没有理由浪费时间和精⼒重写旧的逻辑。⽽微前端能够将这些系 统进⾏整合,在根本不批改来逻辑的同时来同时兼容新⽼两套零碎并⾏运⾏。微前端的价值 罕用的微前端计划qiankun, icestark 本人实现 JS 以及款式隔离emp Webpack5 Module Federation (联邦模块)计划iframe、WebComponent 等计划基于qiankun的微前端整合主利用(vue)main.jsimport Vue from 'vue'import App from './App.vue'import router from './router'import { registerMicroApps, start } from 'qiankun';Vue.config.productionTip = falsenew Vue({ router, render: h => h(App)}).$mount('#app')// 加载微利用registerMicroApps([{ name: 'vue app', entry: '//localhost:8080/', container: '#container', activeRule: '/app1', props: { slogan: 'Hello Qiankun', },}]);start();微利用 (vue)public-path.jsif (window.__POWERED_BY_QIANKUN__) { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;}main.jsimport './public-path';import Vue from 'vue'import App from './App.vue'Vue.config.productionTip = falselet instance = null;function render(props = {}) { const { container } = props; instance = new Vue({ render: (h) => h(App), }).$mount(container ? container.querySelector('#app') : '#app');}// 独立运行时if (!window.__POWERED_BY_QIANKUN__) { render();}export async function bootstrap(props) { // common.setCommonData(props) console.log('bootstrap', props)}export async function mount(props) { // common.initGlState(props) console.log('mount', props) render(props);}export async function unmount() { instance.$destroy(); instance.$el.innerHTML = ''; instance = null;}

March 20, 2022 · 1 min · jiezi

关于微前端:2022年了你必须要学会搭建微前端项目及部署方式

一、微前端简介微前端是一种相似于微服务的架构,它将微服务的理念利用于浏览器端,行将 Web 利用由繁多的单体利用转变为多个小型前端利用聚合为一的利用。各个前端利用能够独立运行、独立开发、独立部署。微前端的益处 利用自治。只须要遵循对立的接口标准或者框架,以便于系统集成到一起,相互之间是不存在依赖关系的。繁多职责。每个前端利用能够只关注于本人所须要实现的性能。技术栈无关。你能够应用 Angular 的同时,又能够应用 React 和 Vue。微前端的毛病 利用的拆分根底依赖于基础设施的构建,一旦大量利用依赖于同一基础设施,那么保护变成了一个挑战。拆分的粒度越小,便意味着架构变得复杂、保护老本变高。技术栈一旦多样化,便意味着技术栈凌乱微前端由哪些模块组成 当下微前端次要采纳的是组合式利用路由计划,该计划的外围是“主从”思维,即包含一个基座(MainApp)利用和若干个微(MicroApp)利用,基座利用大多数是一个前端SPA我的项目,次要负责利用注册,路由映射,音讯下发等,而微利用是独立前端我的项目,这些我的项目不限于采纳React,Vue,Angular或者JQuery开发,每个微利用注册到基座利用中,由基座进行治理,然而如果脱离基座也是能够独自拜访,根本的流程如下图所示 是否要用微前端 微前端最佳的应用场景是一些B端的管理系统,既能兼容集成历史零碎,也能够将新的系统集成进来,并且不影响原先的交互体验二、微前端实战 微前端现有的落地计划能够分为三类,自组织模式、基座模式以及模块加载模式2.1 SingleSpa实战官网 https://zh-hans.single-spa.js... 实用场景:我的项目宏大,多个子项目整合在一个大的我的项目中。即便子项目的所用的技术栈不同,比方vue,react, angular有相应的single-spa的轮子,能够进行整合 1.构建子利用 首先创立一个vue子利用,并通过single-spa-vue来导出必要的生命周 vue create spa-vue npm install single-spa-vue// main.jsimport singleSpaVue from 'single-spa-vue';const appOptions = { el: '#vue', router, render: h => h(App)}// 在非子利用中失常挂载利用if(!window.singleSpaNavigate){ delete appOptions.el; new Vue(appOptions).$mount('#app');}const vueLifeCycle = singleSpaVue({ Vue, appOptions});// 子利用必须导出以下生命周期:bootstrap、mount、unmountexport const bootstrap = vueLifeCycle.bootstrap;export const mount = vueLifeCycle.mount;export const unmount = vueLifeCycle.unmount;export default vueLifeCycle;// router.js// 配置子路由根底门路const router = new VueRouter({ mode: 'history', base: '/vue', //扭转门路配置 routes}) ...

January 6, 2022 · 5 min · jiezi

关于微前端:微前端框架-qiankun-技术分析

咱们在single-spa 技术剖析 根本实现了一个微前端框架须要具备的各种性能,然而又实现的不够彻底,遗留了很多问题须要解决。尽管官网提供了很多样例和最佳实际,然而总显得过于薄弱,总给人一种“问题解决了,然而又没有齐全解决”的感觉。 qiankun 在 single-spa 的根底上做了二次开发,欠缺了很多性能,算是一个比拟齐备的微前端框架了。明天咱们来聊一聊 qiankun 的技术原理。 在本系列的结尾,咱们提到微前端的外围问题其实就是解决如何加载子利用以及如果做好子利用间的隔离问题。所以,咱们从这两点来看 qiankun 的实现。 如何加载子利用single-spa 通过 js entry 的模式来加载子利用。而 qiankun 采纳了 html entry 的模式。这两种形式的优缺点咱们在了解微前端技术原理中曾经做过剖析,这里不再赘述,咱们看看 qiankun 是如何实现 html entry 的。 qiankun 提供了一个 API registerMicroApps 来注册子利用,其外部调用 single-spa 提供的 registerApplication 办法。在调用 registerApplication 之前,会调用外部的 loadApp 办法来加载子利用的资源,初始化子利用的配置。 通过浏览 loadApp 的代码,咱们发现,qiankun 通过 import-html-entry 这个包来加载子利用。import-html-entry 的作用就是通过解析子利用的入口 html 文件,来获取子利用的 html 模板、css 款式和入口 JS 导出的生命周期函数。 import-html-entryimport-html-entry 是这样工作的,假如咱们有如下 html entry 文件: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>test</title></head><body><!-- mark the entry script with entry attribute --><script src="https://unpkg.com/mobx@5.0.3/lib/mobx.umd.js" entry></script><script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script></body></html>咱们应用 import-html-entry 来解析这个 html 文件: ...

December 21, 2021 · 2 min · jiezi

关于微前端:微前端框架-singlespa-技术分析

在了解微前端技术原理中咱们介绍了微前端的概念和核心技术原理。本篇咱们联合目前业内支流的微前端实现 single-spa 来阐明在生产实践中是如何实现微前端的。 single-spa 的文档略显凌乱,概念也比拟多,首次接触它的同学容易抓不住重点。明天咱们尝试整顿出一条清晰的脉络,让感兴趣的同学可能疾速了解它。 在 single-spa 的架构设计中,有两种次要角色,主利用和子利用,如下图。 主利用力求足够简略,只负责子利用的调度,业务逻辑都由子利用来承当。 外围能力其实总结来说,single-spa 的外围就是定义了一套协定。通过这套协定,主利用能够不便的晓得在什么状况下激活哪个子利用。而这套协定次要蕴含两个局部:主利用的配置信息和子利用的生命周期函数。 主利用的配置信息在 single-spa 中,这个配置信息叫 Root Config。 上面的样例展现了配置信息的构造: { name: "subApp1", app: () => System.import("/path/to/subApp1/code"), activeWhen: "/subApp1",}name 就是子利用的名称,app 函数通知主利用如何加载子利用的代码,activeWhen 通知主利用何时激活子利用,也能够为一个返回布尔值的函数。 通过 registerApplication 将子利用的信息注册到主利用中。 样例如下: singleSpa.registerApplication({ name: 'appName', app: () => System.import('appName'), activeWhen: '/appName', customProps: { authToken: 'xc67f6as87f7s9d' }})子利用的生命周期函数主利用在治理子利用的时候,通过子利用裸露的生命周期函数来实现子利用的启动和卸载。 次要有如下几个生命周期函数。 bootstrap 这个生命周期函数会在利用第一次挂载前执行一次。就是说在子利用的代码加载实现当前,页面渲染之前执行。函数模式如下: export function bootstrap(props) { return Promise .resolve() .then(() => { // 能够在这里部署只执行一次的初始化代码 console.log('bootstrapped!') });}mount 当主利用断定须要激活这个子利用时会调用这个生命周期函数。在这个函数中实现子利用的挂载、页面渲染等逻辑。这个函数也只会执行一次。咱们能够简略的了解为 ReactDOM.render 操作。函数模式如下: export function mount(props) { return Promise.resolve().then(() => { // 页面渲染逻辑 console.log('mounted!'); });}unmount ...

December 3, 2021 · 2 min · jiezi

关于微前端:理解微前端技术原理

我最早是在 2016 年接触到微前端的,过后社区里以介绍概念居多,在实际计划,尤其是在业务落地方面利用的比拟少。起初,随着计划逐步成熟,社区里对于微前端的探讨越来越多。 明天,咱们先从概念、关键技术原理层面来对微前端进行具体阐明。后续会有专门的文章来介绍微前端的实践经验。 什么是微前端微前端的概念来源于微服务,其整体的架构思路是将前端利用分解成一些更小、更简略的可能独立开发、测试、部署的利用,之后将这些利用组成整体,在用户看来依然是内聚的单个产品,用户体验是统一的。 从概念上看,微前端架构由主利用和子利用两个局部组成,子利用负责具体的业务实现,主利用负责子利用的加载和卸载,即生命周期治理。 从概念延长开来,咱们不难发现,应用微前端,能够取得如下收益: 子利用独立开发、部署,技术栈无关 拆分当前,子利用领有独立的代码仓库、独立的开发部署流程,甚至能够自在的应用任何技术栈进行开发。由此,咱们能够在组织架构层面造成不同的团队来负责不同的业务模块,各个团队之间绝对独立自主,互不烦扰。增量降级,多技术体系共存 对于很多大型的组织,他们的产品通常都经验了长期的迭代,性能简单,同时技术栈通常也比拟老旧。应用微前端当前,借助于独立的子利用,能够取得增量降级的能力。既能够实现新性能应用新的技术栈,同时与老技术栈共存。又能够对老性能进行逐渐迭代降级,小步快跑。产品层面的自由组合 借助于微前端,咱们能够对各个子利用自在的进行高低线。换句话说,咱们能够依据产品须要,自在的将不同的子利用组合成新的产品。技术剖析在微前端架构下,有主利用和子利用两个根本角色。子利用负责具体的业务逻辑,主利用负责调度子利用。思考到主利用的特殊性性能,为了保障整个框架的可用性,通常主利用不负责任何业务逻辑。 路由与子利用加载因为主利用负责调度子利用,因而主利用须要具备路由治理和资源加载能力。所谓路由治理,就是主利用中须要保护一个路由表,当页面路由发生变化的时候,主利用能够晓得以后须要启动哪个子利用。这个路由表能够是动静的,也能够是动态的。 晓得启动哪个子利用之后,主利用就须要加载子利用的资源。通常有两种资源加载形式: JS Entry。 通常将子利用的所有资源打包成一个入口文件,在 single-spa 的很多样例中就应用了这种形式。HTML Entry。 子利用构建输入的是一个 HTML 文件,主利用通过加载这个 HTML 文件实现子利用的加载。相比较而言,JS Entry 的计划限度更多一些,比方要求将图片、款式等所有资源打包成一个 JS Bundle,构建的包太大,也无奈利用浏览器的并行加载能力。同时,子利用还须要与主利用约定好要挂载的节点,主利用要提前初始化好,或者子利用自行创立,防止挂载失败或者抵触。 HTML Entry 很好的防止了 JS Entry 的问题。实质上,HTML 文件充当的是利用动态资源表的角色。主利用加载了 HTML 当前,浏览器会自行下载子利用的各种资源。同时,因为构建产物是 HTML,子利用具备与独立利用开发时统一的开发体验。当然,HTML Entry 也存在毛病,比方要多一次申请,先加载了 HTML 能力晓得加载哪些资源。 在加载完子利用的资源当前,主利用就能够启动子利用,实现页面渲染了。那么该如何启动子利用呢?主利用须要与子利用之前制订一个接口标准,比方在 single-spa 中就指定了 bootstrap、mount、unmount 和 unload 四个办法。子利用裸露这四个办法给主利用,主利用通过这四个办法来治理子利用的申明周期。 隔离解决了路由和子利用加载的问题,实践上说咱们曾经实现了微前端的外围能力。然而,在理论的工程实际中,咱们还须要解决很多的细节问题。其中最大的一部分就是如何做好子利用间的隔离。比方如何防止子利用间的款式抵触。 抛开现有的微前端计划,如果让咱们从头开始实现一套微前端架构,将独立开发部署的各个子利用组合起来。置信大多数同学都会首先想到 iframe。其实咱们就能够通过 iframe 来了解微前端架构中的种种技术细节。 iframe 自带的款式、环境隔离机制使得它具备人造的沙箱能力,然而 iframe 也有很多人造的缺点,比方事件无奈冒泡到顶层,路由跳转无奈与主利用同步,与主利用通信简单繁琐等。 咱们能够参考 iframe 的设计思维,来设计如何对子利用进行隔离。一个传统的 iframe 具备四层能力:文档的加载能力、HTML 的渲染能力、独立执行 JavaScript 的能力、隔离款式的能力。 文档的加载能力和 HTML 的渲染能力在后面主利用加载子利用资源的时候,咱们曾经做了阐明。 ...

November 24, 2021 · 2 min · jiezi

关于微前端:使用Jenkins部署微前端方案实践总结

本文首发于公众号「前端进阶之旅」 继续集成集成工具 jenkins 的根本介绍和自动化部署微前端我的项目的几个简略计划 一、Jenkins 根底介绍Jenkins 是国内上风行的收费开源软件我的项目,是基于 Java 开发继续集成工具,用于监控继续反复的工作,旨在提供一个凋谢的易用的软件平台,使软件的继续集成自动化,大大节约人力和时效。 Jenkins 性能包含: 继续的软件版本公布/测试项目。监控内部调用执行的工作。1. 系统管理装置好的 jenkins 能够在系统管理进行配置零碎信息等 零碎设置 执行者数量:零碎可同时并发执行工作的数量,零碎默认 2 个,原则上不超过服务器 CPU 核数,否则容易呈现 CPU 利用率过载导致服务挂掉。Jenkins URL:Jenkins 拜访地址,能够批改地址的端口号,和批改服务器配置文件的端口号成果统一凭据配置 凭据能够用来存储须要密文爱护的数据库明码、Gitlab 明码信息、Docker 公有仓库明码等,以便 Jenkins 能够和这些第三方的利用进行交互,须要装置 Credentials Binding 插件,用户才可治理凭据凭据治理 凭据治理蕴含凭据的治理和凭据所在域的治理,零碎默认会创立全局域,用户能够在两个治理表格的存储下增加域,在用户抉择的域下增加凭据或者进入域详情增加凭据。为了最大水平地进步安全性,在 Jenkins 中配置的凭据以加密模式存储在主 Jenkins 实例上(由 Jenkins 实例 ID 加密),用户须要应用配置的惟一标识 ID 进行解决。能够增加的凭证有 5 种: 用户名和明码SSH 密钥(SSH 公私钥对)加密文件令牌(例如 API 令牌、GitHub 集体拜访令牌)证书增加凭据: 品种范畴 (全局、零碎)凭据ID (此字段是可选的。如果未指定其值,Jenkins 将为凭证 ID 调配一个全局惟一 ID(GUID)值。请记住,一旦设置了凭证 ID,就无奈再更改它)凭证形容。插件治理 Jenkins 提供了两种不同的办法来在主服务器上安装插件: 在治理平台界面中应用插件管理器 通过“系统管理” >“插件治理”视图,Jenkins 环境的管理员能够应用该视图。在“ 可选插件 ”选项卡下,能够搜寻用户须要的插件,搜寻到须要的插件后勾选插件列表的选中框,之后点击左下角的下载并且重启后装置,期待插件下载实现后服务主动重启,从新进入零碎即装置胜利。 应用 Jenkins CLI install-plugin 命令 ...

November 18, 2021 · 3 min · jiezi

关于微前端:微前端-SingleSPA

什么是微前端?微前端就是依据不同的性能拆分成多个独立模块(子利用),通过主利用来加载这些子利用。微前端的外围在于拆,拆完后在合。 微前端的应用场景不同团队开发同一个利用,然而用到的技术栈不同的状况下每个团队独立开发部署,不依赖于别的团队代码老的我的项目代码和新的技术栈在同一利用中交融有人说了这用iframe一样能解决啊,留神,和微前端相比,iframe有多个弊病。比方 1.左侧是一个菜单,右侧内容是加载不同的iframe,每当点击一个菜单就会加载整个模块的js,这重大影响了性能。2.当用户在某一个页面刷新浏览器时用户以后点开的会失落SingleSpa实战1.创立子利用这里我创立一个vue子利用(react没学过,当前有机会再整合) vue create app12.下载single-spa-vue包npm install single-spa-vue3.创立主利用vue create main-appnpm i single-spa4.主利用中的mainimport Vue from 'vue'import App from './App.vue'import router from './router'import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI);// 动静增加script脚本const loadScript = async (url)=> { await new Promise((resolve,reject)=>{ const script = document.createElement('script'); script.src = url; script.onload = resolve; script.onerror = reject; document.head.appendChild(script) });}import { registerApplication, start } from 'single-spa';// 注册子利用registerApplication( 'app1', async ()=>{ // 子利用对应的接口 await loadScript('http://localhost:10000/js/chunk-vendors.js'); await loadScript('http://localhost:10000/js/app.js'); return window.app1 }, // 当匹配url门路为/app1时 location => location.pathname.startsWith('/app1'))// 启动利用start();new Vue({ router, render: h => h(App)}).$mount('#app')5.主利用的App.vue<template> <div id="app"> <el-container> <el-aside width="200px"> <el-menu router class="el-menu-vertical-demo"> <el-menu-item-group> <el-menu-item index="/app1">选项1</el-menu-item> </el-menu-item-group> </el-menu> </el-aside> <el-main> <div id="app1"></div> </el-main> </el-container> </div></template>6.子利用 main.jsimport Vue from 'vue'import App from './App.vue'import router from './router'import singleSpaVue from 'single-spa-vue'Vue.config.productionTip = falseconst appOptions = { el: '#app1',//要挂载到主利用的哪个元素上 router, render: h => h(App)}// 返回一个生命周期对象const vueLifeCycle = singleSpaVue({ Vue, appOptions});// 子利用必须导出 以下生命周期 bootstrap、mount、unmountexport const bootstrap = vueLifeCycle.bootstrap;export const mount = vueLifeCycle.mount;export const unmount = vueLifeCycle.unmount;export default vueLifeCycle;7.打包成供主利用应用的类库 (子利用中的配置)在src中增加vue.config.js ...

September 1, 2021 · 1 min · jiezi

关于微前端:使用开源微前端框架-Luigi-创建一个基于微前端架构的工程

官网地址 微前端通常被称为“前端微服务”。 它们容许您将大型单体前端合成为独立的、可扩大的、能够协同工作的独立局部。 微前端架构对于简单的产品或领有泛滥团队的公司尤其有用,能够帮忙您创立统一的 Web 应用程序。 观看此视频,其中解释了微前端架构的基础知识以及如何应用 Luigi 实现。 Luigi 是一个用 Svelte 编写的开源微前端框架。 它容许您创立统一的用户界面和导航,同时还提供其余性能以使开发更容易。 它的外观基于根本库款式。 Luigi 与技术无关,容许您应用 React、Angular、UI5 或任何其余技术构建应用程序并向其增加微前端。 Luigi Fiddle 是一个测试游乐场,您能够在其中感触 Luigi。 这张图描述了 Luigi 的根本架构: Luigi terminology这是一小部分 Luigi 术语: Luigi Core - 指其中显示微前端的次要应用程序。 它包含顶部和侧面导航以及与主应用程序相干的所有其余设置。Luigi Client - 这个术语涵盖了 Luigi 提供的所有与微前端相干的设置。 微前端可通过 Luigi Client API 进行配置。parameters - 参数是用于配置 Luigi 应用程序的元素。导航节点 - Luigi 中侧面导航的各个链接。Contexts - 上下文是 Luigi 参数,容许您将对象传递到微前端。Views - 视图,微前端的另一个名称。本系列文章,咱们将从头开始应用 Luigi 创立一个应用程序。它将基于网络购物平台的理念,并将包含其余性能,例如用于以英语和德语显示网站的本地化。 该应用程序由三个次要局部组成: 应用 React 构建的 Luigi Core 应用程序:“主应用程序”,其中蕴含微前端并包含无论您导航到应用程序的哪个子页面都保持一致的顶部和侧面导航。应用 React 构建的微前端:它们包含主页、“产品”页面和蕴含每个产品信息的“产品详细信息”列表。应用 UI5 构建的微前端:“订单历史”页面,显示已购买产品的数量和价格。最初,您实现的应用程序的主页应如下所示: ...

August 16, 2021 · 7 min · jiezi

关于微前端:微前端Micro-Frontend-落地实施的一些具体例子

前文微前端概述(Micro Frontends) 以及相比单体利用,微前端能带来什么益处 简略介绍了微前端的概念,本文来看一个具体的利用例子。 原文地址 设想一个网站,客户能够在其中订购外卖食品。从外表上看,这是一个相当简略的概念,但如果你想做得好,还有惊人的细节: 应该有一个登陆页面,客户能够在其中浏览和搜寻餐馆。 餐厅应该能够通过任意数量的属性进行搜寻和过滤,包含价格、美食或客户之前订购的货色每家餐厅都须要本人的页面来显示其菜单项,并容许客户抉择他们想吃的货色,包含折扣、餐饮优惠和特殊要求客户应该有一个个人资料页面,他们能够在其中查看他们的订单历史记录、跟踪交付和自定义他们的付款选项 每个页面都有足够的复杂性,咱们能够轻松地证实每个页面都有一个专门的团队,并且每个团队都应该可能独立于所有其余团队在他们的页面上工作。 他们应该可能开发、测试、部署和保护他们的代码,而不用放心与其余团队发生冲突或协调。 然而,咱们的客户依然应该看到一个无缝的网站。 在本文的其余部分,咱们将在须要示例代码或场景的任何中央应用此示例应用程序。 Integration approaches鉴于下面相当涣散的定义,有许多办法能够正当地称为微前端。 在本节中,咱们将展现一些示例并探讨它们的衡量。 所有这些办法都有一个相当天然的架构——通常应用程序中的每个页面都有一个微前端,并且有一个容器应用程序,它: 出现常见的页面元素,例如页眉和页脚解决跨畛域问题,如身份验证和导航将各种微前端放在页面上,并通知每个微前端何时何地渲染本人 Server-side template composition咱们从一种相对不新鲜的前端开发办法开始——用多个模板或片段在服务器上渲染 HTML。 咱们有一个 index.html ,它蕴含所有常见的页面元素,而后应用服务器端蕴含从片段 HTML 文件中插入特定于页面的内容: <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title>Feed me</title> </head> <body> <h1>Feed me</h1> <!--# include file="$PAGE.html" --> </body></html>咱们应用 Nginx 提供此文件,通过匹配正在申请的 URL 来配置 $PAGE 变量: server { listen 8080; server_name localhost; root /usr/share/nginx/html; index index.html; ssi on; # Redirect / to /browse rewrite ^/$ http://localhost:8080/browse redirect; # Decide which HTML fragment to insert based on the URL location /browse { set $PAGE 'browse'; } location /order { set $PAGE 'order'; } location /profile { set $PAGE 'profile' } # All locations should render through index.html error_page 404 /index.html;}这是相当规范的服务器端组合。 咱们能够正当地将其称为微前端的起因是,咱们以这样一种形式拆分了咱们的代码,即每个局部都代表一个独立的畛域概念,能够由独立团队交付。 这里没有显示的是这些不同的 HTML 文件如何最终呈现在 Web 服务器上,但假如它们每个都有本人的部署管道,这容许咱们将更改部署到一个页面,而不会影响或思考任何其余页面。 ...

July 29, 2021 · 5 min · jiezi

关于微前端:微前端解决方案

前言随着技术的倒退,前端利用承载的内容也日益简单,基于此而产生的各种问题也应运而生,从MPA(Multi-Page Application,多页利用)到SPA(Single-Page Application,单页利用),尽管解决了切换体验的提早问题,但也带来了首次加载工夫长,以及工程爆炸增长后带来的巨石利用(Monolithic)问题;对于MPA来说,其部署简略,各利用之间人造硬隔离,并且具备技术栈无关、独立开发、独立部署等特点。要是可能将这两方的特点联合起来,会不会给用户和开发带来更好的用户体验?至此,在借鉴了微服务理念下,微前端便应运而生。 目前社区有很多对于微前端架构的介绍,但大多停留在概念介绍的阶段。而本文会就某一个具体的类型场景,着重介绍微前端架构能够带来什么价值以及具体实际过程中须要关注的技术决策,并辅以具体代码,从而能真正意义上帮忙你构建一个生产可用的微前端架构零碎。 什么是微前端?微前端是一种相似于微服务的架构,它将微服务的理念利用于浏览器端,行将单页面前端利用由繁多的单体利用转变为把多个小型前端利用聚合为一的利用。各个前端利用还能够独立开发、独立部署。 微前端的价值微前端架构具备以下几个外围价值: 技术栈无关 主框架不限度接入利用的技术栈,子利用具备齐全自主权独立开发、独立部署 子利用仓库独立,前后端可独立开发,部署实现后主框架主动实现同步更新独立运行时 每个子利用之间状态隔离,运行时状态不共享微前端架构旨在解决单体利用在一个绝对长的时间跨度下,因为参加的人员、团队的增多、变迁,从一个一般利用演变成一个巨石利用(Frontend Monolith)后,随之而来的利用不可保护的问题。这类问题在企业级 Web 利用中尤其常见。 针对中后盾利用的解决方案中后盾利用因为其利用生命周期长(动辄 3+ 年)等特点,最初演变成一个巨石利用的概率往往高于其余类型的 web 利用。这次要带来了技术栈落后、编译部署慢两个问题。而从技术实现角度,微前端架构解决方案大略分为以下几类场景: 前端容器化:iframe能无效地将另一个网页/单页面利用嵌入到以后页面中,两个页面间的CSS和JavaScript是互相隔离的。iframe相当于创立了一个全新的独立的宿主环境,相似于沙箱隔离,它意味着前端利用之间能够互相独立运行。如果咱们做一个利用平台,会在零碎中集成第三方零碎,或多个不同部门团队下的零碎,将iframe作为容器来包容其余前端利用,显然这仍然是一个十分靠谱的计划。微组件:借助于Web Components技术,开发者能够创立可重用的定制元素,来构建跨框架的前端利用。通常应用 Web Components来做子利用封装,子利用更像是一个业务组件而不是利用。真正在我的项目上应用Web Components技术,离当初的咱们还有些间隔,可是联合Web Components来构建前端利用,是一种面向未来演进的架构。微利用:通过软件工程的形式,在部署构建环境中,把多个独立的利用组合成一个单体利用。微模块:开发一个新的构建零碎,将局部业务性能构建成一个独立的chunk代码,应用时只须要近程加载即可。微前端架构微前端架构很好的借鉴了SPA无刷新的特点,在SPA之上引入新的分层实现利用切换的性能: 微前端架构实际中的问题能够发现,微前端架构的劣势,正是 MPA 与 SPA 架构劣势的合集。即保障利用具备独立开发权的同时,又有将它们整合到一起保障产品残缺的流程体验的能力。 Stitching layer 作为主框架的核心成员,充当调度者的角色,由它来决定在不同的条件下激活不同的子利用。因而主框架的定位则仅仅是:导航路由 + 资源加载框架。 而具体要实现这样一套架构,咱们须要解决以下几个技术问题: 路由零碎及 Future State咱们在一个实现了微前端内核的产品中,失常拜访一个子利用的页面时,可能会有这样一个链路: 此时浏览器的地址可能是 https://app.alipay.com/subApp/123/detail,设想一下,此时咱们手动刷新一下浏览器,会产生什么状况? 因为咱们的子利用都是 lazy load 的,当浏览器从新刷新时,主框架的资源会被从新加载,同时异步 load 子利用的动态资源,因为此时主利用的路由零碎曾经激活,但子利用的资源可能还没有齐全加载结束,从而导致路由注册表里发现没有能匹配子利用 /subApp/123/detail 的规定,这时候就会导致跳 NotFound 页或者间接路由报错。 这个问题在所有 lazy load 形式加载子利用的计划中都会碰到,早些年前 angularjs 社区把这个问题对立称之为 Future State。 解决的思路也很简略,咱们须要设计这样一套路由机制: 主框架配置子利用的路由为 subApp: { url: '/subApp/**', entry: './subApp.js' },则当浏览器的地址为 /subApp/abc 时,框架须要先加载 entry 资源,待 entry 资源加载结束,确保子利用的路由零碎注册进主框架之后后,再去由子利用的路由零碎接管 url change 事件。同时在子利用路由切出时,主框架须要触发相应的 destroy 事件,子利用在监听到该事件时,调用本人的卸载办法卸载利用,如 React 场景下 destroy = () => ReactDOM.unmountAtNode(container)。 ...

July 2, 2021 · 2 min · jiezi

关于微前端:singlespareact搭建微前端应用

概述上一篇《微前端原理篇》讲到了微前端架构设计大抵有三种,Monorepo、NPM包以及SystemJS动静加载模块,本文会逐个实现。如果对这三种设计不分明的同学请翻阅上一篇文章。 MonorepoMonorepo 简略的说,是指将所有我的项目的代码放在一个仓库中。这并不是说代码没有组织都放在 ./src 文件夹外面。相同,通过应用 Buck / Bazel,monorepo 中的代码都是宰割到一个个小的模块中的。

June 20, 2021 · 1 min · jiezi

关于微前端:得物技术浅谈微前端大世界qiankun源码研读

微前端,对于他的好和利用场景,很多师兄们也都介绍过了,那么咱们应用的微前端计划qiankun是如何去做到利用的“微前端”的呢? 几个个性说到前端微服务,必定不能不提他的几个个性。 子利用并行父子利用通信预加载 闲暇时预加载子利用的资源公共依赖的加载按需加载JS沙箱CSS隔离做到以上的这几点,那么咱们子利用就能多重组合,互不影响,面对大型项目的聚合,也不必放心我的项目汇总后的保护、打包、上线的问题。这篇分享,就会简略的读一读qiankun 的源码,从大略流程上,理解他的实现原理和技术计划。 咱们的利用怎么配置?-退出微前端Arya的怀抱吧Arya- 公司的前端平台微服务基座 Arya接入了权限平台的路由菜单和权限,能够动静筛选具备微服务能力的子利用的指定页面组合成一个新的平台,不便各个系统权限的下发和性能的汇聚。 创立流程初始化全局配置 - start(opts)/src/apis.ts export function start(opts: FrameworkConfiguration = {}) { // 默认值设置 frameworkConfiguration = { prefetch: true, singular: true, sandbox: true, ...opts }; const { prefetch, sandbox, singular, urlRerouteOnly, ...importEntryOpts } = frameworkConfiguration; // 查看 prefetch 属性,如果须要预加载,则增加全局事件 single-spa:first-mount 监听,在第一个子利用挂载后预加载其余子利用资源,优化后续其余子利用的加载速度。 if (prefetch) { doPrefetchStrategy(microApps, prefetch, importEntryOpts); } // 参数设置是否启用沙箱运行环境,隔离 if (sandbox) { if (!window.Proxy) { console.warn('[qiankun] Miss window.Proxy, proxySandbox will degenerate into snapshotSandbox'); // 快照沙箱不反对非 singular 模式 if (!singular) { console.error('[qiankun] singular is forced to be true when sandbox enable but proxySandbox unavailable'); frameworkConfiguration.singular = true; } } } // 启动主利用- single-spa startSingleSpa({ urlRerouteOnly }); frameworkStartedDefer.resolve();}start 函数负责初始化一些全局设置,而后启动利用。这些初始化的配置参数有一部分将在 registerMicroApps 注册子利用的回调函数中应用。registerMicroApps(apps, lifeCycles?) - 注册子利用/src/apis.ts ...

April 30, 2021 · 7 min · jiezi

关于微前端:微前端落地系列复盘

前沿:哈喽大家好,我是树酱,好久不见。本文次要为了做复盘,在去年基于qiankun微前端架构的门户建设中,遇到的一些问题,可能你会认为:“哇,这也算问题吗?太简略了吧”。次要是分享在我认知体系内是如何解决的,如果对其中一些解决方案有更好的倡议,记得在评论区留言~ 上图为落地过程中遇到的一些问题,接下来围绕这些问题跟大家分享我的认知体系是如何去解决的 1. 利用权限管制如何做?权限管制个别分为:路由权限、按钮权限(视觉权限)等,上面举例说明路由权限:比方当用户从门户中登陆后,要拜访利用A或者利用A下的某个菜单页面时,但该用户并没有该利用的拜访权限,咱们须要拦挡它,不让它进入按钮权限 (视图权限):比方当某个用户不存在对某种资源进行删除的权限的时候,咱们会将原有的删除操作按钮给暗藏,以此来实现按钮 啊敏同学:那咱们怎么晓得是否有权限,或者说怎么辨别资源类型?:mark,首先咱们先给每个资源定义一个code编码,你能够了解为对这个资源的惟一标记,它的身份id,比方咱们可能是利用、菜单或者按钮。针对不同类型的资源,能够做用规定辨别,比方 1.1 路由权限 啊乐同学:那编码规定确定了,咱们如何管制呢?:咱们来假如一个用户有一个资源汇合的权限 [appliction:monitor、menu:monitor:flume、button:monitor:flume:delete] 首先先说路由权限管制,次要是为了判断该用户是否有利用或者菜单的拜访权限,咱们个别能够在router.beforeEach 导航守卫中做拦挡,个别分为两种状况 动静路由:原先并未增加路由,依据上文提到的资源编码来动静增加路由动态路由:曾经初始化好路由,通过对立在门户这个主利用的路由依据获取的资源编码来判断以后拜访的用户是否有利用拜访权限,如果没有则进行拦挡,如下所示是门户这个主利用对路由的解决,因为当子利用加载后,主利用会劫持本来子利用的路由,举个例子如下 上图中的hasPerssion办法就是通过判断该用户是否有某个利用的资源编码,以此来判断是否有权限拜访,实质上就是new RegExp正则匹配,如果没有权限则跳转到无权限拜访页面 1.2 视觉权限啊敏同学:那按钮权限呢?如何解决:同样须要依赖到资源编码,而后通过自定义指令,比方v-perms来管制 至于v-perms指令咱们是如何给每个子利用复用,通过门户主利用去注入到子利用生命周期, 子利用接管如下 啊敏同学:树酱,你下面提及的按钮权限管制是基于<template>, 那如果是间接render函数渲染咋搞?:render函数中原理也是一样的,只不过把指令换了一种形式,通过工具库外面封装findPermission函数,来管制style的display属性值,当然你也能够用上文提到主利用给子利用的形式注入一个工具函数的形式,以此达到复用。如下所示 2.利用的异样监控当门户落地后,如何去监控子利用的异样信息就显得很重要,毕竟不同环境可能会呈现不一样的状况,那如何去追踪和定位呢?咱们在qiankun的api文档中找到了addGlobalUncaughtErrorHandler办法,用来监听全局的未捕捉异样 比如说我要监听利用加载失败,那我能够捕捉到的错误信息中的信息提醒来做正则匹配 而后通过bus通信,告诉页面显示利用加载失败页面,如下所示 啊豪同学:那你们怎么将异样信息上报的呢?:咱们是通过sentry去做异样信息上报的,sentry自身会做异样捕捉,然而为了让主利用可能对立捕捉子利用的异样信息,做对立异样信息保护治理,所以在addGlobalUncaughtErrorHandler中做了被动上报 3.如何让新的子利用实现疾速集成前言:咱们晓得qiankun架构中一个子利用要集成到主利用中,是须要创立生命周期函数,比方mounted等以及批改打包形式。那如何疾速让新的子利用实现疾速集成呢?咱们是通过打造一个简易版的脚手架工具,把波及相干的性能用一套模版保护起来,而后通过保护好的这个模版,而后通过脚手架创立新我的项目,实质上就是拉取这个模版,如下图所示 ### 4.如何动静注册利用? 前沿:为了让主利用能够去拜访不同的子利用,咱们须要在配置文件中定义好每个子利用的入口entry以及拜访名称,以此来注册子利用,咱们个别会不同的环境有不同的配置,比方下图所示 啊斌同学:那这样的话,每次批改子利用的entry或者新增新的子利用都得从新编译门户这个主利用:是的,本地配置化是会存在这样的问题,咱们能够搭建一个配置核心来保护,而后通过接口调用的形式来获取不同环境的,像上面这样 ### 5.部署中遇到的问题 前沿:部署微前端体系门户波及到公有云部署,私有云部署,还有基于容器化部署等等。过程中遇到一些问题5.1 主利用加载子利用动态资源跨域咋搞?实质上是因主利用是通过fetch去获取子利用的动态资源的,而后通过正则去解析进去子利用的动态资源信息,而后fetch下来,所以必须要求这些动态资源反对跨域,如何配置如下图所示,通过设置容许源了 Access-Control-Allow-Origin:跨域在服务端是不容许的。只能通过给Nginx配置Access-Control-Allow-Origin *后,能力使服务器能承受所有的申请源(Origin) 5.2 主利用加载子利用的动态资源不是最新,导致加载失败?实质上就是子利用更新了代码,而主利用在fetch子利用资源的时候,加载到缓存的资源,导致加载资源失败,那么怎么解决呢?咱们能够在子利用的nginx中,设置cache-control,在每次申请资源的时候都查看是否更新。 5.3 如何让每个子利用都领有通用的ngixn配置?为了解决以上问题,又要保障通用性,能够针对每个子利用都是同样的nginx配置,这时候能够通过在dockerfile中定义,在打包到容器时,把nginx.conf也打到容器中 5.4 如何正确部署主利用和子利用?次要是两种计划: 1.主利用和子利用部署到同一个服务器这种状况适宜公司服务器数量较少,外围就是把主利用部署在一级目录,其余子利用放在二级目录 2.主利用和子利用别离部署在不同服务器这种状况又分为两种,一种是所有子利用都在一台服务器,一种是不同子利用在不同服务器,独立运行。 最初,以上两种形式都有好有坏,具体看你搭建的零碎是外部以ip拜访为主还是内部拜访域名为主,去依据理论状况利用。如果是外部零碎建设,子利用以外部拜访ip为主,子利用都在独立服务器,无需在配置过多域名,那能够间接用计划2,那如果是对外且域名无限,那计划1或者更适合。 具体的配置形式,我看qiankun官网文档曾经更新,可查阅文档 这里就不反复介绍 你好,我是 树酱,请你喝杯 记得三连哦~ 1.浏览完记得点个赞哦,有 有能源 ...

April 28, 2021 · 1 min · jiezi

关于微前端:基于-qiankun-的微前端应用实践

本文作者:张延卿业务背景云音乐广告 Dsp(需求方平台)平台分为合约平台(Vue 框架)和竞价平台(React 框架),因历史起因框架选型未能对立,最近来了新需要,须要同时在两个平台减少一样的模块,因为都是 Dsp 平台,前期这样的需要可能会很多,所以思考到组件复用以及升高保护老本,在想怎么对立技术栈,把 React 零碎塞到 Vue 我的项目中进行出现。 零碎是传统的左右布局,左侧侧边栏展现菜单栏,头部导航展现根底信息,利用内容全副填充到蓝色的内容区。说实话,第一反馈我间接想嵌套 iframe ,然而利用过 iframe 技术的,大家都晓得它的痛:浏览器历史栈问题后退 / 后退<div style="margin-top:5px" />无论你在 iframe 里潜行了多深,你退一步就是一万步,这个体验真的很好受<div style="margin-top:5px" />利用通信<div style="margin-top:5px" >有时候主利用可能只想晓得子系统的 URL 参数,然而 iframe 利用跟它不同源,你就得想点其余方法去获取参数了,咱们最罕用的就是 postMessage 了<div style="margin-top:5px">缓存<div style="margin-top:5px" />iframe 利用更新上线后,关上零碎会发现零碎命中缓存显示旧内容,须要用工夫戳计划解决或强制刷新另外就是应用 MPA + 路由散发,当用户拜访页面时,由 Nginx 等负责依据路由散发到不同的业务利用,由各个业务利用实现资源的组装后返回给浏览器,这种形式就须要把界面、导航都做成相似的样子。<div style="margin-top:5px" /> 长处: 多框架开发;独立部署运行;利用之间齐全隔离。毛病: 体验差,每个独立利用加载工夫较长;因为齐全隔离,导致在导航、顶部这些通用的中央改变大,复用性变的很差。还有就是目前比拟支流的几种微前端计划:<div style="margin-top:5px" /> 基座模式:次要基于路由散发,由一个基座利用监听路由,依照路由规定去加载不同的利用,以实现利用间解耦EMP:Webpack5 Module Federation,去中心化的微前端计划,能够在实现利用隔离的根底上,轻松实现利用间的资源共享和通信;总的来说,iframe 次要用于简略并且性能要求不高的第三方零碎;MPA 无论在实现老本和体验下面都不能满足以后业务需要;基座模式和 EMP 都是不错的抉择,因 qiankun 在业内应用比拟广,较为成熟,最初还是抉择了 qiankun乾坤(qiankun)qiankun(乾坤)是由蚂蚁金服推出的基于Single-Spa实现的前端微服务框架,实质上还是路由散发式的服务框架,不同于本来 Single-Spa 采纳 JS Entry 加载子利用的计划,qiankun 采纳 HTML Entry 形式进行了代替优化。JS Entry的应用限度要求: 限度一个 JS 入口文件图片、CSS 等动态资源须要打包到 JS 里Code Splitting 无奈利用<br/>比照 JS Entry, HTML Entry 应用就不便太多了,我的项目配置给定入口文件后,qiankun 会自行 Fetch 申请资源,解析出 JS 和 CSS 文件资源后,插入到给定的容器中,完满~ ...

March 11, 2021 · 3 min · jiezi

关于微前端:搭建教程手把手从0搭建微前端umiqiankun

开始搭建该文档实用于从0开始搭建微前端利用,学习微前端的demo 以后配置版本 "@umijs/plugin-qiankun": "^2.18.3","umi": "^3.3.3"一、配置基座利用(主利用)新建文件夹命名 mainAPP 进入mianApp执行以下命令 yarn create @umijs/umi-app // 应用umi官网工具创立我的项目yarn // 装置依赖yarn add @umijs/plugin-qiankun -D // 装置qiankun插件注册qiankun,在.umirc.ts书写配置项 /mainApp/.umirc.tsimport { defineConfig } from 'umi';export default defineConfig({ nodeModulesTransform: { type: 'none', }, routes: [ { path: '/', component: '@/pages/index' }, //注册子路由 { name: 'app1', path: '/app1', microApp: 'app1',//对应上一步注册的name } ], //注册qiankun利用 qiankun: { master: { // 注册子利用信息 apps: [ { name: 'app1', // 惟一 id entry: '//localhost:2000', // html entry }, ], // jsSandbox: true, // 是否启用 js 沙箱,默认为 false // prefetch: true, // 是否启用 prefetch 个性,默认为 true }, },//新增配置项完结});也能够新建/mainApp/config/config.ts中配置以上配置,具体拆散可参照umi文档https://umijs.org/zh-CN/docs/... ...

December 31, 2020 · 1 min · jiezi

关于微前端:qiankun-微前端原理与实践

本文来自OPPO互联网技术团队,转载请注名作者。同时欢送关注咱们的公众号:OPPO_tech,与你分享OPPO前沿互联网技术及流动。微前端是指存在于浏览器中的微服务,通常由许多组件组成,并应用相似于 React、Vue 和 Angular 等框架来渲染组件,每个微前端能够由不同的团队进行治理,并能够自主抉择框架。 每个微前端都领有独立的 git 仓库、package.json 和构建工具配置。因而,能够拆分一些巨石利用为多个独立的模块再组合起来,利用间独立保护及上线,互不烦扰。 本文通过一些精简代码的形式介绍微前端框架qiankun的原理及OPPO云在这下面的一些实际。 注:本文默认读者应用过qiankun框架,且文中应用的qiankun版本为:2.0.9。 1. qiankun 的前身 single-spaqiankun 是一个基于 single-spa 的微前端实现库,在qiankun还未诞生前,用户通常应用single-spa来解决微前端的问题,所以咱们先来理解single-spa。 咱们先来上一个例子,并逐渐剖析每一步产生了什么。 import { registerApplication, start } from "single-spa";registerApplication( "foo", () => System.import("foo"), (location) => location.pathname.startsWith("foo"));registerApplication({ name: "bar", loadingFn: () => import("bar.js"), activityFn: (location) => location.pathname.startsWith("bar"),});start();appName: string 利用的名字将会在 single-spa 中注册和援用, 并在开发工具中标记loadingFn: () => 必须是一个加载函数,返回一个利用或者一个 PromiseactivityFn: (location) => boolean 判断以后利用是否沉闷的办法customProps?: Object 可选的传递自定义参数1.1 元数据处理首先,single-spa会对上述数据进行标准化解决,并增加上状态,最终转化为一个元数据数组,例如上述数据会被转为: [{ name: 'foo', loadApp: () => System.import('foo'), activeWhen: location => location.pathname.startsWith('foo'), customProps: {}, status: 'NOT_LOADED'},{ name: 'bar', loadApp: () => import('bar.js'), activeWhen: location => location.pathname.startsWith('bar') customProps: {}, status: 'NOT_LOADED'}]1.2 路由劫持single-spa外部会对浏览器的路由进行劫持,所有的路由办法和路由事件都确保先进入single-spa进行对立调度。 ...

December 7, 2020 · 7 min · jiezi

关于微前端:基于qiankun落地部署微前端踩坑记

前沿:前半年微前端火得一踏糊涂,刚好业务需要上有这样的利用场景,针对目前的微前端解决方案做了技术选型,qiankun作为蚂蚁金服外部孵化进去的微前端解决方案,通过线上利用充沛测验及打磨最初开源,最终抉择qiankun作为咱们云产品架构入口。不过官网文档上对于上线部署文档较少,很多童鞋也可能只是在本地玩玩,没有到真正走通整个闭环,于是联合本身,在将qiankun落地过程中遇到的“那些坑”做个梳理。心愿对你有所帮忙1.???? 茶前点心本文不大篇幅介绍对于qiankun的“前世今生”,更多的设计理念介绍请看文档 如果有想理解其余微前端解决方案的童鞋,也能够回顾下之前树酱分享的微前端那些事举个例子:咱们有个这样的场景,我有个门户Portal的登陆界面(主利用基座),登陆成绩后能够切换不同的子利用,如下有两个子利用A和B,且都在之前是独立部署的,独自能够拜访,然而咱们当初想借助qiankun把他们“嵌”到基座来加载,往下看实操 你可能会问间接用iframe不香吗?真不香,次要几个局限问题 父子利用之间通信问题cookie共享问题(可做单点登陆SSO)交互视图成果不佳 下面是一个通过域名拜访子利用的示意图,接下来咱们看看一个view视图,header头部和sideMenu左侧菜单是属于portal门户的,而右侧区域则是显示切换子利用的视图,预期成果:当咱们拜访dev.portal.com/a该域名时(即切换到子利用A),左侧菜单也会依据不同利用切换不同数据 1.1 注册子利用时应该留神哪些问题????? 啊明同学:qiankun是如何注册子利用的呢?qiankun是通过registerMicroApps(apps, lifeCycles)API来注册子利用的,具体文档请看点我???? 用来实现当浏览器 url 发生变化时,主动加载相应的子利用的性能,联合下面的例子咱们试着在基座main.js注册子利用 次要包含: entry: 子利用的 entry 地址,比方咱们当初有两个子利用A和B,那么这里配置的就是他们的资源拜访域名或iprender:实质上是container的转换,container用来定义子利用的容器节点的选择器或者 Element 实例,这里应用的是理论例子activeRule:子利用的激活规定,即什么路由拜访才会去fetch entry配置的域名或ip,咱们用了getActiveRule来实现匹配,咱们看看getActiveRule的实现,该函数通过传入以后 location 作为参数,而后依据函数返回数值来看,若返回值为 true 时则表明以后子利用会被激活,则去调用entry入口配置 匹配如下 ✅ https://dev.portal.com/a ✅ https://dev.portal.com/a/anyt... ???? https://dev.portal.com/c 匹配胜利后,qiankun 通过 fetch 去获取所匹配子利用的动态资源 1.2 资源拜访跨域如何解决????? 啊呆同学:你这样不会跨域吗?基座 https://dev.portal.com/ 获子利用a的资源 https://dev.monitor.com/a的资源 ,依据浏览器同源策略(浏览器采纳同源策略,禁止页面加载或执行与本身起源不同的域的任何脚本)应该获取不到吧,显著跨域答案:是,因为 qiankun 是通过 fetch 去获取子利用注册时配置的动态资源url,所有动态资源必须是反对跨域的,那就得设置容许源了,简略的设置能够看上面 Access-Control-Allow-Origin:跨域在服务端是不容许的。只能通过给Nginx配置Access-Control-Allow-Origin *后,能力使服务器能承受所有的申请源(Origin)Access-Control-Allow-Headers: 设置反对的Content-Type1.3 子利用加载失败是什么问题????? 啊明同学:跨域解决了,可还是fetch不到子利用a的动态资源?是什么问题咋搞?呈现这个报错:Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in xxx entry ...

December 2, 2020 · 1 min · jiezi

关于微前端:微前端是什么可以带来什么收益

转自掘金原文《微前端到底是什么,能够带来什么收益》 本文将解说微前端诞生的背景,具体讲解微前端概念的原因以及其深刻了解,读完本文,置信你对微前端有一个比拟全面的认知,明确它能够解决您团队以及整个企业什么问题,带来怎么样的收益。一.背景当初很多企业,根本在物理上进行了利用代码隔离,履行单个利用单个库,闭环部署更新测试环境、预公布环境和正式环境。于是,咱们的探讨的是,基于不同利用不同库并独立部署的状况下,如何实现多个利用之间的资源共享? 之前比拟多的解决形式是npm包模式抽离和援用,比方多个利用我的项目之间,可能有某业务逻辑模块或者其余是可复用的,便抽离进去以npm包的模式进行治理和应用。但这样却带来了以下几个问题: 公布效率低下。如果须要迭代npm包内的逻辑业务,须要先公布npm包之后,再每个应用了该npm包的利用都更新一次npm包版本,再各自构建公布一次,过程繁琐。如果波及到的利用更多的话,破费的人力和精力就更多了。多团队合作容易不标准。蕴含通用模块的npm包作为共享资产,“每个人”领有它,但在实践中,这通常意味着没有人领有它。它很快就会充斥芜杂的格调不统一的代码,没有明确的约定或技术愿景。 这些问题让咱们意识到,扩大前端开发规模以便于多个团队能够同时开发一个大型且简单的产品是一个重要但又辣手的难题。 因而,早在2016年,微前端概念诞生了。 二. 微前端概念Micro Frontends 官网定义了微前端概念: Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently.翻译成中文: 从Micro Frontends 官网能够理解到,微前端概念是从微服务概念扩大而来的,摒弃大型单体形式,将前端整体合成为小而简略的块,这些块能够独立开发、测试和部署,同时依然聚合为一个产品呈现在客户背后。能够了解微前端是一种将多个可独立交付的小型前端利用聚合为一个整体的架构格调。 值得注意的几个点: 微前端不是一门具体的技术,而是整合了技术、策略和办法,可能会以脚手架、辅助插件和标准束缚这种生态圈模式展现进去,是一种宏观上的架构。这种架构目前有多种计划,都有利弊之处,但只有实用以后业务场景的就是好计划。微前端并没有技术栈的束缚。每一套微前端计划的设计,都是基于理论需要登程。如果是多团队对立应用了react技术栈,可能对微前端计划的跨技术栈应用并没有要求;如果是多团队同时应用了react和vue技术栈,可能就对微前端的跨技术栈要求比拟高。三. 微前端的劣势同步更新比照了npm包形式抽离,让咱们意识到更新流程和效率的重要性。微前端因为是多个子利用的聚合,如果多个业务利用依赖同一个服务利用的功能模块,只须要更新服务利用,其余业务利用就能够立马更新,从而缩短了更新流程和节约了更新老本。 增量降级因为历史包袱,有团队仍旧存在应用着古老而宏大的前端单体模式,被过期的技术栈或赶工实现的代码品质死死拖住后腿,其水平重大到了让人想颠覆重写。为了防止齐全重写的危险 ,咱们更加偏向于将旧的应用程序逐渐地翻新,与此同时不受影响地持续为咱们的客户提供新性能。 微前端能使咱们更加自在地对产品的各个局部做出独立的决策,让团队能做到继续地减少新性能并且对原有的整体简直不做批改,使咱们的架构、依赖以及用户体验都可能增量降级。 另外,如果主框架中有一个非兼容性的重要更新,每个微前端能够抉择在适合的时候更新,而不是被迫停止以后的开发并立刻更新。如果咱们想要尝试新的技术,或者是新的交互模式,对整体的影响也会更小。 简略、解耦的代码库每个独自的微前端我的项目的源代码库会远远小于一个单体前端我的项目的源代码库。这些小的代码库将会更易于开发。更值得一提的是,咱们防止了不相关联的组件之间无心造成的不适当的耦合。通过加强应用程序的边界来缩小这种意外耦合的状况的呈现。 当然了,一个独立的、高级的架构形式(例如微前端),不是用来取代标准整洁的优良老代码的。咱们不是想要回避代码优化和代码品质晋升。相同,咱们加大做出谬误决策的难度,减少正确决策的可能性,从而使咱们进入胜利的陷阱。例如,咱们将跨边界共享域模型变得很艰难,所以开发者不太可能这样做。同样,微前端会促使您明确并谨慎地理解数据和事件如何在应用程序的不同局部之间传递,这本是咱们早就应该开始做的事件! 独立部署与微服务一样,微前端的独立可部署性是要害。它缩小了部署的范畴,从而升高了相干危险。无论您的前端代码在何处托管,每个微前端都应该有本人的间断交付通道,该通道能够构建、测试并将其始终部署到生产环境中。咱们该当可能在不思考其余代码库或者是通道的状况下来部署每个微服务。做到即便原来的单体我的项目是固定的依照季度手动公布版本,或者其余团队提交了未实现的或者是有问题的代码到他们的主分支上,也不会对以后我的项目产生影响。如果一个微前端我的项目已筹备好投入生产,它应该具备这种能力,而决定权就在构建并且保护它的团队手中。 自主的团队将咱们的代码库和公布周期拆散的更高阶的益处,是使咱们领有了齐全独立的团队,能够参加到本人产品的构思、生产及后续的过程。每个团队都领有为客户提供价值所需的全副资源,这就使得他们可以疾速且无效地口头。为了达到这个目标,咱们的团队须要依据业务性能纵向地划分,而不是依据技术品种。一种简略的办法是依据最终用户将看到的内容来宰割产品,因而每个微前端都封装了应用程序的单个页面,并由一个团队全权负责。与依据技术品种或“横向”关注点(如款式、表单或验证)来组成团队相比,这会使得团队工作更有凝聚力。 四. 微前端计划品种目前国内微前端计划大略分为: 基座模式:通过搭建基座、配置核心来治理子利用。如基于SIngle Spa的偏通用的乾坤计划,也有基于自身团队业务量身定制的计划。自组织模式: 通过约定进行互调,但会遇到解决第三方依赖等问题。去核心模式: 脱离基座模式,每个利用之间都能够彼此分享资源。如基于Webpack 5 Module Federation实现的EMP微前端计划,能够实现多个利用彼此共享资源分享。其中,目前值得关注是去核心模式中的EMP微前端计划,既能够实现跨技术栈调用,又能够在雷同技术栈的利用间深度定制共享资源,如果刚开始调研微前端的话,能够先尝试理解一下EMP微前端计划,或者会给你带来不错的应用体验。 具体的多计划深刻比照剖析,会在下一篇文章《比照多种微前端计划》具体讲解,欢送大家关注wiki博文首发更新。 EMP微前端wiki博文更新目录:基础知识解析微前端到底是什么,能够带来什么收益 比照多种微前端计划 webpack5 module Federation原理学习 EMP的设计架构 多场景应用教程react我的项目如何应用和接入EMP vue我的项目如何应用和接入EMP Vue和React我的项目如何相互近程调用 cocos2d 我的项目如何应用和接入EMP ...

November 10, 2020 · 1 min · jiezi

关于微前端:基于-qiankun-的-CMS-应用微前端实践

图片起源:https://zhuanlan.zhihu.com/p/...本文作者:史志鹏前言LOOK 直播经营后盾工程是一个迭代了 2+ 年,累计超过 10+ 位开发者参加业务开发,页面数量多达 250+ 的“巨石利用”。代码量的宏大,带来了构建、部署的低效,此外该工程依赖外部的一套 Regularjs 技术栈也曾经实现了历史使命,相应的 UI 组件库、工程脚手架也被举荐停止使用,走向了少保护或者不保护的阶段。因而, LOOK 直播经营后盾基于 React 新建工程、做工程拆分被提上了工作日程。一句话形容指标就是:新的页面将在基于 React 的新工程开发, React 工程能够独立部署,而 LOOK 直播经营后盾对外输入的拜访地址冀望维持不变。 本文基于 LOOK 直播经营后盾的微前端落地实际总结而成。次要介绍在既有“巨石利用”、 Regularjs 和 React 技术栈共存的场景下,应用微前端框架 qiankun ,实现CMS利用的微前端落地历程。对于 qiankun 的介绍,请移步至官网查阅,本文不会侧重于介绍无关微前端的概念。 一.背景1.1 现状如上所述,存在一个如下图所示的 CMS 利用,这个利用的工程咱们称之为 liveadmin ,拜访地址为:https://example.com/liveadmin,拜访如下图所示。 咱们心愿不再在 liveadmin 旧工程新增新业务页面,因而咱们基于外部的一个 React 脚手架新建了一个称为 increase 的新工程,新的业务页面都举荐应用这个工程开发,这个利用能够独立部署独立拜访,拜访地址为:https://example.com/lookadmin,拜访如下图所示: 1.2 指标咱们心愿应用微前端的形式,集成这两个利用的所有菜单,让用户无感知这个变动,仍旧依照原有的拜访形式 https://example.com/liveadmin,能够拜访到 liveadmin 和 increase 工程的所有页面。 针对这样一个指标,咱们须要解决以下两个外围问题: 两个零碎的菜单合成展现;应用原有拜访地址拜访两个利用的页面。对于第 2 个问题,置信对 qiankun 理解的同学能够和咱们一样达成共识,至于第 1 个问题,咱们在实际的过程中,通过外部的一些计划失去解决。下文在实现的过程会加以形容。这里咱们先给出整个我的项目落地的效果图:能够看到, increase 新工程的一级菜单被追加到了 liveadmin 工程的一级菜单前面,原始地址能够拜访到两个工程的所有的菜单。 ...

October 22, 2020 · 7 min · jiezi

关于微前端:微前端qiankun从搭建到部署的实践

最近负责的新我的项目用到了qiankun,写篇文章分享下实战中遇到的一些问题和思考。 示例代码: https://github.com/fengxianqi/qiankun-example。 在线demo:http://qiankun.fengxianqi.com/ 独自拜访在线子利用: subapp/sub-vuesubapp/sub-react为什么要用qiankun我的项目有个性能需要是须要内嵌公司外部的一个现有工具,该工具是独立部署的且是用React写的,而咱们的我的项目次要技术选型是vue,因而须要思考嵌入页面的计划。次要有两条路: iframe计划qiankun微前端计划两种计划都能满足咱们的需要且是可行的。不得不说,iframe计划尽管一般但很实用且老本也低,iframe计划能笼罩大部分的微前端业务需要,而qiankun对技术要求更高一些。 技术同学对本身的成长也是有强烈需要的,因而在两者都能满足业务需要时,咱们更心愿能利用一些较新的技术,折腾一些未知的货色,因而咱们决定选用qiankun。 我的项目架构后盾零碎个别都是高低或左右的布局。下图粉红色是基座,只负责头部导航,绿色是挂载的整个子利用,点击头部导航可切换子利用。 参考官网的examples代码,我的项目根目录下有基座main和其余子利用sub-vue,sub-react,搭建后的初始目录构造如下: ├── common //公共模块├── main // 基座├── sub-react // react子利用└── sub-vue // vue子利用基座是用vue搭建,子利用有react和vue。 基座配置基座main采纳是的Vue-Cli3搭建的,它只负责导航的渲染和登录态的下发,为子利用提供一个挂载的容器div,基座应该放弃简洁(qiankun官网demo甚至间接应用原生html搭建),不应该做波及业务的操作。 qiankun这个库只须要在基座引入,在main.js中注册子利用,为了方便管理,咱们将子利用的配置都放在:main/src/micro-app.js下。 const microApps = [ { name: 'sub-vue', entry: '//localhost:7777/', activeRule: '/sub-vue', container: '#subapp-viewport', // 子利用挂载的div props: { routerBase: '/sub-vue' // 下发路由给子利用,子利用依据该值去定义qiankun环境下的路由 } }, { name: 'sub-react', entry: '//localhost:7788/', activeRule: '/sub-react', container: '#subapp-viewport', // 子利用挂载的div props: { routerBase: '/sub-react' } }]export default microApps而后在src/main.js中引入 ...

September 23, 2020 · 7 min · jiezi

关于微前端:GrowingIO-智能运营产品微前端实践

作者:俞展弘GrowingIO 前端开发工程师,次要负责智能经营团队前端开发、gio-design 开发引言GrowingIO 智能经营产品,是 GrowingIO 为客户经营团队提供的一站式、精细化经营治理与数据分析平台。 近期,GrowingIO 智能经营产品团队须要将站内触点等经营性能从 SaaS 平台移植到增长平台上,以反对私有化部署(On-Premise,简称 OP)计划在客户环境中的进行,以此为背景,GrowingIO 经营前端团队在微前端的实际上走了本人小小的一步。 1. 什么是微前端尽管「微前端」三个字这两年曾经在前端畛域被大家所宽泛熟知,但本着谨严写文章的精力还是须要在这里简略阐明一下。 微前端的概念脱胎于服务端的「微服务」概念。最近几年前端世界的趋势就是构建一个功能丰富、弱小的浏览器应用程序(SPA)。 个别一个前端利用通常会由多个独立的团队开发,随着工夫的推移,前端利用的代码规模会一直增长,并且体现得越来越难以保护,成为一个谁看都头疼的巨石利用。 微前端呈现的意义在于将这样一个繁多的巨石利用,转换为多个较为小型的前端利用再聚合为一。各个小型利用能够独立开发、部署,乃至于独立抉择本身的技术栈与依赖,而不影响其余兄弟利用与父利用。 在此基础上简略总结一下微前端须要做到(或者说带来的益处): 利用自治:只须要遵循对立的接口标准或者框架,各个利用能够集成到一起,同时相互之间是不存在依赖关系的。繁多职责:每个前端利用能够只关注于本人所须要实现的性能。技术栈无关:能够在应用 Angular 的同时,又能够应用 React 和 Vue。2. 为什么要拆分微前端如同上一段所说,目前的 GrowingIO SaaS 主站前端利用也是一个随同迭代变得越来越大的巨石利用,但对于经营的前端团队来说,除了公共办法平时不会涉及到大多数不相干模块。 其次,在以后以及可预感的将来,在 SaaS 环境与 OP 环境中经营的业务场景在大部分状况下是雷同的。然而对于前端团队来说,OP 与 SaaS 差异包含但不限于: 采纳了全新脚手架用 GraphQL 取代了 RESTful API 获取根底资源根底组件版本与路由等基础设施与 SaaS 有破坏性更新OP 不须要全副的 SaaS 性能如果采取最原始暴力的开发方式(copy),就须要开发保护两套经营平台前端代码,一套在 SaaS 前端仓库,另一套在 OP 前端仓库。 这样会导致同个性能须要保护两套 codebase,工夫久了 OP 仓库的代码会离 SaaS 骨干代码越来越远,导致保护艰难,同时有概率会一个性能写两次,这对于一个团队来说是不可承受的。 从理论需要登程,咱们当然心愿能做到一套代码适配两个环境,对于同一个性能开发、bug 修复都只须要一次工作量,这样能大大提高人效。所以在性能移植前须要将前端我的项目进行微前端革新。 3. 智能经营产品微前端一小步实现智能经营产品(下称 Marketing)的微前端利用过程大抵划分为两步走:拆 → 装,与此同时解决各种抵触笼罩和兼容问题。 3.1 拆分拆分的过程中咱们须要对 Marketing 利用与 SaaS 利用进行解耦,并针对 OP 环境进行差别屏蔽。 ...

September 17, 2020 · 2 min · jiezi

关于微前端:qiankun-微前端应用实践与部署四

个别状况下,咱们对利用进行配置打包,要对图片字体等资源进行上面配置,使得资源门路失常加载。然而,在微前端模式下,子利用打包部署后,往往会呈现子利用 css 文件外面引入资源门路加载失败的问题,上面就让咱们来探索一下。 ???? 独立利用下的 url-loader 配置: // vue-cli 2 写法module: { rules: [ { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: "url-loader", options: { limit: 10000, // 此处的 utils.assetsPath 是函数,返回依据配置项拼接好的门路,如 static/fonts/[name].[hash:7].[ext] name: utils.assetsPath("img/[name].[hash:7].[ext]") } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: "url-loader", options: { limit: 10000, // 此处的 utils.assetsPath 是函数,返回依据配置项拼接好的门路,如 static/fonts/[name].[hash:7].[ext] name: utils.assetsPath("fonts/[name].[hash:7].[ext]") } } ]}因为 url-loader 的 options 项的属性 publicPath 属性默认是 '',示意相对路径,即打包进去的资源援用 url 都会加上相对路径寻找 static 动态资源入口,比方: /* static/css/app.e99e9aae.css */background-header { background: url(../../static/img/bg_header.790a94f4.png);}所有利用编译打包部署后,当主利用加载子利用,子利用加载本身的 css 文件款式时,因为 其对应的 css 文件外面的图片 url 援用是相对路径,会呈现子利用的资源相对路径拼接主利用 domain 的状况,即子利用的 ../../static/img/bg_header.790a94f4.png 会在主利用的 domain 下进行资源的寻找,导致加载失败 404 的状况。 ...

September 14, 2020 · 2 min · jiezi

关于微前端:qiankun-微前端应用实践与部署三

微前端架构下,主利用有本人的路由模块,同时主利用反对以微前端的形式嵌入业务模块(子利用),如何实现呢? 对于路由qiankun 在主利用初始化会主动监听路由的变动去匹配注册好的子利用路由流动规定,同时 vue 路由也会监听路由变动。 因为主利用有本人的业务模块,须要反对页面刷新,所以采纳 hash 路由模式。qiankun 官网 demo 应用的是 history 路由模式。 那么,采纳 hash 路由模式的话,主利用路由会有 /#/ 的前缀,比方主利用的 resource 组件路由: http://localhost:8889/#/resource假如 history 路由模式下子利用的注册信息为: { name: 'live', entry: '//localhost:7102', container: '#subapp-viewport', activeRule: '/live',}此时 qiankun 只有命中 url 为 http://localhost:8889/live 才会加载子利用。 此处假如应用的路由切换代码为: this.$router.push({ path: '/live'})所以当初切换的 url 是 http://localhost:8889/#/live,显然不能匹配 /live,所以加载子利用失败。咱们须要批改一下子利用注册的 activeRule,使得匹配 hash 路由模式。 为了辨别开主利用的本身模块与子利用的路由区别,子利用的路由减少 /micro 前缀,比方 /micro/live 是子利用的路由。 那么 hash 路由模式下子利用的注册信息变成: { name: 'live', entry: '//localhost:7102', container: '#subapp-viewport', activeRule: '/#/micro/live',}路由切换代码批改为: ...

September 14, 2020 · 2 min · jiezi

关于微前端:qiankun-微前端应用实践与部署二

上面是两种计划的简要形容。 传统部署形式通过配置 nginx 端口到目录的转发。 具体可查看上一篇文章 特点须要对外开放子利用对应的端口,将编译好的利用文件放到对应的配置目录。 docker 部署形式首先构建主利用与子利用的 docker 镜像,通过 docker run 或者 docker-compose 的形式启动容器。 通过配置 nginx 转发规定,匹配拜访门路子利用容器端口。 假如服务器 ip 是 192.168.2.192,主利用容器端口是 8889,子利用容器端口是 7100、7101。 其中利用容器在构建镜像时是实现了 web 服务的,容器跑起来之后在服务器上是能够通过 127.0.0.1:7100 来拜访利用的。 因为前端子利用须要注册到主利用上,须要填写子利用的入口地址。 // index.jsregisterMicroApps( [ { name: 'app1', entry: process.env.NODE_ENV === 'production' ? '//192.168.2.192:7100' : '//localhost:7100', container: '#subapp-viewport', loader, activeRule: '/app1', }, { name: 'app2', entry: process.env.NODE_ENV === 'production' ? '//192.168.2.192:7101' : '//localhost:7101', container: '#subapp-viewport', loader, activeRule: '/app2', } ]}此时服务器须要凋谢的端口是主利用的 8889,子利用的 7100、7101。 ...

September 14, 2020 · 1 min · jiezi

关于微前端:qiankun-微前端应用实践与部署

微前端利用分为主利用与子利用,部署形式是别离编译好主利用与子利用,将主利用与子利用部署到 nginx 配置好的目录即可。 代码仓库 https://github.com/jwchan1996/qiankun-micro-app 别离进入 portal、app1、app2 根目录,执行: 开发模式# portalyarnyarn start# app1、app2npm installnpm run dev生产模式# portalyarn build# app1、app2npm run build主利用主利用 js 文件引入 qiankun 注册子利用,并编写导航页显示跳转逻辑。 <!DOCTYPE html><html lang="zh"><head> <meta charset="UTF-8"> <title>QianKun Example</title></head><body> <div class="mainapp"> <!-- 标题栏 --> <header class="mainapp-header"> <h1>导航</h1> </header> <div class="mainapp-main"> <!-- 侧边栏 --> <ul class="mainapp-sidemenu"> <li class="app1">利用一</li> <li class="app2">利用二</li> </ul> <!-- 子利用 --> <main id="subapp-container"></main> </div> </div> <script src="./index.js"></script></body></html>主利用 js 入口文件: import { registerMicroApps, runAfterFirstMounted, setDefaultMountApp, start, initGlobalState } from 'qiankun';import './index.less';/** * 主利用 **能够应用任意技术栈** * 以下别离是 React 和 Vue 的示例,可切换尝试 */import render from './render/ReactRender';// import render from './render/VueRender';/** * Step1 初始化利用(可选) */render({ loading: true });const loader = loading => render({ loading });/** * Step2 注册子利用 */registerMicroApps( [ { name: 'app1', entry: process.env.NODE_ENV === 'production' ? '//192.168.2.192:7100' : '//localhost:7100', container: '#subapp-viewport', loader, activeRule: '/app1', }, { name: 'app2', entry: process.env.NODE_ENV === 'production' ? '//192.168.2.192:7101' : '//localhost:7101', container: '#subapp-viewport', loader, activeRule: '/app2', } ], { beforeLoad: [ app => { console.log('[LifeCycle] before load %c%s', 'color: green;', app.name); }, ], beforeMount: [ app => { console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name); }, ], afterUnmount: [ app => { console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name); }, ], },);const { onGlobalStateChange, setGlobalState } = initGlobalState({ user: 'qiankun',});onGlobalStateChange((value, prev) => console.log('[onGlobalStateChange - master]:', value, prev));setGlobalState({ ignore: 'master', user: { name: 'master', },});/** * Step3 设置默认进入的子利用 */// setDefaultMountApp('/app1');/** * Step4 启动利用 */start();runAfterFirstMounted(() => { console.log('----------------------------------') console.log(process.env.NODE_ENV) console.log('----------------------------------') console.log('[MainApp] first app mounted');});//浏览器地址入栈function push(subapp) { history.pushState(null, subapp, subapp) }//配合导航页显示逻辑function initPortal(){ //主利用跳转 document.querySelector('.app1').onclick = () => { document.querySelector('.mainapp-sidemenu').style.visibility = 'hidden' push('/app1') } document.querySelector('.app2').onclick = () => { document.querySelector('.mainapp-sidemenu').style.visibility = 'hidden' push('/app2') } //回到导航页 document.querySelector('.mainapp-header h1').onclick = () => { push('/') } if(location.pathname !== '/'){ document.querySelector('.mainapp-sidemenu').style.visibility = 'hidden' }else{ document.querySelector('.mainapp-sidemenu').style.visibility = 'visible' } if(location.pathname.indexOf('login') > -1){ document.querySelector('.mainapp-header').style.display = 'block' }else{ document.querySelector('.mainapp-header').style.display = 'none' } //监听浏览器后退回退 window.addEventListener('popstate', () => { if(location.pathname === '/'){ document.querySelector('.mainapp-sidemenu').style.visibility = 'visible' } if(location.pathname.indexOf('login') > -1){ document.querySelector('.mainapp-header').style.display = 'block' }else{ document.querySelector('.mainapp-header').style.display = 'none' } }, false)}initPortal()docker nginx 配置此处 nginx 次要作用是用于端口目录转发,并配置主利用拜访子利用的跨域问题。 ...

September 14, 2020 · 4 min · jiezi

探索可独立开发和横向扩展的微前端模块化方案

关于前端模块化说到前端模块化,你马上想到的可能就是 cmd、amd、umd 等前端模块化标准,这些是属于文件级别的模块化;或者你会想到 component 的封装、npm 包的封装等等,这些属于组件级别的模块化;或者你会想到将页面切割成很多独立的区块,每个区块是一个模块,这些属于视图级别的模块化;而今天要探讨的是的业务功能级别前端模块化。业务功能级别前端模块化在后台开发人员眼中再熟悉不过了,我们通常说的"用户模块","订单模块","评论模块"等都是从业务功能视角来划分的。随着前端承载的功能越来越厚重,现在已经不只是简单渲染一个视图而已,它往往也包含很多的业务逻辑和状态,所以越来越多的前端工程中也出现了 model、controller、states 等概念,如果前端模块化仅仅停留在文件、组件级别,那么整个工程将变得难以维护和拓展。 业务模块应当是高内聚、低耦合的整体封装看了很多时下流行的前端工程结构,往往是这样: ├── src│ ├── assets│ ├── components│ ├── layouts│ ├── models //vuex或者dva,按业务功能划分模块│ │ ├── user│ │ ├── order│ │ └── comment│ ├── pages│ ├── services│ ├── utils可以看到,在 models(store)这个领域,还是有按照业务功能划分了模块,但是...也仅限于 models 而已,脱离 view,单纯一个 model 模块有什么意义?这样的模块化完整吗?能独立开发吗?能灵活插拔吗?能横向扩展吗? 一个完整的模块应当包含: 一个 model 处理抽象逻辑和状态一组相关的 views,用来展示 model。注意:model 和 view 是一对多的关系一些其它 components 和辅助资源它们应当集中归类到一个目录下面,而不是零碎的分散在各个角落,独立开发的时候我只需要拥有这个目录的修改权限而不是整个工程,插拔模块的时候只需要 copy 或 del 这个目录,而不是翻出各个目录去查找相关文件... 所以我期望的工程结构应当是这样: ├── src│ ├── assets //公用资源│ ├── components //公用组件│ ├── utils //公用工具│ ├── modules //多个独立的业务模块│ │ ││ │ ├── user //用户模块│ │ │ ├── assets //私用资源│ │ │ ├── components //私用组件│ │ │ ├── utils //私用工具│ │ │ ├── model //model│ │ │ └── views //一个或多个视图│ │ │ ├── page1│ │ │ ├── page2│ │ │ ├── list│ │ │ ├── editor│ │ │ └── layout│ │ ││ │ ├── order //订单模块│ │ │ ├── assets //私用资源│ │ │ ├── components //私用组件│ │ │ ├── utils //私用工具│ │ │ ├── model //model│ │ │ └── views //一个或多个视图│ │ │ ├── page1│ │ │ ├── page2│ │ │ ├── list│ │ │ ├── editor│ │ │ └── layout│ │ ││ │ ├── comment //评论模块│ │ │ ├── ...可以看到每个 module 都有一套独立的目录结构,各种资源都被区分为公用资源 和 模块私有资源,所有模块仅依赖公用资源,模块与模块之间切割得十分干净了。 ...

July 6, 2020 · 2 min · jiezi

发布-umijspluginqiankun-230-全面拥抱-qiankun2

两个月前,我们正式发布了 qiankun2.0,在经历了 15+ beta 版本及大量的内部打磨之后,今天我们将正式发布基于 qiankun2.0 的全新的 @umijs/plugin-qiankun。 本次升级在插件层完全兼容 @umijs/plugin-qiankun 之前的版本,所以只是做了 minor 版本的更新。新特性2.3.0 版本在将底层完全迁移至 qiankun2.0 之后,不仅修复了之前 qiankun plugin 的若干问题,同时也带来了一些激动人心的新特性。 配置精简配置微应用时,不再需要手动配置 base 和 mountElementId。 export default { qiankun: { master: { apps: [ { name: 'microApp1', entry: '//test.com/app1',- base: '/app1',- mountElementId: 'app1-root' } ] } }}在此前的模式下,我们需要在主应用中给每个微应用提前准备一个可挂载的节点 mountElementId,以及一个双方提前约定好的路由 /base 才能完成一次微应用接入。 但这种方式会碰到一些麻烦的问题: 容器 加载/卸载 时序问题比如我们的主应用的渲染可能是 异步/时序不确定 的,那么我们必须保证微应用在渲染前,其预备的 mountElementId 容器是已经就绪的状态,否则就会出现子应用 mount 时抛出 Target is not container 之类的异常。此前我们为解决这类问题提供了一个 defer: boolean 的配置,通过开启此配置 + 手动调用 qiankunStart() 的方式完成 qiankun 框架的懒初始化。但这个方式并没有从根本上解决问题,在更复杂的场景(比如每一个微应用的挂载点都可能是异步渲染出来的)下,这个方案还是会有问题。 ...

June 29, 2020 · 3 min · jiezi

如何设计微前端中的主子路由调度

简介: 即便在微前端的内核板块中,路由问题也没有占多大的篇幅……但是它牵涉到集成逻辑、沙箱等核心逻辑;另一方面,想完美地解决路由问题也并不容易,内里存在大量的细节可供挖掘。所以,展开讨论下此问题并不会无趣;而作为一个特别的视角,我们也可以藉由它对整个微前端体系管窥一二。 作者 | 法海即便在微前端的内核板块中,路由问题也没有占多大的篇幅……但是它牵涉到集成逻辑、沙箱等核心逻辑;另一方面,想完美地解决路由问题也并不容易,内里存在大量的细节可供挖掘。所以,展开讨论下此问题并不会无趣;而作为一个特别的视角,我们也可以藉由它对整个微前端体系管窥一二。 问题背景和期望达到的效果领域问题背景对于点进本文的读者而言,相信大家已经很熟悉微前端需要解决的问题场景: 巨石应用的分治开发。新老项目线上并存。三方系统集成。……以上问题场景的具体案例这里不再展开。值得注意的是,根据场景的需求不同,微前端的实施方案会有所细节差异,比如: 三方系统集成的场景下,方案必须要能兼容不同的技术栈;而对于阿里内部项目来说,一般只用考虑 React 跨版本的问题。诸如邮箱这样的多 tab 应用需要能隔离各个 tab 下的子应用;而其他一些独占式界面的应用则不必担心这点,始终维护一个活跃的子应用实例即可。……—— 而本文要讨论的路由问题,在某些场景下可能也不是问题,比如主应用集成的是 widget 粒度的模块,此时 widget 内部并不关心路由,所以只需要处理主应用本身的路由逻辑即可。 但是,在更普遍的场景下,子应用本身也是一个 SPA,有自己的路由逻辑。于是,当主应用集成子应用时,对路由的处理会碰到一系列新的问题。如何解决这些问题,从而实现一个正确的主子路由逻辑?这就是后文将展开的内容。 期望的主子路由效果那何谓「正确的主子路由逻辑」? 不管具体的实现手段如何,我们希望主应用在集成了子应用之后,最终达到如图的效果: 我们虚构了一个主应用叫做 cow-and-chicken,它会集成 chicken 和 cow 两个应用,通过 tab 来切换。默认情况下,主应用会指向 cow 应用,并且,遵循如下的路由效果: 通过一个具体的路径访问主应用,将能调度到子应用的对应路由。比如访问 cow-and-chicken.com/cow/detail 返回 cow 应用的 detail 页面。子应用内部的路由切换后,主应用的路由也同步变化。比如 cow 应用回到首页后,浏览器地址栏将显示 cow-and-chicken.com/cow/。浏览器的前进、后退功能正常使用。同时,我们希望集成过程不需要对子应用作改造,不用额外的约定,也不用担心子应用只能适配诸如独占式的特定主应用场景……总之,解决方案越普适越好。 主子路由调度问题在微前端技术体系中的位置本小节描述了主子路由调度问题在整个微前端技术体系中的位置,如果仅关心路由问题的具体解法,可以跳过这一节。路由问题的解法不是孤立存在的,它会关联到微前端体系中的一些其他要素。理解这些要素之间的逻辑关系能够辅助我们认知整个微前端技术体系。 微前端体系全景这是我所在的阿里云开放平台团队,围绕微前端做的一些建设。 注意到,其中左栏是平台(配置、管控)相关能力,上层是阿里云控制台侧的一些解决方案包装……即是说,大半的工作是贴着业务建设的。对于不同 BU 的团队来说,这些需要根据自己所在业务的特性来定制对应的方案。 而中间下层的「微前端内核」部分,则偏「纯技术」,几乎可以在任何(基于微前端的)业务场景下通用,这部分也更容易让没有阿里云业务概念的读者理解。 微前端内核相关部分展开 上图的高亮部分是和路由问题相关的技术点。我们这里继续展开一下「微前端内核」部分,主要包括: 主应用框架侧的加载、渲染、通信、路由。以及子(微)应用侧的 JS Bundle 运行环境、沙箱。另外的「相关部分」则是: 为了能在子应用容器和主应用框架中正常运行,需要对子应用作改造 —— 这里的改造一般通过工程化工具自动完成。而主应用初始化时需要的子应用信息,则通过配置管理平台来提供。以及常规的脚手架等。图中高亮的部分便是和路由有关的技术点,这些都会在后文提及。 页面状态和前端路由我们先来一个前置的灵魂拷问:为什么一定要有前端路由,它解决什么问题? 事实上,router 技术并非一蹴而就,它是一步步发展成今天这样的 —— Controller在十多年前,经典的 MVC 应用架构在后端大行其道,人们(包括我)自然地想在前端中也实践这一点。 当时按照 MVC 构建后的各个角色形如上图。 ...

June 22, 2020 · 3 min · jiezi