背景
从去年开始,前端领域就出现了一个‘微应用’的名词,说的是前端架构的一种设计思路,业内都把它和后端的微服务进行类比,当时忙于公司的项目。没有静下心来好好了解,现在项目结束,再加上最近看的几篇关于前端微服务的文章,(特别讨厌有些文章说的天花乱坠,引用各种高大上的名字,一篇通读下来什么也没有获得)回头一想,我们做的这个架构设计不就是 ‘微服务’吗?
首先说一下前端微服务。
我觉得这是一种架构设计,不是什么新技术,而是多种技术结合的产物,既然是架构设计,那么它就得有使用场景,否则那是空谈,而它的使用场景则是面对平台级的产品解决方案,可以支撑许多web应用,各个应用之间相互独立解耦,又可以不断扩展,不仅易于老代码,老业务的维护,而且开发项目也是游刃有余的。同时对于开发人员来说,这样的架构设计也是独立的,完完全全可以负责单独的web应用,而不需要和别的团队交叉式协作,所以我觉得如果产品是平台级的,做的是解决方案的东西,长期支撑公司发展的,那它的一种设计思路不妨一试,但如果就是几个独立的web应用,比如说公司官网,后台系统,支付系统,这几个一点关联都没有的项目,没有必要来这样做,反而会增加项目本身的难度。
发展过程
微服务的出现我觉得很大程度上是由于spa单页面应用的出现,组件化的出现,从前端历史的发展来看,一个完整的页面从div,a,span标签的组合,到组件化模块的组合,再到应用的组合,一步步过渡发展而来,最初一个页面由几个标签加点文字或者图片组成,主要用来向消费者输出信息,到后来ajax出现,局部刷新人机交互,页面成了按照功能模块来划分,再到现在单页面应用,直接按照应用来划分,每一个应用有自己的一套数据,交互,逻辑,业务等等,页面成了一个容器,或者说是一张幕布,它所做的就是有一个加载机制,更够很多好地处理各个应用的关系和数据通信,
当然也有外部因素,比如各大浏览器厂商对引擎的升级换代,大量交互数据的出现,体验的升级,云部署等等因素,这些诉求让前端领域不再是展示内容那么简单,需要不断突破自我,架构设计应运而生。
微服务里面容器或者称为平台该怎么搭建,怎么加载不同的web应用,应用之间如何数据通信,应用怎么扩展定义,那些平台级核心方法如何处理等等,带着这些问题,结合我司的项目谈谈我的看法及设计思路。
首先有一个最基本的容器
由于项目的复杂特点和背景,我们使用的是jq,别觉得low,用小米加步枪能打败敌人更是说明策略用得好,容器呢则是iframe,应用之间数据通信呢,则是挂载了window这个大对象(如果你阅读过那些有名框架的源代码,发现都是这么做的)。
加载机制
那么如何去加载不同的应用呢,有的做法是将所有的应用js文件在首次全加入进来,每一个应用都是一个独立的大对象,根据地址栏的url组成,获得其中的hash名,这个名字可以是应用的名字,去实例化特定的应用。
或者学习一下vue-router,利用hash改名字,页面不刷新的特点,去按需加载特定的应用js文件。
在或者直接以整个web组件的形式,通过document.append的方式直接插入进来。
我司采用的是第二种,这样的方式可控,加载机制可以自定义处理。毕加索的名言,‘优秀的艺术家抄袭创意,杰出的艺术家剽窃灵感’。
然后各个应用该如何处理呢,怎么才能做到应用独立扩展,而又没有重复代码呢?
按照如今一切js文件皆模块的原则,每个应用的数据,交互逻辑,都是独立的类,或者独立的模块,这个每次扩展就是一个独立的类,包含着新业务的特定数据和逻辑,相互之间使用import进行引用,不会出现代码越来越多,惨不忍睹的情况,而每一个应用它都有一个index.js文件,在每次启动应用的时候去加载这个index文件。
而那些平台级基础层的组件如何操作呢
继承,由于是平台级的基础层,每个应用都会使用,所以在每个应用的逻辑处理时,都需要通过继承来使用平台级的方法,当然每个应用都不一样,平台级的工具要做到‘拿来即用’,应用可以结合自己的数据自由组合这些工具,搭建自己的应用,软件行业里面有句名言,‘架构设计中,没有一个问题是不能通过一层抽象层来解决,如果有,那就是两层’。
注意后期维护
如果不明白这个架构思路,当有新人接收项目,或者出现新的业务的时候,很容易将这个架构打破,可能还是会按照程序员他自己原来的思路去往上堆,如果是个高手他可能会看明白,但是个初中级的段位呢?对吧,最明显的例子就是你可能仅仅加一个小功能,想当然地直接插入进去,虽然成功了,结果很容易忽视它是一个平台级的还是应用级的方法,甚至可能会因为命名而导致你其他应用的部分功能不好使,所以架构规则很重要,同时也会发现,当你只是要添加一个小功能的时候,基于这是一个平台级的应用,合理地增加新功能是一件不容易的事,你可能会质疑它,但随着你的不断深入,抽丝剥茧,你最终会发现,这一切都是有原因可言的。
关于后台通信
由于将项目所有的重心放在了前端,所以弱化了后端的功能,只需要提供最基本的数据增删改查即可。
关于构建部署
如何前端构建部署都是基于webpack工具来操作,平台级的部署也能够体现微服务的特点,独立部署,独立构建,所以在需要结合项目去自定义脚手架,在我司项目中,自定义npm命令,以web应用名来定义,而在webpack文件夹下,目录结构大概是这样:
和其他脚手架类似,有一个最基本的base文件,来做平台级的构建优化,比如压缩静态资源,babel转编译,打包编译,开发环境和构建环境的差异化部署等等,来覆盖整个应用,然后各个应用有自己独立的webpack文件,对webpack有一定了解的人都知道,在应用中继承或者使用baseJS文件,直接require进来即可,由于webpack的几大要素都是通过对象属性来构成的,所以想二次加工这baseJS文件,可以直接修改这些属性即可,如此,便建立了应用自己的构建部署,
在package.json文件中根据命令定义好了特定web应用的webpack文件
而在cmd命令中,只需输入命令npm run XXX,则会在package.json命令中自动加载特定webpack文件
快速理解
项目特别复杂,你又想特别快入手,明白它的架构设计,我觉得抓住两点很重要,
第一,数据流,你得注意它的数据结构和流向,从上到下(父子组件,应用之间),从左到右(兄弟组件,应用之间),数据又是如何展示到各个应用的,有一个整体概念,
第二,事件机制,其实就是数据处理的交互,每一部分的数据都如何产生的,逻辑处理是怎样的,再深入到具体的应用中,去分析它的业务即可,在大学里面计算机专业的课程很大一部分是在教授数据结构和算法,而没有教你一大堆主流框架,我认为,一个应用就是由数据结构,算法,以及本身的业务数据构成的,而那些vue或者react只不过是一种工具,让你更好地实现你的idea。
总结
写着写着,其实发现这个vue的设计思想特别像,我觉得vue的组件化设计其实就是面向对象思路,react更多的是函数式编程,一切js皆文件,以一种web组件的形式来集成应用,无论是哪一种主流框架结构,更多的理解框架本身的设计思路,并融会到自己的项目中,也算是一种借鉴和突破,我认为不一定非得用主流框架,使用一大堆API就是新技术,借鉴思想,修炼js内功,结合业务突破瓶颈,才是最根本的。