Tags:NodeTypeScriptkoa2
Category: Back End
将 koa2/nodejs 项目 使用 typescript + koa + graphql 重构(历险记)
- 为了尽快适应 typescript 开发, 所以决定将个人网站的后台使用 ts 重构
项目补充安装 koa ts graphql 相关依赖
- devDependencies 都是一些 koa 的类型描述文件,方便 ts 类型解析
"dependencies": {
"@koa/cors": "^3.0.0",
"@types/graphql": "^14.5.0",
"axios": "^0.19.0",
"graphql": "^14.6.0",
"graphql-tools": "^4.0.7", // 这个很有用 合并多个graphql的schma
"koa": "^2.10.0",
"koa-bodyparser": "^4.2.1",
"koa-graphql": "^0.8.0", // graph 在koa搭建的依赖
"koa-mount": "^4.0.0", // 这个已经废了等一下就删除
"koa-router": "^7.4.0",
"mongoose": "^5.7.5"
},
"devDependencies": {
"@types/koa": "^2.11.1",
"@types/koa-bodyparser": "^4.3.0",
"@types/koa-graphql": "^0.8.3",
"@types/koa-mount": "^4.0.0",
"@types/koa-router": "^7.4.0",
"@types/koa__cors": "^3.0.1",
"@types/mongoose": "^5.7.1",
"@types/node": "^13.7.1",
"ts-node": "^8.6.2", // 本地运行ts 代码的运行时依赖
"typescript": "^3.7.5"
}
- 因为 nodemon 已经全局安装了 本项目就不安装了
typescript 项目初始化
tsc --init
// 会多出一个tsconfig.json
- tsconfig.json 配置学习连接tsconfig.json
为什么不用 apollo-server-koa?
- 因为迁移很多 restful api 到 graph 都没有测试
- 目前服务大多数还是 restful, 所以不想让 graphql 主导整个后端服务所以将 graphql 当作一下子服务先把
开始
- 修改所有.js 文件成 ts, 并且加上类型校验(略...) 很累
- 加入 graphql 服务, 在启动项目入口文件加入
import Koa from 'koa'
import cors from '@koa/cors'
import bodyParser from 'koa-bodyparser'
import { router } from './router' // 其他restful 路由都在这里面 是一个koa-router 实例对象
import graphqlHTTP from 'koa-graphql' // graphql创建http服务
import { allSchema } from './gqlService/rootSchema' // 所有gql好的schema,参数注入gqlHttp服务
const app = new Koa()
// koa-router@7+ 使用router.all 方法确定可以获取到ctx.req.body
// 前端可以在post里面传参数
router.all(
'/graphql',
graphqlHTTP(ctx => ({
schema: allSchema,
context: ctx, //从koa获取到的上下文,当前端需要使用post body时从这里获取
graphiql: true // 运行graphql 前端playground 图形化请求界面 生产环境关闭它
}))
)
app.use(cors())
app.use(bodyParser())
app.use(router.routes())
实现服务端 gql Schema
- Schema 是什么, 它定义了数据模型的解构、字段的类型, 模型间的关系
- 在 graphqlHTTP 服务里面需要传入一个 schema, 是所有服务器上 gql 数据的关于 Query 和 Mutaion 属性的对象
const schema = new GraphQLSchema({
query: // ..定义所有关于数据的请求的集合 类型为GraphQLObjectType
mutation: //... 定义所有关于数据突变的集合 类型也是GraphQLObjectType
})
- GraphQLObjectType gql 自定义创建类型, 有了他就可以轻松随便的定义你想要的数据结构以及对数据的处理
const HelloType = new GraphQLObjectType({
name: 'Hello', // 名字
description: 'hello gql', // 描述
fields: () => ({ // 自定义类型下的字段
// 客户端可以传入参数
id: { type: GraphQLNonNull(GraphQLInt) }
msg: {
type: msgType, // msgType 是另一个自定义类型
// args 客户端传递过来的参数对象
resolve: (args) => {
return await DBModel.find(msgModel => msgModel.id === args.id)
}
}
})
})
- 问题当有很多个不同的数据模型怎么样合并到一起,然后再传入 Schema 中?
- 使用 graphql-tools 合并所有的自定义 Schema
- graph 后端实现的方式有很多使用 graphqlHTTP 的方式, graphql-tools 合并 schema 是现在发现的最好方法
- 另外的 graphql 后端实现方法是 定义 typeDefs 以及 resovlers + merge-graphql-schemas, 现在不要用力过猛,只用最简单的方式打到目的
import { mergeSchemas } from 'graphql-tools'
import { blogSchema } from './blogSchema'
import { commentSchema } from './commentSchema'
// 另一个合并所有schema的插件merge-graphql-schemas
const allSchema = mergeSchemas({
schemas: [blogSchema, commentSchema]
})
export { allSchema }
// 每一个单一Schema 都是这样的结构
const schema = new GraphQLSchema({
query: // ..定义所有关于数据的请求的集合 类型为GraphQLObjectType
mutation: //... 定义所有关于数据突变的集合 类型也是GraphQLObjectType
})
- 2020/02/23 待续