主要介绍 Vue 框架下、在工程化的前端项目中如何实现前端模块化、分布式部署方案。css
这也是一份在我所在部门内已经使用近一年的一套前端架构及工程化方案。前端
PS:webpack
这是一部连续剧...ios
这是里的模块指业务功能模块,不是 js 范畴的模块。为便于区分,后文将 js 范畴的模块称为 jsModule.web
这是一段现实场景的回忆录,因此,1. 可能有细节遗漏;2. 它不是一个目标的最简版实现,可能会有点复杂ajax
若是是在一个项目内,完成业务与非业务逻辑、业务组件之间的解耦,增长代码引用规范的校验,基本能够知足业务功能的模块化。可是若是指望模块可以独立部署,问题就复杂起来了。npm
独立部署意味着:axios
这会带来一些问题:后端
曾经的一个
npm run dev
会打包全部代码,webpack或者其余打包工具会解决代码拆分和加载的问题。如今须要:分别打包平台、模块的代码,分别启动平台资源服务、模块资源服务,而后本身加载这个模块的代码并执行跨域
模块是后加载的,异步的,模块须要各自负责本身的路由、状态管理,对平台而言这是不可预测并先行定义的,因此 Router 和 Vuex 须要改成动态注入的方式,不过很幸运的是,它们都支持这个特性
工程内使用的打包工具是 webpack, 它会注册一个全局的变量(默认是 webpackJsonp), 并以数组的方式管理 jsModule。若是加载另一段一样的方式打包的代码,二者管理的 jsModule 会变得混乱,由于 jsModule 的引用是以数组索引的方式实现的。
模块打包后的结果,可能产生 js、css以及其它静态资源文件,若是指望保留 chunkId 拼接文件名的方式,或者考虑打包配置变动、后期资源变化的状况,模块的最终资源列表将是不可人工枚举的。因此我须要打包工具打包完成后输出一个资源列表,不过 webpack 的插件很优秀,没必要担忧。
考虑一个模块间依赖的场景:若是A依赖B,如何知道B已经加载完了?再考虑一个场景,模块 C 和 D,同时请求加载一样的资源,如何管理?因此我须要知道模块是什么,是否已经彻底加载,还须要一个独立资源加载器避免重复资源请求。
考虑这样的场景:某系统A(平台)已经集成了模块B(B的资源指向了测试或生产环境地址),开发时如何将模块B的资源指向开发环境?(理想状况下可能指望提供一个纯净的平台,不过现实总会有惊喜)
一个功能的上线须要通过:开发环境 > 测试环境 > 预发环境 > 生产环境,平台和模块都各自有对应的以上这些环境。以上不一样的流程,除域名不一样之外,代码自己及其运行环境并无任何差异,那怎样保证测试环境的平台加载测试环境的模块资源?生产环境加载生产的?
这也是处理起来最麻烦的一个问题,模块的请求事实上有两部分:模块资源(js/css等) 和 数据资源(ajax请求)。一般不一样的模块都对应不一样的后端服务(b.com)。当模块集成到平台上运行的时候,实际上发出请求的对象不是模块自己而是平台(a.com)。固然咱们能够选择同一走平台代理,或者要求模块服务器信任平台来源的请求。其次,从开发上讲,原则上禁止代码中的任何形式的域名硬编码,模块中没有域名的记录,那应该怎样让平台知道模块的数据资源请求的域名呢?
举个例子,平台选择用 axios 提供 http 服务,若是模块A引用axios并提供了并不当心作了全局配置,好比加个 baseUrl,其它的模块怕是会全军覆没了。。。我不但愿每一个模块引入本身http服务,这很混乱,也会带来不少功能重复的代码,我也不但愿采用 iframe,这会带资源和性能的浪费,也会带来布局上的一些坑。我作了部分隔离,以确保不会出现无心识的AOE
实际上也还一些其它细节问题,好比
npm run dev
后自动打开浏览器的功能,我须要分别启动平台的服务和模块的服务,这是两个进程,我须要肯定平台的代码编译工做已经完成,因此进程间通讯成了必需品。再好比,抽离了全局的编译命令,hotreload 也让我踩了点坑, 等等。。。
不管是模块仍是平台的开发,保留原来的味道
npm run dev
, 该有热加载会有,该有自动打开浏览器也会有。固然,配置文件变了~
这就有点扯淡了,事实上当时在发展过程当中让前端的兄弟陪我踩了很多的坑,这部分处理也是经历一次大的修改的,固然,如今工做得好不错。
以上输出顺序或结构可能会有调整