现公司从创立之后的很长一段时间内是纯PHP的技术栈,前端、后端都在PHP代码中糅合在一起。新功能越加越多,页面越来越复杂之后,那些混在在PHP代码中的HTML代码越来越不可维护,于是终于有公司里的程序员看不下去,开始了技术革命,将PHP代码抽象成一个个微服务提供API,前端则采用Node+React,解放了前端工程师的生产力,使得新界面的开发越来越顺利,前端程序员也越发不用关心后端的实现了。
故事说到这里听起来皆大欢喜,然而时间长了,新的问题出现了——我们的微服务需要的调整越来越多。PM永远想要尝试新的点子,我们的新需求仍然是更加“花里胡哨”的页面,原先一个页面调用的微服务,在新的需求下需要新的数据,于是和原来比,要做的工作反而多了:在纯PHP的框架下,PHP后端代码和HTML前端代码都在同一个文件中,新需求也可能需要改一个(套)文件;然而在新的架构下,我们即需要调整微服务(PHP文件),又需要去调整前端代码(JS文件),还需要更改两者之间的协议(Apache Thrift),并且还需要严格的遵守Release的顺序和向前兼容的问题。
GraphQL就是在这样的背景下被引入到我们的技术栈之中,关于GraphQL的介绍网上有很多博文,在这里就不展开描述,个人觉得对于我们的产品开发中最有利的两点:
1. 降低了后端API的调整频度。所谓的新“需求”,有很多时候其实就是将数据转移,比如将本来在A页面展示的数据挪到B页面,或者将A和B页面合并成一个页面,抑或是A页面拆成B和C两个页面。在GraphQL引入之前,这样的展示层面的增删改都必将导致后端API的变化,但在GraphQL引入之后,前端程序员只需在Node端调整查询语句,就可以自己定制出自己需要的API。
2. 增加了前端的灵活性和可调试性。前端可以根据需求,理论上可以将整个数据库的数据在一个页面上实现任意的组合,并且由于有graphiql等强大的工具,可以边实现新的页面,边调整自己的查询语言,在出现问题时也可以通过直接执行查询语句来看是否后端返回的数据有问题。
比如有一款社交网络的应用,我们后端有一个getUserByUserId的API,可以查询一个用户的信息(ID,用户名,朋友们的ID),如果我们要做一个页面来显示一个用户的三度好友树,如果不使用GraphQL的解决方案,需要创建一个新的API,在API中先通过getUserByUserId去查询一个用户的信息和所有好友ID,再通过getUserByUserId去获得每个朋友的信息和好友ID,如此循环最后返回。
而如果使用GraphQL的解决方案,我们只需要定义用户和API的Schema:
type User {
userId: Int
userName: String
friends: [User]
}
extend type Query {
getUserByUserId(userId: Int): User //根据用户Id查询单个用户
getUsersByUserIds(userIds: [Int]): [User] //根据多个用户Id查询多个用户
}