前端模块化、分布式架构设计与实现(一)

设计思想与目标

概要

主要介绍 Vue 框架下、在工程化的前端项目中如何实现前端模块化、分布式部署方案。css

这也是一份在我所在部门内已经使用近一年的一套前端架构及工程化方案。前端

PS:webpack

这是一部连续剧...ios

这是里的模块指业务功能模块,不是 js 范畴的模块。为便于区分,后文将 js 范畴的模块称为 jsModule.web

这是一段现实场景的回忆录,因此,1. 可能有细节遗漏;2. 它不是一个目标的最简版实现,可能会有点复杂ajax

架构图

难点在哪里

若是是在一个项目内,完成业务与非业务逻辑、业务组件之间的解耦,增长代码引用规范的校验,基本能够知足业务功能的模块化。可是若是指望模块可以独立部署,问题就复杂起来了。npm

独立部署意味着:axios

  1. 代码须要分别打包
  2. 代码托管在不一样的服务器,对应不一样的域名
  3. 不一样业务模块可能访问不一样的后端服务

这会带来一些问题:后端

  1. 对现有研发流程会有影响

曾经的一个 npm run dev 会打包全部代码,webpack或者其余打包工具会解决代码拆分和加载的问题。如今须要:分别打包平台、模块的代码,分别启动平台资源服务、模块资源服务,而后本身加载这个模块的代码并执行跨域

  1. Router 及 Vuex 管理工做方式的变化

模块是后加载的,异步的,模块须要各自负责本身的路由、状态管理,对平台而言这是不可预测并先行定义的,因此 Router 和 Vuex 须要改成动态注入的方式,不过很幸运的是,它们都支持这个特性

  1. 分别打包的代码,若是打包工具配置不当运行时会致使代码引用错误

工程内使用的打包工具是 webpack, 它会注册一个全局的变量(默认是 webpackJsonp), 并以数组的方式管理 jsModule。若是加载另一段一样的方式打包的代码,二者管理的 jsModule 会变得混乱,由于 jsModule 的引用是以数组索引的方式实现的。

  1. 模块的资源管理

模块打包后的结果,可能产生 js、css以及其它静态资源文件,若是指望保留 chunkId 拼接文件名的方式,或者考虑打包配置变动、后期资源变化的状况,模块的最终资源列表将是不可人工枚举的。因此我须要打包工具打包完成后输出一个资源列表,不过 webpack 的插件很优秀,没必要担忧。

  1. 模块资源的加载

考虑一个模块间依赖的场景:若是A依赖B,如何知道B已经加载完了?再考虑一个场景,模块 C 和 D,同时请求加载一样的资源,如何管理?因此我须要知道模块是什么,是否已经彻底加载,还须要一个独立资源加载器避免重复资源请求。

  1. 开发环境下的模块冲突

考虑这样的场景:某系统A(平台)已经集成了模块B(B的资源指向了测试或生产环境地址),开发时如何将模块B的资源指向开发环境?(理想状况下可能指望提供一个纯净的平台,不过现实总会有惊喜)

  1. 多环境下的模块功能测试

一个功能的上线须要通过:开发环境 > 测试环境 > 预发环境 > 生产环境,平台和模块都各自有对应的以上这些环境。以上不一样的流程,除域名不一样之外,代码自己及其运行环境并无任何差异,那怎样保证测试环境的平台加载测试环境的模块资源?生产环境加载生产的?

  1. 跨域问题

这也是处理起来最麻烦的一个问题,模块的请求事实上有两部分:模块资源(js/css等) 和 数据资源(ajax请求)。一般不一样的模块都对应不一样的后端服务(b.com)。当模块集成到平台上运行的时候,实际上发出请求的对象不是模块自己而是平台(a.com)。固然咱们能够选择同一走平台代理,或者要求模块服务器信任平台来源的请求。其次,从开发上讲,原则上禁止代码中的任何形式的域名硬编码,模块中没有域名的记录,那应该怎样让平台知道模块的数据资源请求的域名呢?

  1. 模块隔离

举个例子,平台选择用 axios 提供 http 服务,若是模块A引用axios并提供了并不当心作了全局配置,好比加个 baseUrl,其它的模块怕是会全军覆没了。。。我不但愿每一个模块引入本身http服务,这很混乱,也会带来不少功能重复的代码,我也不但愿采用 iframe,这会带资源和性能的浪费,也会带来布局上的一些坑。我作了部分隔离,以确保不会出现无心识的AOE

  1. 其它问题

实际上也还一些其它细节问题,好比npm run dev 后自动打开浏览器的功能,我须要分别启动平台的服务和模块的服务,这是两个进程,我须要肯定平台的代码编译工做已经完成,因此进程间通讯成了必需品。再好比,抽离了全局的编译命令,hotreload 也让我踩了点坑, 等等。。。

个人目标

  1. 不改变研发习惯

不管是模块仍是平台的开发,保留原来的味道npm run dev, 该有热加载会有,该有自动打开浏览器也会有。固然,配置文件变了~

  1. 模块开发时不用关心细节,好比跨域的代码怎么写

这就有点扯淡了,事实上当时在发展过程当中让前端的兄弟陪我踩了很多的坑,这部分处理也是经历一次大的修改的,固然,如今工做得好不错。

  1. 在以上要求下实现前端的模块化、分布式部署

具体事项

  1. 编译命令改造,支持平台、模块代码打包,这也是解决上面的问题必要的一步
  2. 编译命令集成模板功能(平台和模块的模板)
  3. 模块管理工具(客户端运行)
  4. 增长 eslint 规则,禁止不规范的跨模块代码引用
  5. 分离 http 服务、mock 服务
  6. 文档

接下来。。。

  1. 模块接口设计
  2. 模块管理器的实现
  3. 模块依赖关系的定义与实现
  4. 模块、平台通讯功能实现
  5. 路由管理
  6. 状态管理
  7. 跨域请求处理
  8. 编译工具的改造
  9. 开发模式架构
  10. 开发与测试

以上输出顺序或结构可能会有调整

FLAG: 用自律善待将来的本身

相关文章
相关标签/搜索