Nodejs、GraphQL、MongoDB、Hapi 和 Swagger 构建 API(一)
可重用 API 流行的最大原因是 API 允许使用来自 Web 客户端、移动应用程序、桌面应用程序的数据,实际上是任何客户端。将构建一个基于 Nodejs,由 MongoDB 数据驱动的强大而灵活的 GraphQL API,并支持 Swagger 文档。
API 的主要骨干将是 Hapi.js 来完成,接下来将详细介绍所有技术。最终实现一个拥有非常强大的 GraphQL API 和出色的文档。最重要的是将与客户端的集成(React、Vue、Angular)
本系列文章将包括NodeJs后端服务(实现登录、文章管理)、前端VUE文章管理系统、Docker部署全栈项目开发。图很形象的展现全栈开发的场景,多显示器、多语言语法切换、语言之间语法互串。
项目代码仓库:https://github.com/QuintionTang/powerful-api
开发环境
任何项目的开始都需要准备好开发环境,可以配置或者借助Docker。
- 安装 NodeJS
- 基本的 JavaScript
- 终端(任何都可以,最好是基于 bash 的)
- 文本编辑器(任何一个都行),首先VSCode
- 安装数据 MongoDB ,任何安装MongoDB,可以参阅官方文档。
项目开始
打开终端并创建项目,在项目目录下,初始化一个 Nodejs 项目。
npm init
接下来,设置 Hapi 服务器,安装依赖项,可以使用 Yarn 或 NPM。
npm install hapi nodemon --save
在继续之前,先简单介绍一下 hapi.js 是什么以及它可以做什么。
以最小的开销和完整的开箱即用功能构建功能强大、可扩展的应用程序
hapi.js 使开发人员能够专注于编写可重用的应用程序逻辑,而不是花时间构建基础设施。
不使用 Express,而是使用 Hapi。简而言之,Hapi 是一个 Node 框架,选择 Hapi 的原因很简单,能够使代码简单和灵活。Hapi 能够以非常快速的方式构建所需的 API。
安装的第二个依赖项是 nodemon,这个依赖库主要用于提高开发效率,每次代码有变更会自动重启API服务。
打开编辑器 VSCode,正式进入编码。构建 Hapi 服务器非常简单,在根目录下创建一个 server.js
文件,代码如下:
const hapi = require("hapi");
const server = hapi.server({
port: 3006,
host: "localhost",
});
const init = async () => {
await server.start();
console.log(`Server running at:${server.info.uri}`);
};
init();
- 第一行代码加载
hapi
依赖 - 其次,创建一个常量
server
赋值 Hapi 服务器的一个新实例,传递一个带有端口和主机选项的配置对象。 - 第三,创建一个名为
init
的异步函数。在init
方法中,有另一个启动服务器的异步方法server.start()
,执行init()
函数启动服务。
到此,一个简单的服务已经构建完成了,启动服务:
node server.js
打开浏览器,输入 http://localhost:3006
,不出意外的话会是一个404错误,这是因为还没有定义任何路由。
{"statusCode":404,"error":"Not Found","message":"Not Found"}
打开 package.json
并编辑 scripts
部分,添加开发启动脚本,如下:
"dev": "nodemon server.js"
这样开发启动脚本如下:
npm run dev
为了使代码风格一致,确保每个开发人员的代码风格一致(可以简单看看《简谈提高团队代码质量的利器:ESLint 与 Prettier》),需要安装辅助开发的依赖:
npm install babel-eslint eslint-plugin-node --save-dev
安装完成之后,在项目根目录下增加文件 .eslintrc.js
,代码如下:
module.exports = {
root: true,
parser: "babel-eslint",
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
ecmaFeatures: {
legacyDecorators: true,
},
},
plugins: [""],
extends: ["eslint:recommended"],
env: {
browser: true,
},
rules: {},
overrides: [
// node files
{
files: [
".eslintrc.js",
".template-lintrc.js",
"config/**/*.js",
"src/*/server.js",
],
parserOptions: {
sourceType: "script",
},
env: {
browser: false,
node: true,
},
plugins: ["node"],
rules: Object.assign(
{},
require("eslint-plugin-node").configs.recommended.rules,
{
"node/no-unpublished-require": "off",
}
),
},
],
};
路由设置
Hapi 的路由非常直观,假设点击 /
希望发生什么?这里有三个主要组成部分。
path
:一般是资源的路径method
:API请求方法,一般是指HTTP方法,常用的包括POST
、GET
、PUT
、DELETE
handler
:一般是指API的响应逻辑
const hapi = require("hapi");
const server = hapi.server({
port: 3006,
host: "localhost",
});
const init = async () => {
server.route({
method: "GET",
path: "/",
handler: (request, response) => `<h1>This is powerful api.</h1>`,
});
await server.start();
console.log(`Server running at:${server.info.uri}`);
};
init();
在 init
方法中,使用 server
的 route
的方法增加根目录访问的响应API,一个简单的 GET
接口。
设置数据库
接下来要建立数据库,这里将使用 mongodb 和 mongoose。
本文构建的API服务使用一个基于分布式文件存储的数据库 MongoDB。
在 Nodejs 中编写与数据库相关的逻辑(CURD操作)通常使用 Mongoose ,而 Mongoose 是 MongoDB 的一个对象模型工具,是基于 node-mongoldb-native
开发的 MongoDB 驱动,可以在异步环境下执行。同时它也是针对 MongoDB 操作的一个对象模型库,封装了MongoDB对文档的的一些增删改查等常用方法,让 Nodejs 下操作 MongoDB 数据库变得更加灵活简单。
在 Nodejs 下 MongoDB + Mongoose
是一种常见的开发组合。
开始安装依赖:
npm install mongoose --save
在文件 server.js
引入:
const mongoose = require("mongoose");
接下来先来配置数据库环境,可以参考官方文档进行安装,按照文档步骤基本可以正常配置好,这里就不展开。这里介绍使用 Docker 来启动一个 MongoDB,对于 Docker 如果不熟悉,可以参阅《面向WEB开发人员的Docker》。
设置 Mongo Docker 镜像
使用以下命令拉取 Docker 镜像:
docker pull mongo
现在已经将Mongo Docker 镜像下载到自己机器上了,执行以下命令运行 MongoDB 。
docker run -it -v $PWD/mongodata:/data/db -p 27017:27017 --name mongodb -d mongo
MongoDB 运行在端口 27017
上,数据存储在项目根目录下的文件夹 mongodata
。
接下来增加数据库连接逻辑:
const mongoUrl = "mongodb://127.0.0.1:27017/powerful";
const mainDB = mongoose
.createConnection(mongoUrl, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.asPromise();
mainDB
.then((db) => {
console.info("Connected to MongoDB mainDB");
db.model("Users", new mongoose.Schema({ name: String }));
})
.catch((err) => {
console.error("Failed to connect to mainDB", {
params: { err: err.message },
});
});
在终端运行代码可以看到如下结果:
到这里就完成数据库的设置和连接,连接成功后创建一个 Users
的集合,可以通过 MongoDB 可视化工具 MongoDB Compass 连接到数据库查看数据信息: