使用Micro + Apollo Server + Node.js(TypeScript)来快捷建立GraphQL API服务器
首先
我将介绍如何使用ZEIT开发的适用于Node.js的Micro框架,在本地搭建一个用于模拟的GraphQL API服务器,并尝试使用GraphQL API。
如果有人问什么是“Micro”?
- Node.js でちょっとしたサーバーサイドやるなら、 Micro が良いかも
因为已经有一篇易懂的文章了,所以请先阅读这篇文章,大致了解一下Micro。
-
- npmの公式ページ
- ZEITのMicroに関するブログ
建议尝试确认一下。
目标读者
-
- GraphQLに関する知識をある程度有している方
-
- GraphQL APIを提供するサーバーを簡単に素早く作りたい方
- 言語はTypeScriptで書きたい方
运行环境
-
- Mac OS Sierra: v10.12.6
-
- node: v11.2.0(8系以上が必須)
-
- npm: v6.5.0
- yarn: v1.12.3
服务器建设步骤
创建一个工作目录〜生成package.json文件。
$ mkdir micro-typescript-graphql-sample
$ cd micro-typescript-graphql-sample
$ yarn init -y
安装必要的软件包。
$ yarn add micro microrouter apollo-server-micro graphql graphql-tools
$ yarn add -D micro-dev typescript ts-node @types/graphql @types/micro @types/microrouter
microrouter
クライアントからのリクエストをルーティングするために必要
apollo-server-micro
Apollo Serverの機能をMicroで使うために必要
graphql-tools
定義されたGraphQLスキーマとリゾルバを合成し、Apollo Serverに渡すオブジェクトを生成するmakeExecutableSchema関数を使用するために必要
micro-dev
開発環境でMicroサーバーを起動し、Hot Reloading、ログ出力などの機能を使うために必要
ts-node
.tsファイルに書かれたスクリプトをコンパイル無しでNode環境で実行するために必要
创建tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true,
"module": "commonjs",
"outDir": "./build",
"resolveJsonModule": true,
"strict": true,
"target": "esnext"
},
"include": ["./src/**/*"],
"exclude": ["node_modules"]
}
可以随意进行设置,但在构建时需要设置”esModuleInterop”: true和”outDir”: “./build”。
此外,为了导入JSON文件,也需要设置”resolveJsonModule”: true。
创建src/index.ts
import { send } from 'micro';
import { get, post, router } from 'microrouter';
import { ApolloServer, gql } from 'apollo-server-micro';
import { makeExecutableSchema } from 'graphql-tools';
const mockData = [
{
director: 'Bryan Singer',
title: 'Bohemian Rhapsody',
},
{
director: 'Bob Persichetti',
title: 'Spider-Man: Into the Spider-Verse',
},
];
const typeDefs = gql`
type Movie {
title: String
director: String
}
type Query {
movies: [Movie]
}
`;
const resolvers = {
Query: { movies: () => mockData },
};
const schema = makeExecutableSchema({
typeDefs,
resolvers,
});
const apolloServer = new ApolloServer({ schema });
const graphqlPath = '/data';
const graphqlHandler = apolloServer.createHandler({ path: graphqlPath });
module.exports = router(
get('/', (req, res) => 'Welcome!'),
post(graphqlPath, graphqlHandler),
get(graphqlPath, graphqlHandler),
(_, res) => send(res, 404, 'Not Found'),
);
在package.json中添加命令。
在package.json中添加scripts属性。
{
"name": "micro-typescript-graphql-sample",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"apollo-server-micro": "^2.3.1",
"graphql": "^14.0.2",
"graphql-tools": "^4.0.3",
"micro": "^9.3.3",
"microrouter": "^3.1.3"
},
"devDependencies": {
"@types/graphql": "^14.0.3",
"@types/micro": "^7.3.3",
"@types/microrouter": "^3.1.0",
"micro-dev": "^3.0.0",
"ts-node": "^7.0.1",
"typescript": "^3.2.2"
},
"scripts": {
"start": "micro ./build/index.js",
"dev": "node -r ts-node/register node_modules/.bin/micro-dev ./src/index.ts",
"build": "tsc -b"
}
}
以下是用终端实现这件事的方法。
这个用法是控制台上的。
$ yarn dev
或者
yarn build && yarn start
执行此操作将启动Micro服务器。
(您可以使用Ctrl + C停止服务器)

当服务器处于运行状态时,在浏览器中访问http://localhost:3000/data,您可以在Prisma的GraphQL Playground上尝试GraphQL API。

为了使用热重新加载(Hot Reloading)功能,可以在开发过程中使用 micro-dev 的 yarn dev 来启动服务器。这样可以方便地查看日志、检测源代码的更改并自动重新启动。
重构(例如将GraphQL模式拆分)
我认为在src/index.ts中只需要上面的一个例子就可以创建并尝试GraphQL API,但是我希望将模式定义等内容放在另一个文件中进行管理。
安装 graphql-import
请在.graphql文件中创建类型定义,并添加graphql-import进行导入和导出。
$ yarn add graphql-import
接下来,按照以下目录结构,创建用于类型、解析器和模式定义的文件。
├── node_modules
├── package.json
├── src
│ ├── index.ts
│ ├── mocks
│ │ └── movies.json
│ ├── resolvers
│ │ ├── index.ts
│ │ └── movies.ts
│ ├── schema.ts
│ └── typeDefs
│ ├── movie.graphql
│ ├── query.graphql
│ └── schema.graphql
├── tsconfig.json
└── tslint.json
创建类型定义文件
type Movie {
title: String
director: String
}
# import Movie from "movie.graphql"
type Query {
movies: [Movie]
}
# import Query from "query.graphql"
schema {
query: Query
}
创建解析器
import mockMovies from '../mocks/movies.json';
export const movies = () => mockMovies;
import { movies } from './movies';
export const resolvers = {
Query: {
movies,
},
};
创建模式
import { importSchema } from 'graphql-import';
import { makeExecutableSchema } from 'graphql-tools';
import { resolvers } from './resolvers';
const typeDefs = importSchema('src/typeDefs/schema.graphql');
export const schema = makeExecutableSchema({
resolvers,
typeDefs,
});
修改src/index.ts
import { send } from 'micro';
import { get, post, router } from 'microrouter';
import { ApolloServer } from 'apollo-server-micro';
import { schema } from './schema';
const apolloServer = new ApolloServer({ schema });
const graphqlPath = '/data';
const graphqlHandler = apolloServer.createHandler({ path: graphqlPath });
module.exports = router(
get('/', (req, res) => 'Welcome!'),
post(graphqlPath, graphqlHandler),
get(graphqlPath, graphqlHandler),
(_, res) => send(res, 404, 'Not Found'),
);
尽管结果与初次构建GraphQL API时相同,但它已被扩展为更易于操作的结构。
最后一句话 yī jù huà)
本次我们先试着创建了一些模拟数据,并使用GraphQL API的查询操作进行尝试,但未来我还想尝试使用Mutation操作、JWT认证、CORS支持等。
标本源代码
这次介绍的源代码可以从以下GitHub链接获取:
https://github.com/galoi/micro-typescript-graphql-sample