122.single-spa 01.微应用注册流程

程序员 2024-9-2 09:41:16 40 0 来自 中国

registerApplication 设置项中的app必要传是什么东西?
registerApplication({  name: "appVue2",  app: async () => {    return new Promise((resolve, reject) => {      (function (factory) {        typeof define === "function" && define.amd          ? define(factory)          : factory();      })(function () {        "use strict";        function load() {          return new Promise((resolve, reject) => {            resolve({              async mount() {                console.log("load mount");              },              async bootstrap() {                console.log("load bootstrap");              },            });          });        }        load();      });    });  },  activeWhen: (location) => location.pathname.startsWith("/app-vue2"),});start();registerApplication 方法
function registerApplication(  appNameOrConfig,  appOrLoadApp,  activeWhen,  customProps  ) {      //...省略一些其他的方法      //管理应用,添加一些其他设置项      apps.push(        assign(          {            loadErrorTime: null,            status: NOT_LOADED,            parcels: {},            devtools: {              overlays: {                options: {},                selectors: [],              },            },          },          registration        )      );      if (isInBrowser) {        ensureJQuerySupport();          //重要函数,路由重写        reroute();      }      }reroute 方法,重要作用存储应用的声明周期方法
function reroute() {  var pendingPromises =    arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];  var eventArguments = arguments.length > 1 ? arguments[1] : undefined;  if (appChangeUnderway) {    return new Promise(function (resolve, reject) {      peopleWaitingOnAppChange.push({        resolve: resolve,        reject: reject,        eventArguments: eventArguments,      });    });  }  var _getAppChanges = getAppChanges(),    appsToUnload = _getAppChanges.appsToUnload,    appsToUnmount = _getAppChanges.appsToUnmount,    appsToLoad = _getAppChanges.appsToLoad,    appsToMount = _getAppChanges.appsToMount;  var appsThatChanged,    navigationIsCanceled = false,    oldUrl = currentUrl,    newUrl = (currentUrl = window.location.href);  //调用了start方法后为true  if (isStarted()) {    appChangeUnderway = true;    appsThatChanged = appsToUnload.concat(      appsToLoad,      appsToUnmount,      appsToMount    );    return performAppChanges();  } else {    appsThatChanged = appsToLoad;      //加载app    return loadApps();  }}performAppChanges方法,利用customEvent添加一些自定方法用来监听微应用的一些事故利用,初始化时全部新注册的应用都在loadThenMountPromises内里,然后会在toLoadPromise方法内里加载微应用信息,接下来看toLoadPromise方法
  function performAppChanges() {    return Promise.resolve().then(function () {     //...省略一些代码  customEvent注册自界说事故,通常欣赏器addEventListener就是用来监听事故的      var unloadPromises = appsToUnload.map(toUnloadPromise);      var unmountUnloadPromises = appsToUnmount        .map(toUnmountPromise)        .map(function (unmountPromise) {          return unmountPromise.then(toUnloadPromise);        });      var allUnmountPromises = unmountUnloadPromises.concat(unloadPromises);      var unmountAllPromise = Promise.all(allUnmountPromises);      unmountAllPromise.then(function () {        window.dispatchEvent(          new customEvent(            "single-spa:before-mount-routing-event",            getCustomEventDetail(true)          )        );      });      /* We load and bootstrap apps while other apps are unmounting, but we       * wait to mount the app until all apps are finishing unmounting       */      var loadThenMountPromises = appsToLoad.map(function (app) {          //加载应用        return toLoadPromise(app).then(function (app) {          return tryToBootstrapAndMount(app, unmountAllPromise);        });      });  }toLoadPromise方法,发现这边是个promise,promise内里是调用app.loadPromise的信息,app.loadPromise也是一个promise,这分析我们在调用注册微应用信息的方法时app 属性的值为promise,接下来看app.loadApp,loadApp就是传入的函数,smellsLikeAPromise也是验证app.loadApp的实验结果是否为promise,假如是promise则往下实验,可以看到这边返回的是loadPromise的实验结果。
必须分析的一点app.loadApp方法必须是umd格式的代码,怎样将我们写的一段js代码打包成umd格式进行测试?
利用打包工具,我用的是roolup,利用方法,全局安装rollup,npm i -g roolup
然后利用下令rollup mount.js --file bundle.js --format umd --name "myBundle"
mount.js是我单独写的js文件为了方便打包,bundle.js是指定打包后的文件名, umd是指定打包格式, --name选项,导出的变量为myBundle
也可以参考roolup官网
function toLoadPromise(app) {  return Promise.resolve().then(function () {    if (app.loadPromise) {      return app.loadPromise;    }    if (app.status !== NOT_LOADED && app.status !== LOAD_ERROR) {      return app;    }    app.status = LOADING_SOURCE_CODE;    var appOpts, isUserErr;      //app.loadPromise -> registerApplication中app属性的值为一个异步函数    return (app.loadPromise = Promise.resolve()      .then(function () {        //此处的app.loadApp就相称于见下面一段代码   loadPromise ->  return new Promise(xxx)应用打包结果必要封装为一个promise        var loadPromise = app.loadApp(getProps(app));         //验证加载微应用代码的函数是否为promise        if (!smellsLikeAPromise(loadPromise)) {}        return loadPromise.then(function (val) {          app.loadErrorTime = null;          appOpts = val;          var validationErrMessage, validationErrCode;            //...省略一些验证信息          app.status = NOT_BOOTSTRAPPED;          app.bootstrap = flattenFnArray(appOpts, "bootstrap");          app.mount = flattenFnArray(appOpts, "mount");          app.unmount = flattenFnArray(appOpts, "unmount");          app.unload = flattenFnArray(appOpts, "unload");          app.timeouts = ensureValidAppTimeouts(appOpts.timeouts);          delete app.loadPromise;          return app;        });      })  });}实在加载的流程就是根据registerApplication的传参,实验app属性内里的代码,只不外在single-spa中内里的这部分代码乾坤已经帮我们封装了,我们只必要传入entry和应用访问地址,qiankun会利用import-html-entry会根据我们传的entry,解析出模板信息,css信息和script信息(这部分就不外多说了,之前有写过乾坤资源加载机制的文章,可以参考这篇文章),然后我们又利用打包工具webpack将其打包格式设置为umd格式帮我们做手动打包这部分工作。
在子体系接入微应用时我们必要在子应用中声明几个生命周期函数,qiankun就通过控制声明周期函数来控制微应用的挂载和卸载以此到达子应用切换的目的。
在single-spa内部发现并非有许多的逻辑代码,都是promise,通过注册的app,对其进行管理和控制。
registerApplication({  name: "appVue2",  app: async () => {      //app.loadApp实验的实际就是该段代码,必须返回是umd格式的会有校验,否则会提示报错    return new Promise((resolve, reject) => {      (function (factory) {        typeof define === "function" && define.amd          ? define(factory)          : factory();      })(function () {        "use strict";        function load() {          return new Promise((resolve, reject) => {            resolve({              async mount() {                console.log("load mount");              },              async bootstrap() {                console.log("load bootstrap");              },            });          });        }        load();      });    });  },  activeWhen: (location) => location.pathname.startsWith("/app-vue2"),});
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-23 19:35, Processed in 0.180666 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表