前段时间陆续面试了一波候选人,其中提到最多的就是微前端方案,微前端不像前端框架的面试题那样,它更偏重于项目实战,更加考察候选人的技术水平,不像React,Vue随便一问,就是各种响应式原理,Fiber架构等等烂大街的。
为什么选择微前端作为项目亮点
如果你的简历平平无奇,面试官实在在你的简历上问不出什么,那么只能给你上点“手写题”强度了
作为面试官,我经常听到很多候选人说在公司做的项目很简单,平常就是堆页面,写管理端,写H5,没有任何亮点,我以我一次面试候选人的经历分享给大家
面试官:你为什么选择用微前端做管理端升级,你的项目很庞大么?
候选人: 不是的,其实是我们把两个管理端合并,让用户方便使用。
面试官:咦,竟然这样你们还不如用a标签链接或者nginx转发一下就行了,更加方便,杀鸡焉用牛刀啊
候选人:为了让客户体验到单页面的感觉,体验感更好
面试官:enen....
从这里你会觉得候选人的想法有点奇葩,但是换个角度来想,一定要等到项目庞大拆服务了才用微前端么,我管理端项目一开始就上微前端不行么。其实从这里可以看出来,管理系统使用微前端的成本并不会太大,而且从后面的技术问答中,候选人的微前端还是挺优秀的,各个细节基本都涉略到了。
如果你在公司内部很闲,又是刚好负责无关紧要的运营管理端,那么新的管理端可以一开始接入微前端方案,为未来的技术升级提供一个接口,风险也可控,还能够倒腾技术,简历还能新增亮点,何乐而不为
另外提到H5了,就提多一嘴,H5面向C端用户比较多,这方面更应该关心一些性能指标数据,比如FP
,FCP
等等,围绕这些指标进行优化,亮点不就来了么,这类例子比比皆是,要学会多挖掘
接下来是我作为面试官,经常考察候选人的问题,因为大部分候选人都是用qiankun框架,所以本文以qiankun框架为模板,重点剖析项目实战中微前端中遇到的问题和原理
请解释一下微前端的概念以及它的主要优点和挑战?
微前端是一种将不同的前端应用组合到一起的架构模式。这些应用可以独立开发、独立部署、独立运行,然后在一个主应用中进行集成。这种模式的主要目标是解决大型、长期演进的前端项目的复杂性问题。
主要优点:
- 解耦: 微前端架构可以将大型项目分解为多个可以独立开发、测试和部署的小型应用。这种解耦可以提高开发效率,减少团队间的协调成本。
- 技术栈无关: 不同的微前端应用可以使用不同的技术栈,这为使用新技术、升级旧技术提供了可能。
- 并行开发: 因为微前端应用是独立的,所以多个团队可以并行开发不同的应用,无需担心相互影响。
- 独立部署: 每个微前端应用可以独立部署,这意味着可以更快地推出新功能,同时降低了部署失败的风险。
主要挑战:
- 性能问题: 如果不同的微前端应用使用了不同的库或框架,可能会导致加载和运行的性能问题。
- 一致性: 保持不同的微前端应用在用户体验、设计和行为上的一致性可能会比较困难。
- 状态共享: 在微前端应用之间共享状态可能会比较复杂,需要使用特殊的工具或模式。
- 复杂性: 尽管微前端可以解决大型项目的复杂性问题,但是它自身也带来了一些复杂性,比如需要管理和协调多个独立的应用。
- 安全性: 微前端架构可能会增加跨域等安全问题。
你能详细描述一下 qiankun 微前端框架的工作原理吗?
qiankun 是一个基于 single-spa 的微前端实现框架。它的工作原理主要涉及到以下几个方面:
- 应用加载:qiankun 通过动态创建 script 标签的方式加载子应用的入口文件。加载完成后,会执行子应用暴露出的生命周期函数。
- 生命周期管理:qiankun 要求每个子应用都需要暴露出 bootstrap、mount 和 unmount 三个生命周期函数。bootstrap 函数在应用加载时被调用,mount 函数在应用启动时被调用,unmount 函数在应用卸载时被调用。
- 沙箱隔离:qiankun 通过 Proxy 对象创建了一个 JavaScript 沙箱,用于隔离子应用的全局变量,防止子应用之间的全局变量污染。
- 样式隔离:qiankun 通过动态添加和移除样式标签的方式实现了样式隔离。当子应用启动时,会动态添加子应用的样式标签,当子应用卸载时,会移除子应用的样式标签。
- 通信机制:qiankun 提供了一个全局的通信机制,允许子应用之间进行通信。
在使用 qiankun 时,如果子应用是基于 jQuery 的多页应用,你会如何处理静态资源的加载问题?
在使用 qiankun 时,如果子应用是基于 jQuery 的多页应用,静态资源的加载问题可能会成为一个挑战。这是因为在微前端环境中,子应用的静态资源路径可能需要进行特殊处理才能正确加载。这里有几种可能的解决方案:
方案一:使用公共路径
在子应用的静态资源路径前添加公共路径前缀。例如,如果子应用的静态资源存放在 http://localhost:8080/static/
,那么可以在所有的静态资源路径前添加这个前缀。
方案二:劫持标签插入函数
这个方案分为两步:
- 对于 HTML 中已有的 img/audio/video 等标签,qiankun 支持重写 getTemplate 函数,可以将入口文件 index.html 中的静态资源路径替换掉。
- 对于动态插入的 img/audio/video 等标签,劫持 appendChild、innerHTML、insertBefore 等事件,将资源的相对路径替换成绝对路径。
例如,我们可以传递一个 getTemplate 函数,将图片的相对路径转为绝对路径,它会在处理模板时使用:
微前端是一种将不同的前端应用组合到一起的架构模式。这些应用可以独立开发、独立部署、独立运行,然后在一个主应用中进行集成。这种模式的主要目标是解决大型、长期演进的前端项目的复杂性问题。 主要优点: 解耦: 微前端架构可以将大型项目分解为多个可以独立开发、测试和部署的小型应用。这种解耦可以提高开发效率,减少团队间的协调成本。 技术栈无关: 不同的微前端应用可以使用不同的技术栈,这为使用新技术、升级旧技术提供了可能。 并行开发: 因为微前端应用是独立的,所以多个团队可以并行开发不同的应用,无需担心相互影响。 独立部署: 每个微前端应用可以独立部署,这意味着可以更快地推出新功能,同时降低了部署失败的风险。 主要挑战: 性能问题: 如果不同的微前端应用使用了不同的库或框架,可能会导致加载和运行的性能问题。 一致性: 保持不同的微前端应用在用户体验、设计和行为上的一致性可能会比较困难。 状态共享: 在微前端应用之间共享状态可能会比较复杂,需要使用特殊的工具或模式。 复杂性: 尽管微前端可以解决大型项目的复杂性问题,但是它自身也带来了一些复杂性,比如需要管理和协调多个独立的应用。 安全性: 微前端架构可能会增加跨域等安全问题。 你能详细描述一下 qiankun 微前端框架的工作原理吗? qiankun 是一个基于 single-spa 的微前端实现框架。它的工作原理主要涉及到以下几个方面: 应用加载:qiankun 通过动态创建 script 标签的方式加载子应用的入口文件。加载完成后,会执行子应用暴露出的生命周期函数。 生命周期管理:qiankun 要求每个子应用都需要暴露出 bootstrap、mount 和 unmount 三个生命周期函数。bootstrap 函数在应用加载时被调用,mount 函数在应用启动时被调用,unmount 函数在应用卸载时被调用。 沙箱隔离:qiankun 通过 Proxy 对象创建了一个 JavaScript 沙箱,用于隔离子应用的全局变量,防止子应用之间的全局变量污染。 样式隔离:qiankun 通过动态添加和移除样式标签的方式实现了样式隔离。当子应用启动时,会动态添加子应用的样式标签,当子应用卸载时,会移除子应用的样式标签。 通信机制:qiankun 提供了一个全局的通信机制,允许子应用之间进行通信。 在使用 qiankun 时,如果子应用是基于 jQuery 的多页应用,你会如何处理静态资源的加载问题? 在使用 qiankun 时,如果子应用是基于 jQuery 的多页应用,静态资源的加载问题可能会成为一个挑战。这是因为在微前端环境中,子应用的静态资源路径可能需要进行特殊处理才能正确加载。这里有几种可能的解决方案: 方案一:使用公共路径 在子应用的静态资源路径前添加公共路径前缀。例如,如果子应用的静态资源存放在 http://localhost:8080/static/,那么可以在所有的静态资源路径前添加这个前缀。 方案二:劫持标签插入函数 这个方案分为两步: 对于 HTML 中已有的 img/audio/video 等标签,qiankun 支持重写 getTemplate 函数,可以将入口文件 index.html 中的静态资源路径替换掉。 对于动态插入的 img/audio/video 等标签,劫持 appendChild、innerHTML、insertBefore 等事件,将资源的相对路径替换成绝对路径。 例如,我们可以传递一个 getTemplate 函数,将图片的相对路径转为绝对路径,它会在处理模板时使用: 作者:linwu 链接:https://juejin.cn/post/7252342216843296828 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
对于动态插入的标签,劫持其插入 DOM 的函数,注入前缀。
对于动态插入的标签,劫持其插入 DOM 的函数,注入前缀。
方案三:给 jQuery 项目加上 webpack 打包
这个方案的可行性不高,都是陈年老项目了,没必要这样折腾。
在使用 qiankun
时,如果子应用动态插入了一些标签,你会如何处理?
在使用
qiankun
时,如果子应用动态插入了一些标签,我们可以通过劫持 DOM 的一些方法来处理。例如,我们可以劫持appendChild
、innerHTML
和insertBefore
等方法,将资源的相对路径替换为绝对路径。
以下是一个例子,假设我们有一个子应用,它使用 jQuery 动态插入了一张图片:
方案三:给 jQuery 项目加上 webpack 打包 这个方案的可行性不高,都是陈年老项目了,没必要这样折腾。 在使用 qiankun 时,如果子应用动态插入了一些标签,你会如何处理? 在使用 qiankun 时,如果子应用动态插入了一些标签,我们可以通过劫持 DOM 的一些方法来处理。例如,我们可以劫持 appendChild、innerHTML 和 insertBefore 等方法,将资源的相对路径替换为绝对路径。 以下是一个例子,假设我们有一个子应用,它使用 jQuery 动态插入了一张图片: 作者:linwu 链接:https://juejin.cn/post/7252342216843296828 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我们可以在主应用中劫持 jQuery 的 html
方法,将图片的相对路径替换为绝对路径:
beforeMount: app => { if(app.name === 'my-app'){ // jQuery 的 html 方法是一个复杂的函数,这里为了简化,我们只处理 img 标签 $.prototype.html = function(value){ const str = value.replace('<img src="./img/my-image.png">', '<img src="http://localhost:8080/img/my-image.png">') this[0].innerHTML = str; } } }
在这个例子中,我们劫持了 jQuery 的 html
方法,将图片的相对路径 ./img/my-image.png
替换为了绝对路径 http://localhost:8080/img/my-image.png
。这样,无论子应用在哪里运行,图片都可以正确地加载。
在使用 qiankun
时,你如何处理老项目的资源加载问题?你能给出一些具体的解决方案吗?
在使用
qiankun
时,处理老项目的资源加载问题可以有多种方案,具体的选择取决于项目的具体情况。以下是一些可能的解决方案:
- 使用
qiankun
的getTemplate
函数重写静态资源路径:对于 HTML 中已有的img/audio/video
等标签,qiankun
支持重写getTemplate
函数,可以将入口文件index.html
中的静态资源路径替换掉。例如:
start({ getTemplate(tpl,...rest) { // 为了直接看到效果,所以写死了,实际中需要用正则匹配 return tpl.replace('<img src="./img/my-image.png">', '<img src="http://localhost:8080/img/my-image.png">'); } });
劫持标签插入函数:对于动态插入的 img/audio/video
等标签,我们可以劫持 appendChild
、 innerHTML
、insertBefore
等事件,将资源的相对路径替换成绝对路径。例如,我们可以劫持 jQuery 的 html
方法,将图片的相对路径替换为绝对路径:
beforeMount: app => { if(app.name === 'my-app'){ $.prototype.html = function(value){ const str = value.replace('<img src="./img/my-image.png">', '<img src="http://localhost:8080/img/my-image.png">') this[0].innerHTML = str; } } }
- 给老项目加上 webpack 打包:这个方案的可行性不高,都是陈年老项目了,没必要这样折腾。
- 使用 iframe 嵌入老项目:虽然
qiankun
支持 jQuery 老项目,但是似乎对多页应用没有很好的解决办法。每个页面都去修改,成本很大也很麻烦,但是使用 iframe 嵌入这些老项目就比较方便。