于10月8日至10日在纽约市加入我们,了解有关GraphQL联邦和API平台工程的最新技巧、趋势和新闻。加入我们在纽约市的GraphQL峰会2024
文档
免费开始

使用 Apollo Server 实现 subgraph


本文演示了如何使用Node.js和子图(subgraph)和Apollo Server创建一个(supergraph)

若要使用不同的语言和/或框架创建子图,请参阅联邦兼容子图实现列表。注意,并非所有列出的库都支持所有联邦功能。

定义子图

要成为超级图的一部分,子图必须符合Apollo Federation子图规范,该规范可向您的图以及Apollo Studio等工具暴露子图的特性。

将现有的转换为单个子图是构建联邦超级图的一个方便的第一步。首先,以下是一个非联邦 Apollo Server的设置:

index.ts
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import gql from 'graphql-tag';
const typeDefs = gql`
type Query {
me: User
}
type User {
id: ID!
username: String
}
`;
const resolvers = {
Query: {
me() {
return { id: '1', username: '@ava' };
},
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
// Note the top-level await!
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);
index.js
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import gql from 'graphql-tag';
const typeDefs = gql`
type Query {
me: User
}
type User {
id: ID!
username: String
}
`;
const resolvers = {
Query: {
me() {
return { id: '1', username: '@ava' };
},
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
// Note the top-level await!
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);

上面,我们把我们的模式用gql 标签来自 graphql-tag 包,将我们的 schema 转换为 AST(即 DocumentNode)。虽然 Apollo Server 可以接受一个 string(或者 DocumentNode)作为它的 typeDefs,下面的 buildSubgraphSchema 函数需要我们传递的 schema 是一个 DocumentNode

如果你之前已经设置过 Apollo Server,这应该看起来很熟悉。如果你还没有,我们在开始联邦之前推荐你先熟悉一下基础知识。

现在,让我们将其转换为 subgraph!

1. 安装并导入 @apollo/subgraph

第一步是在服务器项目中安装 @apollo/subgraph@apollo/subgraph 包:

npm install @apollo/subgraph

我们还需要在这个文件中引入 buildSubgraphSchemabuildSubgraphSchema 函数(我们稍后会用到)在初始化 ApolloServerApolloServer 的文件中:

index.ts
import { buildSubgraphSchema } from '@apollo/subgraph';
index.js
import { buildSubgraphSchema } from '@apollo/subgraph';

2. 集成 Federation 2

为了使 subgraph 使用 Federation 2 的新功能,它的 schema 需要包含以下 extend schemaextend schema 定义:

import gql from 'graphql-tag';
const typeDefs = gql`
# highlight-start
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
# highlight-end
type Query {
me: User
}
type User {
id: ID!
username: String
}
`;
import gql from 'graphql-tag';
const typeDefs = gql`
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
type Query {
me: User
}
type User {
id: ID!
username: String
}
`;

这个定义使得 schema 能够使用 Federation 2 功能。没有它,Federation 2 的 会假定 subgraph 使用 Federation 1,这会为了向后兼容而设置一些默认值。

当你开始使用更多 与 federation 相关的指令(超出 @key@shareable),你需要在上述的 import 数组中添加这些

3. 定义实体

实体在 subgraph 中不是必需的,但它们是联邦 supergraph 的核心构建块,所以练习定义它们是有好处的。

作为我们的联邦架构的一部分,我们希望 其他 subgraph 能够向 User 类型贡献 。为了启用此功能,我们在 User 类型的定义中添加 @key ,将其指定为 entity

index.ts
const typeDefs = gql`
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
type Query {
me: User
}
type User
@key(fields: "id") { # highlight-line
id: ID!
username: String
}
`;
index.js
const typeDefs = gql`
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
type Query {
me: User
}
type User
@key(fields: "id") {
id: ID!
username: String
}
`;

@key 指令告知网关哪个能够唯一标识User 的特定实例。在这种情况下,网关可以使用单个id

接下来,我们为User 添加一个引用解析器。一个引用解析器告诉网关如何通过它的@key 字段来获取实体:

index.ts
const resolvers = {
Query: {
me() {
return { id: '1', username: '@ava' };
},
},
User: {
__resolveReference(user, { fetchUserById }) {
return fetchUserById(user.id);
},
},
};
index.js
const resolvers = {
Query: {
me() {
return { id: '1', username: '@ava' };
},
},
User: {
__resolveReference(user, { fetchUserById }) {
return fetchUserById(user.id);
},
},
};

(此示例需要定义fetchUserById函数以从我们的后端数据存储中获取适当的User。)

4. 生成子图模式

最后,我们使用来自@apollo/subgraph包的buildSubgraphSchema函数来添加对联盟支持的增强到我们的模式定义中。我们向ApolloServer构造函数提供此函数的结果:

index.ts
const server = new ApolloServer({
schema: buildSubgraphSchema({ typeDefs, resolvers }),
});
// Note the top level await!
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);
index.js
const server = new ApolloServer({
schema: buildSubgraphSchema({ typeDefs, resolvers }),
});
// Note the top level await!
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);

服务器现在已准备好作为一个联邦图中的子图执行!

综合示例

以下是上述代码片段的合并(请注意,为了使此示例完整,您必须为您的定义fetchUserById函数):

index.ts
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import gql from 'graphql-tag';
import { buildSubgraphSchema } from '@apollo/subgraph';
const typeDefs = gql`
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
type Query {
me: User
}
type User @key(fields: "id") {
id: ID!
username: String
}
`;
const resolvers = {
Query: {
me() {
return { id: '1', username: '@ava' };
},
},
User: {
__resolveReference(user, { fetchUserById }) {
return fetchUserById(user.id);
},
},
};
const server = new ApolloServer({
schema: buildSubgraphSchema({ typeDefs, resolvers }),
});
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);
index.js
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import gql from 'graphql-tag';
import { buildSubgraphSchema } from '@apollo/subgraph';
const typeDefs = gql`
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
type Query {
me: User
}
type User @key(fields: "id") {
id: ID!
username: String
}
`;
const resolvers = {
Query: {
me() {
return { id: '1', username: '@ava' };
},
},
User: {
__resolveReference(user, { fetchUserById }) {
return fetchUserById(user.id);
},
},
};
const server = new ApolloServer({
schema: buildSubgraphSchema({ typeDefs, resolvers }),
});
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);

自定义指令

请参阅有关子图中自定义指令的信息子图中的自定义指令

上一页
事件参考
下一页
@apollo/subgraph参考
评分文章评分在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,Apollo GraphQL。

隐私政策

公司