使用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停止服务器)

スクリーンショット 2018-12-23 17.39.26.png

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

スクリーンショット 2018-12-23 17.27.22.png

为了使用热重新加载(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

bannerAds