前端工程化实践
一
作者说
近两年来,前端工程界发生了非常多的事情。Angular发布了Angular4以及Angular5两个版本,在2018年初又推出了Angular 6.0.0 Beta版,Angular6.0在原Angular5的基础上有了非常大的改进,可谓势如破竹;与此同时,Vue得益于平缓的学习曲线、简单易用的Api等特性,在近一年来也迅猛发展;成为了许多人选择的前端架构。
前端技术的快速发展使得工程师眼花缭乱。Angular、React、Vue等众多前端框架该如何选择、前端代码该如何部署等问题成为了前端工程师争论的焦点。
前端工程化面临的问题
在前端工程化的过程中,有几个比较重要的方面需要考虑:
➤ 前端路由如何实现
➤ 组件的模块化开发
➤ 前端代码的自动化构建
前端路由的实现方式是前后端分离框架下需要重点考虑的问题,前端不仅要考虑工程的多层级架构,还要考虑如何实现前端路由。
由于前端模块化的开发方式,各个组件之间如何相互通信、组件间相互调用的方式变得尤为重要。这部分必须统一进行开发、管理,否则就无法开展多人协作开发,并且在功能、组件、页面不断增加的情况下,前端代码会越来越难以维护。
在前端工程开发的过程中,要提前考虑部署方式。尽可能地使用一套能够满足所有部署方案的方法进行开发,减少部署工作量。
01.前端路由实现方式
前端路由的实现方式为Hash路由与History路由:
Hash路由:例如http://domain.com/#/login.html, 这里的#即为hash;我们通过监听哈希变化触发的事件 —— hashchange来跳转到相应的模块。
History路由:例如http://domain.com/login.html,使用HTML5的History API、pushState()、replaceState()等方法。路由请求发至后端服务器,然后再跳转相应的模块。
传统的做法是使用History路由。使用History路由的好处主要有两点:一是页面的URL比较美观,二是可以使用浏览器自身的特性进行前进后退。但是在单页面应用的情况下,还需要后端服务的支持。
我们在开发公共管理组件的时候并不希望路由发生变化或将请求发送至后端,故而使用Hash路由,这样做的好处是可以通过前端来控制用户权限,在一定程度上为后续系统的扩展提供了方便。
02.组件的模块化开发
前端工程化开发首先要对前端的功能模块进行划分,功能模块间不能有耦合关系。这样做的好处是不同的团队可以同时进行开发,各团队只需要遵循统一的开发标准,最后将各个模块的代码合并即可。
同时在前端开发的过程中,需要将UI组件公共化、标准化,方便后期复用。
03.前端代码灵活部署,实现前后端通讯
在前后端开发模式下,有两种部署方式可以实现与后端进行ajax通信。一种是使用Nginx作为前端服务器,一种是在构建工具中进行请求转发。
1. 使用Nginx作为前端服务器,需要启动Nginx服务,通过配置config文件,实现请求转发到不同的服务器;
Nginx的config文件配置请求转发示例如下:
2. 构建工具的请求转发方式,则是通过构建工具启动server后自带的proxy来进行请求的转发。
对于构建工具的转发方式,我们以webpack作为示例。
通过proxy,启动的webpack server会过滤请求,将请求转发到对应的服务器。对应的示例代码如下:
当前端代码部署在Tomcat容器中时,由于不同项目的ContextPath都不同,每当应用名称改变时,前端工程都需要对ajax请求的路径请求进行修改,给开发工作带来了极大的不便。
对于这个问题有一个一劳永逸的解决办法。即在npm build之前,在前端工程的配置文件中加上homepage变量来进行服务绝对路径的配置。
这样在npm build过程中,前端代码就在服务的根路径下,只需在前端工程的配置文件中加入上述代码,便可重写ajax请求路径。若不想设置固定请求路径,只需要将上述代码修改为:
前端工程化实践分析
以我们项目中微服务团队正在开发的微服务公共管理组件为例,谈一谈前端工程化的实践。
微服务公共管理组件是我们正在研发的基于微服务框架的权限管理框架,
遵循前后端分离、前端模块化的方式进行开发。这样做的好处是使更多的人可以同时进行开发,做到软件的快速交付。同时,前后端分离也是微服务架构下比较好的实践。
抛开前端框架之争,结合公共管理组件的前端设计,我们从开发到部署的整个生命周期来进行分析,主要有以下三个考虑层面:
1. 从功能角度具体对各个模块进行分类,同时根据需要,考虑清楚页面路由的实现方式。
2. 由于公共管理组件后续要支持各个应用系统的建设,所以要求前端具有非常高的可添加性,方便后期进行新的功能添加。
3. 前端工程的架构既要考虑最终上线部署,也要方便开发人员进行开发。
01.模块化开发
前端工程化首先要对前端的功能模块进行清晰地划分,功能模块间不能存在耦合关系。在这种情况下,需要整个团队遵循统一的开发标准,在功能开发完成后将代码合并即可。
我们做了如下功能模块的划分:
➤ 用户认证
➤ 业务字典
➤ 对应用提供Api Gateway
➤ 基础数据服务
➤ 权限服务
图 1 公共管理模块划分
02.模块化的路由及页面实现
模块化的实现主要包含两个方面:路由的模块化及页面的模块化。
路由模块化,解决了父子模块嵌套的问题,在单向数据流的框架中,这一点尤为重要。同时,通过路由嵌套和规范页面URL,整个前端路由的结构更加清晰,能够较为容易地实现页面跳转、及组件、页面间传参。
页面模块化可以提高页面组件的复用率,减少重复的代码。
● 路由的模块化
公共管理组件可以分为5个模块,每个模块分配一个路由地址,通过路由地址可以找到不同的模块。图中展示的是路由地址划分,如下图所示:
图 2 公共管理模块路由
● 页面模块化
就功能页面而言,每个页面要按照组件的方式组成。组件可以划分为Container Components以及Presentation Components。
Container Components用来承载各个不同的公共组件,同时又具有一定布局的功能。Container Components同时也负责与服务端进行通信,获取需要展示的数据,传给Presentation Components。
Presentation Components是具体的功能组件。一般不参与和服务端的交互,只负责展示外部传递的数据。通过这种方式来达到组件使用率的最大化。
如下图所示,页面由Header、SideBar、Content三个组件组成,而每个组件可由多个小组件构成。
图 3 页面模块化
03.部署实践
对于前端部署一般有两种方案:
1. 前后端分离方式,使用Nginx转发请求,这种方式有个好处就是不需要关注前端文件的路径;
2. 在混合模式下,前端代码需要部署在tomcat等类似的中间件中,这种情况下,需要关注Ajax请求路径以及静态资源的路径。
图 4 前后端分离部署
上图为前后端分离的简易方案。在具体部署生产环境时,可以使用nginx进行负载均衡,同时也可以部署多台nginx服务器。如果仍然无法满足性能要求,可以使用LVS+F5/LVS+Nginx等多种方式进行负载均衡。
图 5 混合项目部署
上图为传统应用部署方案,只需要将前端工程编译后的文件部署至Tomcat中间件中。
在传统的部署方式中,需要根据实际场景需要来选择合适的部署方案。而我们前端工程只需要在代码编译打包时根据不同的部署方案修改配置文件,解决ajax请求路径与静态资源路径即可。
前端工程化的未来——微前端
微前端,第一次出现是在2016年的 ThoughtWorks 技术雷达,它将微服务的概念扩展到了前端领域。将一个网站作为许多个组件的组合体,每个组件由独立的技术团队负责,每个团队可以选择自己的技术栈,不需要与其他团队统一,也不需要依赖共享状态和全局变量。
图 6 微前端思想
当然这个理论使非常美好的,不过就目前来看,微前端实施起来依然困难重重,单单只是框架与框架之间的壁垒,就难以突破。
小结
无论采用哪种前端框架,前端开发的思路是一样的。要从工程化的角度去实现项目。这样才能在更短的开发周期内实现前端项目的交付,实现更好的用户体验以及更绚丽的页面效果。
——//////////——
平台云课堂
为邮储科技人带来有价值有温度的阅读
领取专属 10元无门槛券
私享最新 技术干货