微前端qiankun问题You need to export the functional lifecycles in xxx entry终极解决方案
微前端qiankun问题You need to export the functional lifecycles in xxx entry终极解决方案
背景
最近开启了自己Q2的OKR项目,将手上的后台系统,改成微前端模式,方便后续的维护。
目前这个后台系统(知识库管理后台)的部分页面也作为微前端微应用的一部分,嵌入另一个微前端的主应用(综合管理后台)里面的,也就是说它既作为微前端的微应用,也作为了微应用的主应用。
遇到问题
在调试过程中,我尝试将该项目在本地改造成主应用在本地跑起来,同时注册的微应用是它目前的线上版本,但是在实际调试过程中还是遇到了Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in xxx entry。
写本文章时测试发现没问题了。。。上班继续测试下。
Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in xxx entry,我相信这个报错几乎所有接入微前端的同学都碰到过的。
解决过程
这个官网也给了很明确的解决方案。 官网FAQ
原理探索
我觉得应该重点关注图中我划线的1、2、5三点了。
概括来说主要有几点:
- 看入口文件(也就是React或Vue项目的render根节点的那个文件)是否配置了bootstrap,mount等生命周期函数,及时里面的内容是空的,仅一行console也行,但是必须要有。
- 让qiankun打包后的哪个js文件是上述你暴露了生命周期的入口文件
因为qiankun一般是通过解析html的源代码中解析js,并试图读取哪个是entry。html中引入大于一个js的,就要格外注意entry的配置,方便主应用识别到。
上图就是知识库管理后台线上项目的html,可以看到上面引入了三个js,index.xx.js是项目入口,在html中标记了entry向主应用来表明它是entry文件。 作为上述综合管理后台的子应用时,一切正常,但是我在本地调试还是出问题了,Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in xxx entry
在调试过程中发现qiankun会有三次尝试取出生命周期钩子途径
依此进行如下尝试:
- 从js文件的exports中取
- 以沙盒最后设置属性作为属性值在全局变量中取
- 以appName作为属性值在全局变量中取
其中兜底的就是global[appName]
,这个就是我们在webpack的output里面配置的library。
我看了看目前知识库管理后台的webpack配置(用的webpack4)
跟文档基本一样,打包后会window下面挂载全局变量aiagentrobot_app
,只不是项目里面的entry有多个请注意这一点。
一切都很正确,为什么我在本地跑的时候还是出问题了?
那说明连最后兜底的window.aiagentrobot_app也没有兜住啊。
在控制台打印下结果,看看是否挂载了。
熟悉react的会发现,这里面的都是react相关的方法啊。原来是把entry里面的common的内容挂载到window上了。
我们这里探究区分不同的entry的必要性,只想办法怎么让webpack只把entry中的index部分内容挂载在window上。 单纯的webapck.config.js无法实现这样的效果,但是webpack不仅支持读取单个config,还支持读取多个config的数组的。
所以我们只用把自己的webpack.prod.config.js改成类似这样的
module.exports = [{
entry: 'scrc/index.js',
output: {
path: path.join(__dirname, outDir),
filename: "build.[name].[hash].js",
chunkFilename: "chunk.[id].[hash].js",
library: `aiagentrobot_app`,
libraryTarget: "umd",
jsonpFunction: `webpackJsonp_${packageJSON.name}`,
}
}, {
entry: {
common: ['react', 'react-dom'],
atd: ['antd'],
},
output: {
path: path.join(__dirname, outDir),
filename: "build.[name].[hash].js",
chunkFilename: "chunk.[id].[hash].js",
}
}]
也就是只针对你的入口文件加入output.library
的相关配置
此时我们再在控制台打印下兜底的window.aiagentrobot_app,一切正常了。既然兜底的正常了,qiankun怎么也不会报错Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in xxx entry了。
还有个疑惑点,就是为什么知识库管理后台作为微应用在综合管理后台下时没问题,同样作为微应用在知识库管理后台本地环境时不行呢? 我本地是怎么注册微应用的
{
name: 'aiagentrobot',
entry: '//aigatewaycms.fat19.qa.nt.ctripcorp.com',
container: '#test_app',
activeRule: '/cms/',
}
我尝试在综合管理后台的控制台打印兜底的window.aiagentrobot_app
输出的是一个dom节点,原来综合管理后台作为主应用在注册微应用的时候把container的节点也用了跟aiagentrobot_app同样的名字。。。这样给掩盖了重要的调试信息啊。 知识库管理后台在注册微应用给不会采用这种方式,好歹换个id的名字啊。
- 分类:
- Web前端
相关文章
Vue同一路由跳转页面不刷新解决方案及注意事项
默认情况跳转至同一个路由地址(path相同,即使params或者query不同也算同一个)的话,只是浏览器url变了,其它是不会发生任何变化,这就是网友常说的“同一页面跳转,路由变了但是页面不刷新” 阅读更多…
vue发送请求是应该在mounted还是在created生命周期
一个经常会被问到的问题: 为什么不在 created 里去发ajax? created 可是比 mounted 更早调用啊,更早调用意味着更早返回结果,那样性能不是更高? 首先,一 阅读更多…