前后端分离开发约定

前后端分离开发约定

遵守约定,可以避免一些不必要的歧义,降低沟通成本。

前后端配合开发流程

划分前后端工作界限,避免前后端工作节奏被相互影响;并行开发之前,一定要确定好接口!!!

  • 前后端理解需求,前端进行部分页面开发,技术难点攻克;后端进行需求分析、数据库设计,确定绝大部分字段名称、类型、各式、描述等;
  • 基于原型/文档,后端设计接口,基于restfull形成swagger接口文档,前端确认后端接口是否符合前端需求。需要确认内容如下:
    • 每一个页面都需要哪些请求,哪些是以前提供过,哪些没有提供过;
    • 请求方法类型,确认使用get还是post等;
    • 请求的url;
    • 请求参数结构、参数名、类型;
    • 返回数据结构、变量名、类型;
  • 前端基于约定好的swagger文档进行页面开发;后端进行业务开发,提供真实数据接口。接口规范定义之后,后期如有变动及时沟通;
  • 前后端进行联调:后端验证接口是否正确,前端提供技术支持;

前后端界限(任务分工)

前端负责展示,后端负责数据处理;不要让前端进行数据的拼接,筛选等操作。

  • 前端
    • 展示后端传递数据,一般不需进行处理就可以直接展示;
    • 处理用户交互,收集数据发送ajax请求;
  • 后端工作
    • code 转 name,同时保留原先的code,前端转换会发送过多的请求,影响展现性能;
    • 页面中多个零散请求,如果可行,合并成一个请求,减少页面请求数量,提高页面展现性能;

ajax约定

数据交互统一使用JSON。

请求约定

基于restfull设计请求url。

  • 正确区分get post put del 等请求含义:
    • get: 获取服务端数据;
    • post: 保存数据到服务端;
    • put: 修改服务端数据;
    • del: 删除服务端数据;
  • 列表页分页参数:
    • 页容量:pageSize
    • 页码:pageNum;
  • 同一个数据出现在任何位置,要统一参数名;比如:房间号roomNo,不要出现roomNumroomCode等其他参数名;
  • 如无特殊需求,传递时间数据,要统一时间格式;
  • 后端需要的参数,要声明字段名、类型、各式(时间)、描述(中文说明字段含义);

成功时返回数据结构(版本一)

适用于接口需要支撑多端情况,通过message可以统一多端提示,如果提示信息需要更改,只改接口,各个端不需要修改,不需要发布。

  • code:业务逻辑结果编码,前端一般用不到,也可以通过code约定成功还是失败;
  • message:后端提供的信息,一般用于展现给用户,错误提示或者成功提示;成功提示如果后端统一给出,那么可以统一各个端(pc、android、ios)的提示信息,要区分开发、生产模式,开发过程中给出完整的错误提示,便于定位错误,生产环境给出用户友好提示并隐藏错误细节;
  • error:后端详细异常对象(或者字符串),用来体现具体的后端错误信息,方便定位问题,只非生产环境提供,生产环境不提供,以免暴露后端细节;
  • data:数据,单个数据为json对象,多条数据为json数组,数据变量命名规则如下:
    • 数据变量驼峰式命名;
    • 数据不必加前缀,比如用户查询,直接返回idnameaccount即可,直接数据对象的属性,不必添加user前缀,不要写成userIduserNameuserAccount
    • 如果是其他对象属性,需要加前缀区分,比如user对象中有角色id,角色id要命名成roleId
    • 同一个数据,无论出现在哪个接口里面,要保证命名统一,减少歧义及沟通成本;比如:roomNum房号,不要出现roomNoroomCode等多个命名;
    • 码表型数据,对应code要转成对应的中文,命名以Name结尾,同时保留原有code(多数业务需要用到原code),比如:roomCode,同时提供roomCodeName用于显示;
    • 时间用于展示,直接格式化成要显示的格式,最好提供原时间的时间戳。如果不提供格式化后的数据,需要提供时间戳,前端可以自己格式化,不要提供其他格式日期,前端格式化时,容易出错;
    • 列表数据,每条件记录以id为唯一标识;一定要存在id属性;
    • 每一个字段要给出描述,不常见字段前端并不知道对应的是什么,沟通成本比较高;
  • total:总条数,分页页面会用到;
  • 其他约定字段等;

成功时返回数据结构(版本二)

适用于接口只对接一端,后端只需要给出错误信息,成功提示前端提供。

  • 直接包含数据:
    • 单个数据为js对象;
    • 多条数据为js数组;
  • 分页查询:
    • list存放数据;
    • total存放总条数;

失败时返回数据结构

接口调用失败、后端逻辑验证失败等,后端要返回错误信息;

  • 所有非预期成功结果都视为失败,比如校验错误、越权操作等
  • 后端要基于不同的开发模式,返回不同的错误提示,生产环境返回友好的用户提示;其他环境返回用户提示+具体错误信息,方便调试。
  • 合理使用http状态码,前端会根据不同的http状态码进行不同的操作,详见如下 http状态码约定;

http状态码约定:

基于不同的状态码,前端会有相应的封装

  • 200:正常业务逻辑,不包含校验错误等业务逻辑,200一定是预期的成功;
  • 400:业务逻辑错误,校验错误,后端主动抛出的错误等,也可以约定为其他cod,视情况而定;
  • 401:需要登录,前端发现ajax返回401,会跳转到登录页面;
  • 403:无权操作,前端一般会给出类似“无权操作”的提示;
  • 404:资源不存在,前端一般会给出类似“您访问的资源不存在”的提示;
  • 500:服务端异常,前端一般会给出“未知系统错误,请联系管理员”;

后端解决跨域

跨域问题由服务端配置或NG代理进行解决,更简单一些。只是开发过程中会遇到跨域问题,实际生产环境使用NG,解决了跨域问题;

  • header一些设置,以nodejs为例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", config().allow_origin);
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("Access-Control-Allow-Credentials", "true");
    res.header("X-Powered-By", ' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
    });
  • cookie问题: ajax跨域请求中的cookie问题

    • 后端Access-Control-Allow-Origin不能设置成*,要指定具体的域名;
    • 前端ajax请求,要设置withCredentialstrue,允许跨域的cookie访问;

通过配置proxy解决跨域

前端开发会启动一个开发模式的服务,如果这个服务支持proxy配置,可以通过配置proxy解决跨域问题

1
2
3
4
5
"proxy": {
"/api": {
"target": "http://localhost:3000"
}
}