angular html 立即执行_Angular 微前端

转眼间接手这个Angular团队大半年了. 时隔多年又和 Angular 这个框架相遇, 感慨颇多. 在安全类的公司, 业务又多以后台类型的应用为主. Angular 确实是个不错的选择. 社区里前有 singleSPA , 后有阿里某兄弟出的 qiankun , 徐海峰同学的plante 都挺好的, 突然觉得喜欢Angular的兄弟姐妹还挺多, 哈哈.

为什么要上微前端这个架构呢? 首先他很热门[手动微笑]... 团队里最核心的是一个老项目, 本身也是基于Angular的, 模块很多, 这种服务于政企的项目基本就有无限种定制的可能. 库里分支林林总总, 模块内的逻辑判断错综复杂. 整个库庞大不说, 上手的成本变大, 增加功能, 修正bug的风险也变大. 于是才有了拆分的想法.

基本上也是拆成一主多子的形式, 主应用负责加载和公共部分, 比如菜单和公共头这种组件. 子应用负责具体的业务逻辑. 相比之前拆成多个独立的SPA来说, 第一体验变好了, 不用刷新页面了. 公共的部分终于也有了统一维护的地方, 不用每个应用再打包一遍.

啰嗦半天了, 还是直奔主题吧, 又不是写演讲稿.

对于我这种不熟的人来说, 第一步往往是最困难的, 压根不知道是怎么启动的. 下面这段代码脚手架生成的, 估计大家都长一个样

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

事后想想其实挺傻的, 太注重于形式, 不像Vue或是React就理解不了了. 上面这段代码就是在启动, 做为启动器, 它必然不是立即执行的, 需要把它做一次包装. 类似这样的.

const bootstrapModule = () => {
  return platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.error(err));
};

怎么启动的问题解决了, 就到了怎么加载的问题. 编译出来的文件是有hash的, 怎么确定文件名就是第一个问题, 先说怎么解决

webpack-assets-manifest
plugins: [new WebpackAssetsManifest()]

过年那会看 qiankun 实现的好像是解析 index.html 然后拿到的资源, 但是这个插件会生成一个 manifest.json 的文件, 里面描述了加载资源的对应关系:

{
  "main.js": "main-es2015.14cfd9059a95d872a670.js",
  "polyfills-es5.js": "polyfills-es5.28641362adfd90707b20.js",
  "polyfills.js": "polyfills-es2015.88041870e993ea4af105.js",
  "styles.css": "styles.3ff695c00d717f2d2a11.css"
}

加载就涉及到隔离不隔离的问题. CSS Angular都是自带命名空间的 [手动点赞]. 只有加载外部的比如ng-zorro css的时候才有可能冲突(而且还属于特别情况). 社区里说得最多的还是JS的隔离. 解决方案基本也是把代码放到闭包里 eval 一下. 我觉得一个team的人来开发, 这个问题就变得不是那么重要了. 于是加载方案就很简单, 直接打上 script link 标签就行了. 也可以在这些标签上打 id . 必要时还可以卸载掉.

后面是路由的问题. Angular 只有路由没有设置正确报错之后会自己跳到 / 去. 当在子应用里设置了路由

{
	path: 'security-analysis',
	loadChildren: () => import('a.module').then(m => m.SecurityAnalysisModule)
}

请务必在主应用里也设置, 主子应用本质上来说是多个SPA, 属于互不相通的情况. 如果每个子路由都要在两个地方出现就显得比较麻烦了. 这里我用了徐海峰同学的方案

{
	path: '**',
	component: EmptyComponent
}

一步到位把所有的子路由都给匹配上.

到此为止, 单纯的测试应该就可以跑了.

刚才说了路由既然不是互通的, 那同步就成了必然的事情. 那不同步能不能跑起来? 诚然是可以的. 只是状态有些问题, 你马上就能遇见导航菜单和的激活状态不正确的问题. 好了, 路由的改变是有事件通知的, 那么剩下的问题就是怎么拿到这个 Router 的实例了.

platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .then((moduleRef: NgModuleRef<AppModule>) => {
      const router: Router = moduleRef.injector.get(Router);
    });

查文档的时候我是真的觉得自己对这个框架一无所知, 勉强只算是个会用罢了. 原来 bootstrapModule 返回的是个Promise, 并且能直接拿到 module 的引用. 后面就简单了, 监听事件, 判断, 同步即可. 对了, 记得同步是双向的.

最后无非就是怎么注册, 怎么通讯的问题了. 我是选择了在 window 上挂全局对象和函数的方案. 在内部做分享的时候, 有同学问都拆分成这样了还需要做通讯么? 其实考虑到项目的类型是有的. 最典型的就是一些需要轮询下载状态的业务, 比如日志下载. 也有在主应用里保持一个 ws 的情况.

差不多也就写到这里. 如果有幸这篇文章能被你搜索到并且还能读到这里, 就现在这个时间来说, 我是推荐你自己去造轮子的. 社区里也没什么特别成熟的方案, 自己也能对框架更熟悉些. 后面的难点我觉得更多的是项目管理. 这么些个子应用版本怎么管理, 怎么通过便利的方式能打包, 交付等等. 有时间再写一个吧.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值