上周没有更新原创技术文章,缘由是忙着重构一个新接手的项目,此项目由于项目技术负责人离职,虽然投入人力持续增多,前端达到4人,后端3人,但由于新参与的童鞋对代码结构和业务的理解,致使项目开发了一个多月,还有一堆问题,达不到上线要求。接手项目以后,一开始对项目业务场景和代码进行简单的了梳理,跟了一天项目,观察提测后FE+RD的状态,本身也动手改了一天代码,无论是FE+RD包括本身都以为实在是太难受了,小坑大坑不断,因而决定重构。重构不是我的冲动,而是的的确确存在各类大大小小的问题:css
接口太碎:项目自己按照Vue组件化开发,可是页面每一个组件独自采用vuex+ajax请求管理本身的数据,好比:首页由轮播图、各类列表和用户信息展示组成,致使首页从上到下7~8个模块,每一个模块都各自发本身的请求,访问首页须要同时发出8个ajax请求前端
由于「1」提到的,单个组件数据都是使用Vuex进行管理,致使Vuex的store太乱:并且FE按照组件去开发,各自跟后端RD兑接口、联调,可是没有人来统筹安排,致使大量重复工做;除此以外,action和mutation中的业务逻辑代码太多,而不一样页面须要不一样的数据格式,则致使:vue
或者在mutation当中对数据进行从新整理node
或者新开个接口,这样就形成接口愈来愈多,mutation部分代码愈来愈重。web
一开始设计或者沟通有误。好比:用户信息相关的接口,须要传入用户id(uid),而不是经过登陆cookie从passport获取;第三方接口须要用户信息,居然请求的时候将cookie发给对方(幸亏cookie是http only的,没有调通被我及时发现)ajax
重复代码太多,抽象能力太差。一份代码在多个地方复制,致使代码改来改去最后都不知道哪里改了哪里没改vuex
命名太乱,包括url、方法名之类,还有错别字,getAdcontent(用户地址信息),getmaildetail(用户地址信息)编程
研发人员缺少全局意识,只管本身的代码,而不关心整个流程。因为先后投入人较多,没人对整个项目有把控,只能面向本身的需求编程。好比:积分获取页面,获取成功以后,联调成功,可是实际在积分获取列表页面却没有相关的记录信息;在好比:任何用户均可以领走别人的奖品,缘由后端没作奖品是不是当前登陆用户获取的校验后端
问题定位能力不够,碰见问题一调就是半天,找不到根本问题api
介绍下项目背景:
此项目是一个用户积分任务和消费项目,一些页面须要用户登陆,页面主要包括:首页、任务+列表、商品+列表、我的信息和记录以及其余类(说明和规则等)
项目用Vue+yog2编写,ajax请求部分使用vue resource
整个项目仍是用Vue+yog2来写,针对进入页面分为两种状况:
第一次经过网站URL进入某个页面,我称为:「首次后端渲染」
非首次已经进入页面URL后,用户点击连接在项目内跳页,我称之为:「非首次跳转」
整个流程整理以下:两个流程从「两个小人」开始看起

代码流程以下:
router → middleware → page/api action → model → ral请求数据复制代码
其中在action部分,专门写了个 baseAction
函数,封装了重复的代码,使用时传入用于获取数据的model方法和处理数据的方法便可。
render部分,针对页面第一次请求须要将页面数据放在HTML片断中chunk输出,而不是经过ajax请求(为何不用vue ssr,能够看下历史公众号文章《Vue SSR 从入门到Case Study》,以后单页内跳转是ajax请求)。详细代码以下:
client.tpl 部分代码:

baseAction 部分实现chunked

client主要流程是:
vue router → created时期 判断是否有页面数据 →复制代码提交mutation(有数据),dispatch action(异步拉取数据)→ state触发修改,页面dom生成复制代码
这部分流程图主要展示是Vuex和Vue resource部分的代码,经过Vuex的dispatch action,触发Vue resource的异步请求,等返回数据则commit mutation。
通过改造后整个流程变成:
「首次后端渲染」:此时须要后端渲染主要HTML+页面数据,利用chunked,先将不依赖后端数据部分返给浏览器,页面数据和后面的HTML拿到数据后再返给浏览器。 client.tpl
被「一分为二」:HTML[0] + HTML[1]
将页面通用的css和js lib库,放在HTML[0]中,首先返回,浏览器先解析下载
业务代码初始化代码放在HTML[1], 等到获取到后台API数据一块儿返回
「非首次跳转」:这是一个单页应用的流程,用户点击连接,实际走的是vue的router,而后出发vue页面渲染,URL是经过history pushState mode更改实际URL,这时候若是强刷或者复制url在浏览器打开,又走「首次后端渲染」
vue页面渲染须要的数据是经过vue-resource发起ajax请求,拿到数据以后commit mutation改变state
以前代码每一个组件都单独ajax请求本身的数据,致使Vuex的module特别多特别乱,并且后端api接口太多太碎,很差维护。最后开发的童鞋本身都在群里抱怨,找个action或者mutation都不知道在哪一个文件内,须要搜代码。。
页面view相关的数据才使用Vuex来管理,页面功能性ajax(例如签到、兑换)不要使用vuex;「首次后端渲染」和「非首次跳转」的view数据都经过commit mutation来修改state,最终映射到DOM表现上;功能性ajax则在组件内本身发请求实现,保持组件内聚;
P.S:这就是「贫血组件」和「充血组件」的区别,自己组件内的状态和逻辑都放在全局store管理,会增长store复杂度,下降效率(代码性能和开发效率)
收敛是根据业务页面作的,前文提到:
页面主要包括:首页、任务+列表、商品+列表、我的信息和记录以及其余类(说明和规则等)
其中须要数据的有:首页、任务(详情、列表)、商品(详情、列表)和我的中心四个。
改造前module:

改造后module针对业务梳理的四个大页面内容,保留了四个:

复用后端接口数据格式,减小mutation数据处理逻辑
改造前不少action存在下面的代码(注意箭头部分):

其中这个循环主要作两件事情:修改 type
、修改 img_url
为 url
,实际根本没有必要:
修改 type
:实际这已是页面view层的逻辑了,在vue的模板或者computed中作更合适
修改 img_url
为 url
:这里实际是产品的封面图,改为 url
反而更不合适了,并且致使了数据不一致
代码能够直接用 item
便可!即不须要作额外的循环处理,保证数据一致性,避免前端的二次设计
以前全部的api都是走了一个 proxy
,经过node转发一下,直接到了后台API接口,代码以下:

看似很方便甚至有点暗爽的实现,实则带来了下面的问题:
接口非显性声明,下降可控性,形成无法枚举有多少接口,各个接口须要什么参数,增长维护成本
安全性!后台这个服务是彻底暴漏给了前端,若是存在敏感的接口,前端js就能够直接透传利用
改造后的代码放在model层,供「首次后端渲染」和「非首次单页」ajax请求使用:
除了作代码重构改造外,还在间隙中作了一些优化,这里记录一下:
详见本文「后端node server部分代码」和「后端渲染+SPA」
不少页面设计会在首页和列表页面存在有产品的title、图片和简单的一些meta,例以下图:

点击连接进去详情页面能够直接利用,这部分数据咱们作了复用。
实现方法是:页面点击的时候,将该条数据内容commit给下一个页面的mutation。
缓存在node和前端Ajax API多有,后端node主要缓存的是首页,由于首页须要请求4个接口(接口梳理后),其中三个接口是跟用户登陆态无关的,这三个接口能够用lru-cache缓存起来。
前端的ajax api缓存是在 get
请求增长的,能够根据实际状况用,根据url做为key,使用sessionStorage存储(同时cache类本身实现了缓存时间)
除了优化外,我在介绍下两个技巧:单页切换view的loading和统一的错误处理。
在单页跳转内,下一个view须要API请求获取数据,而后才能渲染,这时候须要加载个loading显示(或者作个切换动效)。
原理是:
利用eventBus,在router中添加两个事件
closeLoading
和vue.action.error
,分别用于「关闭loading」和「展示页面数据错误的错误页」loading展示在router的
beforeEach
的钩子内实现,loading的事件在vuex的action获取数据成功以后发送错误的触发有vuex 的 action / mutation 来发送事件
eventBus也不用本身写,能够直接用Vue实例的 $on
、 $emit
、 $once
等就够了,代码以下:
import Vue from 'vue'复制代码export default new Vue()复制代码
重构主要作的事情是:
统一接口请求,从新梳理API;
收敛Vuex store设计(包括mutation/action的聚合,state简化);明确Vuex的使用边界
明确组件职责边界,划分「充血组件」与「贫血组件」
抽象封装重复的代码逻辑
作了一些简单优化
说下成果:项目已经delay好久,从4月初到5月初已经一个月了还没上线,接手项目是五一前,整个重构共2我的力用了三天完成95%的工做,目前已经提测,
下面是重构项目的团队内部问题总结:
项目开发中必定要有大局意识,虽然如今项目可能是分组件来的开发方式,可是开发前要跟你们交代清楚约定、规范,什么该作什么不应作;
技术负责人多 check 代码,防止错误的道路上越行越远;
要有全局意识,关注整个流程,不要只看到本身的「一亩三分地」,好比:在某个商品页面,购买/兑换成功了,不要认为没有问题了,可能记录页面尚未展示(后台接口没有入库);
Don’t repeat yourself!看见重复代码就浑身难受,「抽象」能力是工程师的基本能力。
加强debug能力,发现问题直觉就能判断出来哪一个环境,而后针对性debug