最近在做把graphql融入我的项目中。起因是咱们团队的后端应用的是restful标准。每次查问的时候可能多少都会呈现冗余字段,要剔除这些冗余字段对于后端同学来说没有技术含量又耗时。另外后端同学对于bff层其实不怎么感冒,因为数据聚合对他们来说没什么含量,齐全是对前端同学服务。所以咱们齐全能够引入查问来接手后端同学的bff层。又或者咱们新增了字段须要查问新增的字段后端同学也须要更改。基于这些尝试引入node+graphql。graphql的查问劣势在于前端能够被动管制字段的获取(只有这些字段是能够拜访的)。集成graphql有两种形式。
后端同学间接集成 (java接口(restful或者graphql)-->前端)前端减少两头服务层(java接口-->前端两头服务层nodejs(graphql)-->前端)对于第一种形式,后端同学可能更改会更大,更改接口标准来投合前端可能代价太大且后端同学可能也不太会快乐批改接口标准多进去的工作量。所以咱们选了第二种,引入nodejs中间层作为申请的转发。首先批改前端的代理前端代理到本地nodejs服务,间接应用weboack的proxy代理配置:
proxy: { '/api': { target: 'http://localhost:8080/', changeOrigin: true, }, '/local': { target: 'http://localhost:8080/', changeOrigin: true, pathRewrite: { '^/local': '' }, }, },代理写了两个配置,带有'/api'前缀的间接代理到后端,带有'/local'的要在node中间层做解决。为什么要写要两个配置,因为不是所有的申请都须要应用graphql做解决,这一点在前面应用它的时候就会晓得,它有劣势当然也有劣势。引入你的我的项目要看它能施展多大价值。写了这两个配置之后,带有两个关键字的申请都讲代理到本地node服务的8080端口。接下来配置node中间层。
前端两头服务层的配置两头服务层应用koa2搭建,当然你也能够应用express等等其余。graphql的集成就是用中间件koa-graphql
const Koa = require('koa');const koaStatic = require('koa-static');const views = require('koa-views');const koaBody = require('koa-body');const path = require('path');const mount = require('koa-mount');const { graphqlHTTP } = require('koa-graphql');const { makeExecutableSchema } = require('graphql-tools');const loggerMiddleware = require('./middleware/logger');const errorHandler = require('./middleware/errorHandler');const responseWrapperMiddleware = require('./middleware/responseWrapper');// const decoratorRequest = require('./middleware/decoratorRequest');const axiosRequest = require('./middleware/axiosRequest');const accessToken = require('./middleware/accessToken');const apiProxy = require('./middleware/apiProxy');const typeDefs = require('./graphql/typeDefs');const resolvers = require('./graphql/resolvers');const router = require('./routes/_router');const { APP_KEYS, API_HOST, APP_ID, APP_SECRET } = require('./config');const port = process.env.PORT || 8080;const distPath = path.join(__dirname, '/dist');const getSchema = (...rst) => { const schema = makeExecutableSchema({ typeDefs: typeDefs, resolvers: resolvers(...rst), }); return schema;};const app = new Koa();// logger配置app.use(loggerMiddleware());// 设置动态资源目录app.use( koaStatic(path.resolve(__dirname, './dist'), { index: false, maxage: 60 * 60 * 24 * 365, }),);// 各环境下通用app配置// cookie验证签名app.keys = APP_KEYS;//设置模板引擎ejsapp.use( views(distPath, { map: { html: 'ejs', }, }),);// 异样解决app.use(errorHandler);// req.bodyapp.use(koaBody({ multipart: true }));// 包装申请的返回app.use(responseWrapperMiddleware());// 申请app.use( axiosRequest({ baseURL: `${API_HOST}/audit`, }),);// 申请后端的accessTokenapp.use( accessToken({ appId: APP_ID, appSecret: APP_SECRET, }),);// 间接代理前端的/api申请转发给后端,外部对立做鉴权和参数设置app.use( apiProxy({ prefix: '/api', }),);// koa graphql中间件app.use( mount( '/graphql', graphqlHTTP(async ( request, response, ctx, graphQLParams ) => { return ({ schema: getSchema(request, response, ctx, graphQLParams), graphiql: true, }); }) ),);// 路由app.use(router.routes());app.use(router.allowedMethods());app.listen(port, function() { console.log( `\n[${ process.env.NODE_ENV === 'production' ? 'production' : 'development' }] app server listening on port: ${port}\n`, );});次要看看graphql的配置其余都是koa惯例的中间件配置
...