使用 GraphQL + Node.js 构建高性能 API
·
使用 GraphQL + Node.js 构建高性能 API
大家好,我是欧阳瑞(Rich Own)。今天想聊聊我这几年做全栈开发最喜欢用的 API 设计方式——GraphQL,配合 Node.js,真的能让后端开发效率提升一个档次。
为什么选择 GraphQL?
用过 RESTful 的同学都知道,有时候为了一个页面,得调用好几个接口,要么是接口返回的数据太多(Overfetching),要么是不够(Underfetching)。GraphQL 完美解决了这个问题,客户端想要什么数据自己决定。
项目初始化
先建个新项目:
mkdir graphql-server && cd graphql-server
npm init -y
npm install express express-graphql graphql cors
npm install --save-dev nodemon
定义 Schema
在 schema.js 里定义我们的数据模型。假设我们要做一个极客社区的用户系统:
const { buildSchema } = require('graphql');
const schema = buildSchema(`
type User {
id: ID!
name: String!
bio: String
github: String
projects: [Project]
}
type Project {
id: ID!
title: String!
description: String
techStack: [String]
isWeb3: Boolean
}
type Query {
user(id: ID!): User
allUsers: [User]
project(id: ID!): Project
}
type Mutation {
createUser(name: String!, bio: String, github: String): User
addProject(userId: ID!, title: String!, description: String, techStack: [String], isWeb3: Boolean): Project
}
`);
module.exports = schema;
准备数据
为了演示,先搞点模拟数据:
// data.js
const users = [
{
id: '1',
name: '欧阳瑞',
bio: '全栈开发工程师 / Web3 探索者',
github: 'richown',
projects: ['1', '2']
}
];
const projects = [
{
id: '1',
title: 'CyberPunkNFT',
description: '赛博朋克风格 NFT 平台',
techStack: ['Solidity', 'Next.js', 'Three.js'],
isWeb3: true
},
{
id: '2',
title: 'DAO Toolkit',
description: '去中心化治理工具集',
techStack: ['React', 'GraphQL', 'Hardhat'],
isWeb3: true
}
];
module.exports = { users, projects };
Resolver 实现
编写 resolvers.js:
const { users, projects } = require('./data');
const resolvers = {
user: ({ id }) => users.find(u => u.id === id),
allUsers: () => users,
project: ({ id }) => projects.find(p => p.id === id),
createUser: ({ name, bio, github }) => {
const newUser = {
id: String(users.length + 1),
name,
bio,
github,
projects: []
};
users.push(newUser);
return newUser;
},
addProject: ({ userId, title, description, techStack, isWeb3 }) => {
const newProject = {
id: String(projects.length + 1),
title,
description,
techStack: techStack || [],
isWeb3: isWeb3 || false
};
projects.push(newProject);
const user = users.find(u => u.id === userId);
if (user) {
user.projects.push(newProject.id);
}
return newProject;
}
};
module.exports = resolvers;
注意 User 类型里的 projects 字段需要一个 Resolver:
const root = {
...resolvers,
User: {
projects: (user) => user.projects.map(pid => projects.find(p => p.id === pid))
}
};
module.exports = root;
启动服务器
server.js:
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const cors = require('cors');
const schema = require('./schema');
const root = require('./resolvers');
const app = express();
app.use(cors());
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true, // 开启 GraphiQL 图形化界面
}));
const PORT = 4000;
app.listen(PORT, () => {
console.log(`🚀 GraphQL Server running at http://localhost:${PORT}/graphql`);
});
更新 package.json:
{
"scripts": {
"dev": "nodemon server.js"
}
}
运行:
npm run dev
试试看!
打开 http://localhost:4000/graphql,GraphiQL 界面会自动打开。
试试这个 Query:
query {
user(id: "1") {
name
bio
github
projects {
title
techStack
isWeb3
}
}
}
再试试 Mutation:
mutation {
createUser(name: "Hash Fan", bio: "喜欢鬃狮蜥的开发者", github: "hashfan") {
id
name
}
}
进阶:结合 Prisma
实际开发中,我们当然不会用内存数据。配合 Prisma ORM 体验极佳:
npm install @prisma/client
npm install --save-dev prisma
npx prisma init
定义 schema.prisma,然后生成客户端,改造 Resolver 即可。
写在最后
GraphQL 配合 Node.js 真的是绝配,前端后端都爽。我的鬃狮蜥 Hash 虽然看不懂代码,但它很喜欢我用 GraphQL 开发时高效的样子——因为我能更快搞定工作陪它。
有兴趣的同学欢迎留言交流,我是欧阳瑞,我们下次见!
技术栈:Node.js · GraphQL · Express · Prisma
更多推荐



所有评论(0)