# 环境准备

  • 操作系统:支持 macOS,Linux,Windows
  • 运行环境:建议选择 LTS 版本,最低要求 8.x。

# 初始化

# 使用脚手架生成 Egg 项目

推荐直接使用脚手架,只需几条简单指令,即可快速生成项目(npm >=6.1.0):

$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i

上面这种方式是 egg.js 官方推荐的创建简易项目, 而我们本小册使用 Typescript 开发, 所以我们换种方式:

TypeScript 初始化方式

$ npm init egg --type=ts
$ npm i

# 目录结构

egg-example

    |-- .autod.conf.js
    |-- .gitignore
    |-- .travis.yml
    |-- README.md
    |-- appveyor.yml
    |-- package-lock.json
    |-- package.json
    |-- tsconfig.json			# 指定了用来编译这个项目的根文件和编译选项
    |-- tslint.json				# 代码检查
    |-- app
    |   |-- router.ts			# 用于配置 URL 路由规则
    |   |-- controller			# 用于解析用户的输入,处理后返回相应的结果
    |   |   |-- home.ts
    |   |-- public				# 用于放置静态资源
    |   |-- service				# 用于编写业务逻辑层
    |       |-- Test.ts
    |-- config					# 用于编写配置文件
    |   |-- config.default.ts
    |   |-- config.local.ts
    |   |-- config.prod.ts
    |   |-- plugin.ts			# 用于配置需要加载的插件
    |-- test					# 用于单元测试
    |   |-- app
    |       |-- controller
    |       |   |-- home.test.ts
    |       |-- service
    |           |-- Test.test.ts
    |-- typings					# 目录用于放置 d.ts 文件
        |-- index.d.ts

gg API 项目中,一般都会包括这些功能项:路由文件、控制器目录、逻辑层目录。这些都在上述的代码结构中有列出,这是典型的 MVC 架构。新加功能时将代码放入对应功能的目录/文件中,可以使整个项目代码结构更加清晰,非常有利于后期的查找和维护。

# MVC

MVC 全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

# 安装插件

插件机制是Egg框架的一大特色,形成了egg 的繁荣的生态圈,接下来我们就来安装我们本次项目的第一个插件。

由于我们后续的实战是基于 TypeScript 的,所以在这里我选择了一个支持 TypeScript 的包 @switchdog/egg-graphql 。

$ npm i --save @switchdog/egg-graphql

# 开启插件

在 config/plugin.ts 下告诉 egg 开启哪些插件:

graphql: {
    enable: true,
    package: '@switchdog/egg-graphql',
},

# 配置插件

通常插件都会有一些配置项,在/config/config.default.ts中配置即可:

config.graphql = {
    router: '/graphql',
    // 是否加载到 app 上,默认开启
    app: true,
    // 是否加载到 agent 上,默认关闭
    agent: false,
    // 是否加载开发者工具 graphiql, 默认开启。路由同 router 字段。使用浏览器打开该可见。
    graphiql: true,
    apolloServerOptions: {
      tracing: true, // 设置为true时,以Apollo跟踪格式收集和公开跟踪数据
      debug: true, // 一个布尔值,如果发生执行错误,它将打印其他调试日志记录
    },
  };

在中间件中开启 graphql

config.middleware = [ 'graphql' ];

配置完成之后,每个落到 /graphql的请求都会触发 GraphQL Schema 的查询。

# GraphQL 代码结构

graphql 目录下,有 4 种代码,分别是:common 全局类型定义、query 查询代码、**mutation 更新操作代码 **和 resolver业务实现代码。

.
├── graphql                       | graphql 代码
│   ├── common                    | 通用类型定义
│   │   ├── resolver.js           | 合并所有全局类型定义
│   │   ├── scalars               | 自定义类型定义
│   │   │   └── date.js           | 日期类型实现
│   │   └── schema.graphql        | schema 定义
│   ├── mutation                  | 所有的更新
│   │   └── schema.graphql        | schema 定义
│   ├── query                     | 所有的查询
│   │   └── schema.graphql        | schema 定义
│   └── user                      | 用户业务
│       ├── connector.js          | 连接数据服务
│       ├── resolver.js           | 类型实现
│       └── schema.graphql        | schema 定义

tips: 在这只是为大家展示,请不要在开始就创建user目录,后边教程用到时再创建,不然会报错。

# CORS 跨域访问

CORS,常被大家称之为跨域问题,准确的叫法是跨域资源共享**(CORS,Cross-origin resource sharing)**,是W3C标准,是一种机制,它使用额外的HTTP头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。

我们先来安装 egg-cors

# npm i egg-cors --save

开启 /config/plugin.ts:

cors: {
    enable: true,
    package: 'egg-cors',
},

配置 /config/config.default.ts:

config.cors = {
    origin: '*',
    allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
};

# CSRF

CSRF(Cross-site request forgery)跨站请求伪造,也被称为 One Click Attack 或者 Session Riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。

使用 graphql 或 rest 端点时,实际上不必担心使用 CSRF 保护。对服务的请求应该是无状态的,并且不真正依赖Cookie或会话数据。

关闭 /config/config.default.ts:

config.security = {
    csrf: {
      ignore: () => true,
    },
};

# 小结

本节介绍了项目的初始化,egg.js 项目的目录结构以及 graphql 的目录结构。知道了egg.js 框架是 MVC 的形式,并了解了什么是 MVC。以及在如何在 egg.js 框架中安装和使用第三方包。

阅读全文