micro-zoe
/
micro-app
Public
- Notifications
- Fork 544
-
Star 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Sign up for GitHub
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jump to bottom
从零开始写一个微前端框架-渲染篇 #17
Closed
bailicangdu opened this issue
Aug 3, 2021
· 5 comments
Closed
从零开始写一个微前端框架-渲染篇 #17
bailicangdu opened this issue
Aug 3, 2021
· 5 comments
Labels
docs
Improvements or additions to documentation
Comments
bailicangdu
added
the
docs
Improvements or additions to documentation
label
Aug 3, 2021
bailicangdu
changed the title
手写一个微前端框架-渲染篇
从零开始手写一个微前端框架-渲染篇
Aug 3, 2021
bailicangdu
changed the title
从零开始手写一个微前端框架-渲染篇
从零开始写一个微前端框架-渲染篇
Aug 3, 2021
This was referenced Aug 4, 2021
从零开始写一个微前端框架-沙箱篇
#19
Closed
从零开始写一个微前端框架-样式隔离篇
#20
Closed
从零开始写一个微前端框架-数据通信篇
#21
Closed
ksky521
mentioned this issue
Aug 12, 2021
技术周刊投稿 - CONTENT-AWARE IMAGE RESIZING IN JAVASCRIPT
SearchFeed/weekly#4
Closed
BUPTlhuanyu
mentioned this issue
Aug 17, 2021
微前端
BUPTlhuanyu/blog#4
Open
bailicangdu
closed this as completed
Aug 25, 2021
Perseman
commented
Nov 16, 2021
否则会出现 |
hopperhuang
mentioned this issue
Dec 28, 2021
microservice
hopperhuang/tech-story#41
Open
AursorDev
commented
Jul 8, 2022
@Perseman 这个是在获取js的时候,因为他那个资源地址是相对的比如 /static/js/bundle.js,用fetch 去获取的话,相当于获取了基座应用的,比如:localhost:8080/static/js/bundle.js,然后获取不到就会返回一个 404的html页面,用eval去执行html就会报这个错误, |
AursorDev
commented
Jul 8, 2022
•
edited
edited
@Perseman 解决方法:
|
zlqxk
commented
Jul 11, 2022
写的太好了 |
zhangmingdi
commented
Mar 28, 2023
所有的静态资源都是通过fetch去拿的么,有一些静态资源无法控制跨域怎么办 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
docs
Improvements or additions to documentation
5 participants
前言
自从微前端框架 micro-app开源后,很多小伙伴都非常感兴趣,问我是如何实现的,但这并不是几句话可以说明白的。为了讲清楚其中的原理,我会从零开始实现一个简易的微前端框架,它的核心功能包括:渲染、JS沙箱、样式隔离、数据通信。由于内容太多,会根据功能分成四篇文章进行讲解,这是系列文章的第一篇:渲染篇。
通过这些文章,你可以了解微前端框架的具体原理和实现方式,这在你以后使用微前端或者自己写一套微前端框架时会有很大的帮助。如果这篇文章对你有帮助,欢迎点赞留言。
相关推荐
整体架构
和micro-app一样,我们的简易微前端框架设计思路是像使用iframe一样简单,而又可以避免iframe存在的问题,其使用方式如下:
最终效果也有点类似,整个微前端应用都被封装在自定义标签micro-app中,渲染后效果如下图:
所以我们整体架构思路为:CustomElement + HTMLEntry。
HTMLEntry就是以html文件作为入口地址进行渲染,入上图中的
http://localhost:3000/
就是一个html地址。概念图:
前置工作
在正式开始之前,我们需要搭建一个开发环境,创建一个代码仓库
simple-micro-app
。目录结构
代码仓库主要分为src主目录和examples案例目录,vue2为基座应用,react17为子应用,两个项目都是使用官方脚手架创建的,构建工具使用rollup。
两个应用页面分别如下图:
基座应用 -- vue2
子应用 -- react17
在vue2项目中,配置
resolve.alias
,将simple-micro-app指向src目录的index.js。在react17的webpack-dev-server中配置静态资源支持跨域访问。
正式开始
为了讲的更加明白,我们不会直接贴出已经完成的代码,而是从无到有,一步步实现整个过程,这样才能更加清晰,容易理解。
创建容器
微前端的渲染是将子应用的js、css等静态资源加载到基座应用中执行,所以基座应用和子应用本质是同一个页面。这不同于iframe,iframe则是创建一个新的窗口,由于每次加载都要初始化整个窗口信息,所以iframe的性能不高。
如同每个前端框架在渲染时都要指定一个根元素,微前端渲染时也需要指定一个根元素作为容器,这个根元素可以是一个div或其它元素。
这里我们使用的是通过customElements创建的自定义元素,因为它不仅提供一个元素容器,还自带了生命周期函数,我们可以在这些钩子函数中进行加载渲染等操作,从而简化步骤。
micro-app
元素可能存在重复定义的情况,所以我们加一层判断,并放入函数中。在
/src/index.js
中定义默认对象SimpleMicroApp
,引入并执行defineElement
函数。引入simple-micro-app
在vue2项目的main.js中引入simple-micro-app,执行start函数进行初始化。
然后就可以在vue2项目中的任何位置使用micro-app标签。
插入micro-app标签后,就可以看到控制台打印的钩子信息。
以上我们就完成了容器元素的初始化,子应用的所有元素都会放入到这个容器中。接下来我们就需要完成子应用的静态资源加载及渲染。
创建微应用实例
很显然,初始化的操作要放在
connectedCallback
中执行。我们声明一个类,它的每一个实例都对应一个微应用,用于控制微应用的资源加载、渲染、卸载等。我们在
connectedCallback
函数中初始化实例,将name、url及元素自身作为参数传入,在CreateApp
的constructor中记录这些值,并根据url地址请求html。在初始化实例时,根据传入的参数请求静态资源。
请求html
我们使用fetch请求静态资源,好处是浏览器自带且支持promise,但这也要求子应用的静态资源支持跨域访问。
因为请求js、css等都需要使用到fetch,所以我们将它提取出来作为公共方法。
重新使用封装后的方法,并对获取到到html进行处理。
html格式化后,我们就可以得到一个DOM结构。从下图可以看到,这个DOM结构包含link、style、script等标签,接下来就需要对这个DOM做进一步处理。
提取js、css等静态资源地址
我们在
extractSourceDom
方法中循环递归处理每一个DOM节点,查询到所有link、style、script标签,提取静态资源地址并格式化标签。请求静态资源
上面已经拿到了html中的css、js等静态资源的地址,接下来就是请求这些地址,拿到资源的内容。
接着完善
loadHtml
,在extractSourceDom
下面添加请求资源的方法。fetchLinksFromHtml
和fetchScriptsFromHtml
分别请求css和js资源,请求资源后的处理方式不同,css资源会转化为style标签插入DOM中,而js不会立即执行,我们会在应用的mount方法中执行js。两个方法的具体实现方式如下:
上面可以看到,css和js加载完成后都执行了
onLoad
方法,所以onLoad
方法被执行了两次,接下来我们就要完善onLoad
方法并渲染微应用。渲染
因为
onLoad
被执行了两次,所以我们进行标记,当第二次执行时说明所有资源都加载完成,然后进行渲染操作。在
mount
方法中将DOM结构插入文档中,然后执行js文件进行渲染操作,此时微应用即可完成基本的渲染。以上步骤完成了微前端的基本渲染操作,我们看一下效果。
开始使用
我们在基座应用下面嵌入微前端:
最终得到的效果如下:
可见react17已经正常嵌入运行了。
我们给子应用react17添加一个懒加载页面
page2
,验证一下多页面应用是否可以正常运行。page2
的内容也非常简单,只是一段标题:在页面上添加一个按钮,点击即可跳转page2。
点击按钮,得到的效果如下:
正常渲染!🎉🎉
一个简易的微前端框架就完成了,当然此时它是非常基础的,没有JS沙箱和样式隔离。
关于JS沙箱和样式隔离我们会单独做一篇文章分享,但是此时我们还有一件事情需要做 - 卸载应用。
卸载
当micro-app元素被删除时会自动执行生命周期函数
disconnectedCallback
,我们在此处执行卸载相关操作。接下来完善应用的
unmount
方法:当destory为true时,删除应用的实例,此时所有静态资源失去了引用,自动被浏览器回收。
在基座应用vue2中添加一个按钮,切换子应用的显示/隐藏状态,验证多次渲染和卸载是否正常运行。
效果如下:
一且运行正常!🎉
结语
到此微前端渲染篇的文章就结束了,我们完成了微前端的渲染和卸载功能,当然它的功能是非常简单的,只是叙述了微前端的基本实现思路。接下来我们会完成JS沙箱、样式隔离、数据通讯等功能,如果你能耐下心来读一遍,会对你了解微前端有很大帮助。
The text was updated successfully, but these errors were encountered: