千家信息网

微前端框架导入加载子应用的方法是什么

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"微前端框架导入加载子应用的方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"微前端框架导入加载子应用的方法是什么"吧!下面代码,我
千家信息网最后更新 2026年11月03日微前端框架导入加载子应用的方法是什么

本篇内容主要讲解"微前端框架导入加载子应用的方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"微前端框架导入加载子应用的方法是什么"吧!

下面代码,我指定的entry,就是子应用的访问入口地址

微前端到底是怎么回事呢? 我画了一张图

我们今天不谈其他的实现技术细节,坑点,就谈整体架构,这张图就能完全解释清楚

那么registerMicroApps,到底做了什么呢?

源码解析下,只看重要部分今天:

lifeCycles是我们自己传入的生命周期函数(这里先不解释),跟react这种框架一样,微前端针对每个子应用,也封装了一些生命周期,如果你是小白,那我就用最简单的话告诉你,生命周期钩子,其实在框架源码就是一个函数编写调用顺序而已(有的分异步和同步)

apps就是我们传入的数组,子应用集合

代码里做了一些防重复注册、数据处理等

看源码,不要全部都看,那样很费时间,而且你也得不到利益最大化,只看最精髓、重要部分

无论上面做了上面子应用去重、数据处理,我只要盯着每个子应用,即app这个对象即可

看到了loadApp这个方法,我们可以大概猜测到,是通过这个方法加载

下面__rest是对数据进行处理

loadApp这个函数有大概300行,挑最重点地方看

registerApplication是single-spa的方法,我们这里通过loadApp这个方法,对数据进行处理

上面这个函数,应该是整个微前端框架最复杂的地方,它最终会返回一个函数,当成函数传递给single-spa这个库的registerApplication方法使用

它的内部是switch case逻辑,然后返回一个数组

这是一个逻辑判断

case 0:            entry = app.entry, appappName = app.name;            _b = configuration.singular, singular = _b === void 0 ? false : _b, _c = configuration.sandbox, sandbox = _c === void 0 ? true : _c, importEntryOpts = __rest(configuration, ["singular", "sandbox"]);  return [4  /*yield*/            , importEntry(entry, importEntryOpts)];

重点来了

会通过importEntry 去加载entry(子应用地址)

上面代码里最重要的,如果我们entry传入字符串,那么就会使用这个函数去加载HTML内容(其实微前端的所有子应用加载,都是把dom节点加载渲染到基座的index.html文件中的一个div标签内)

importHTML这个函数,就是我们今晚最重要的一个点

传入url地址,发起fetch请求(此时由于域名或者端口不一样,会出现跨域,所有子应用的热更新开发模式下,webpack配置要做以下处理,部署也要考虑这个问题)

整个importHTML函数好像很长很长,但是我们就看最重要的地方,一个框架(库),流程线很长+版本迭代原因,需要兼容老的版本,所以很多源码对于我们其实是无用的

整个函数,最后返回了一个对象,这里很明显,通过fetch请求,获取了对应子应用entry入口的资源文件后,转换成了字符串

这里processTpl其实就是对这个子应用的dom模版(字符串格式)进行一个数据拼装,其实也不是很复杂,由于时间关系,可以自己看看过程,重点看结果

这里的思想,是redux的中间件源码思想,将数据进行了一层包装,高可用使用

function processTpl(tpl, baseURI) {  var scripts = [];  var styles = [];  var entry = null;  var template = tpl  /*    remove html comment first    */    .replace(HTML_COMMENT_REGEX, '').replace(LINK_TAG_REGEX, function (match) {  /*      change the css link      */  var styleType = !!match.match(STYLE_TYPE_REGEX);  if (styleType) {  var styleHref = match.match(STYLE_HREF_REGEX);  var styleIgnore = match.match(LINK_IGNORE_REGEX);  if (styleHref) {  var href = styleHref && styleHref[2];  var newHref = href;  if (href && !hasProtocol(href)) {            newHref = getEntirePath(href, baseURI);          }  if (styleIgnore) {  return genIgnoreAssetReplaceSymbol(newHref);          }          styles.push(newHref);  return genLinkReplaceSymbol(newHref);        }      }  var preloadOrPrefetchType = match.match(LINK_PRELOAD_OR_PREFETCH_REGEX) && match.match(LINK_HREF_REGEX);  if (preloadOrPrefetchType) {  var _match$matchmatch = match.match(LINK_HREF_REGEX),            _match$match3 = (0, _slicedToArray2["default"])(_match$match, 3),            linkHref = _match$match3[2];  return genLinkReplaceSymbol(linkHref, true);      }  return match;    }).replace(STYLE_TAG_REGEX, function (match) {  if (STYLE_IGNORE_REGEX.test(match)) {  return genIgnoreAssetReplaceSymbol('style file');      }  return match;    }).replace(ALL_SCRIPT_REGEX, function (match) {  var scriptIgnore = match.match(SCRIPT_IGNORE_REGEX); // in order to keep the exec order of all javascripts  // if it is a external script  if (SCRIPT_TAG_REGEX.test(match) && match.match(SCRIPT_SRC_REGEX)) {  /*       collect scripts and replace the ref        */  var matchmatchedScriptEntry = match.match(SCRIPT_ENTRY_REGEX);  var matchmatchedScriptSrcMatch = match.match(SCRIPT_SRC_REGEX);  var matchedScriptSrc = matchedScriptSrcMatch && matchedScriptSrcMatch[2];  if (entry && matchedScriptEntry) {  throw new SyntaxError('You should not set multiply entry script!');        } else {  // append the domain while the script not have an protocol prefix  if (matchedScriptSrc && !hasProtocol(matchedScriptSrc)) {            matchedScriptSrc = getEntirePath(matchedScriptSrc, baseURI);          }          entryentry = entry || matchedScriptEntry && matchedScriptSrc;        }  if (scriptIgnore) {  return genIgnoreAssetReplaceSymbol(matchedScriptSrc || 'js file');        }  if (matchedScriptSrc) {  var asyncScript = !!match.match(SCRIPT_ASYNC_REGEX);          scripts.push(asyncScript ? {            async: true,            src: matchedScriptSrc          } : matchedScriptSrc);  return genScriptReplaceSymbol(matchedScriptSrc, asyncScript);        }  return match;      } else {  if (scriptIgnore) {  return genIgnoreAssetReplaceSymbol('js file');        } // if it is an inline script  var code = (0, _utils.getInlineCode)(match); // remove script blocks when all of these lines are comments.  var isPureCommentBlock = code.split(/[\r\n]+/).every(function (line) {  return !line.trim() || line.trim().startsWith('//');        });  if (!isPureCommentBlock) {          scripts.push(match);        }  return inlineScriptReplaceSymbol;      }    });    scriptsscripts = scripts.filter(function (script) {  // filter empty script  return !!script;    });  return {      template: template,      scripts: scripts,      styles: styles,  // set the last script as entry if have not set      entry: entry || scripts[scripts.length - 1]    };  }

最终返回了一个对象,此时已经不是一个纯html的字符串了,而是一个对象,而且脚本样式都分离了

这个是框架帮我们处理的,必须要设置一个入口js文件

// set the last script as entry if have not set

下面是真正的single-spa源码,注册子应用,用apps这个数组去收集所有的子应用(数组每一项已经拥有了脚本、html、css样式的内容)

此时我们只要根据我们之前编写的activeRule和监听前端路由变化去控制展示子应用即可,原理如下:(今天不做过多讲解这块)

window.addEventListener('hashchange', reroute);  window.addEventListener('popstate', reroute);  // 拦截所有注册的事件,以便确保这里的事件总是第一个执行  const originalAddEventListener = window.addEventListener;  const originalRemoveEventListener = window.removeEventListener;  window.addEventListener = function (eventName, handler, args) {      if (eventName && HIJACK_EVENTS_NAME.test(eventName) && typeof handler === 'function') {          EVENTS_POOL[eventName].indexOf(handler) === -1 && EVENTS_POOL[eventName].push(handler);     }      return originalAddEventListener.apply(this, arguments);  };  window.removeEventListener = function (eventName, handler) {      if (eventName && HIJACK_EVENTS_NAME.test(eventName) && typeof handler === 'function') {          let eventList = EVENTS_POOL[eventName];          eventList.indexOf(handler) > -1 && (EVENTS_POOL[eventName] = eventList.filter(fn => fn !== handler));      }      return originalRemoveEventListener.apply(this, arguments);  };

也是redux的中间件思想,劫持了事件,然后进行派发,优先调用微前端框架的路由事件,然后进行过滤展示子应用:

export function getAppsToLoad() {      return APPS.filter(notSkipped).filter(withoutLoadError).filter(isntLoaded).filter(shouldBeActive);  }

整个微前端的触发流程

到此,相信大家对"微前端框架导入加载子应用的方法是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

应用 前端 函数 方法 框架 数据 源码 处理 重要 就是 事件 内容 字符 字符串 对象 数组 载子 个子 代码 入口 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 新华互联网科技 互联网和科技技术 互联网科技深圳 广州凡科互联网科技 撒么互联网科技公司 互联网科技素材视频竖屏 甘肃拓世互联网科技有限公司 四个字互联网科技公司取名 深圳育鹏互联网科技有限公司招聘 中国互联网十大科技股排名 银川新华互联网科技学校联系电话 群盈汇互联网科技有限公司 互联网科技圈年度人物 怎样加入科技互联网 九思连强互联网电子科技有限公司 广西科技产业互联网是什么 互联网金融运营模式中的金融科技 好易买互联网科技 上海互联网科技园景观 六子台科技互联网展会 中国 科技 互联网 凡科互联网科技 互联网科技的未来发展 北京三清互联网科技 金融科技与互联网金融相同和不同 互联网金融中的现代科技 恒生互联网科技指数跳水 科技赋能视角下互联网保险发展 珠海东科互联网科技有限公司 互联网科技企业文化
0