apollo-client 在 node.js 上工作吗?
Does apollo-client work on node.js?
我需要一个 graphql 客户端库 到 运行 在 node.js 上进行一些测试和一些数据混搭 - 不在生产能力中。我在其他任何地方都使用 apollo(react-apollo
,apollo 的 graphql-server-express
)。我的需求很简单。
apollo-client
是一个可行的选择吗?我找不到在节点上使用它的示例或文档 - 如果您知道,请分享。
或者我 should/can 在节点上使用参考 graphql 客户端?
这里是简单的node js实现。
'graphiql' 客户端足以进行开发活动。
1. run npm install
2. start server with "node server.js"
3. hit "http://localhost:8080/graphiql" for graphiql client
server.js
var graphql = require ('graphql').graphql
var express = require('express')
var graphQLHTTP = require('express-graphql')
var Schema = require('./schema')
// This is just an internal test
var query = 'query{starwar{name, gender,gender}}'
graphql(Schema, query).then( function(result) {
console.log(JSON.stringify(result,null," "));
});
var app = express()
.use('/', graphQLHTTP({ schema: Schema, pretty: true, graphiql: true }))
.listen(8080, function (err) {
console.log('GraphQL Server is now running on localhost:8080');
});
schema.js
//schema.js
var graphql = require ('graphql');
var http = require('http');
var StarWar = [
{
"name": "default",
"gender": "default",
"mass": "default"
}
];
var TodoType = new graphql.GraphQLObjectType({
name: 'starwar',
fields: function () {
return {
name: {
type: graphql.GraphQLString
},
gender: {
type: graphql.GraphQLString
},
mass: {
type: graphql.GraphQLString
}
}
}
});
var QueryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: function () {
return {
starwar: {
type: new graphql.GraphQLList(TodoType),
resolve: function () {
return new Promise(function (resolve, reject) {
var request = http.get({
hostname: 'swapi.co',
path: '/api/people/1/',
method: 'GET'
}, function(res){
res.setEncoding('utf8');
res.on('data', function(response){
StarWar = [JSON.parse(response)];
resolve(StarWar)
console.log('On response success:' , StarWar);
});
});
request.on('error', function(response){
console.log('On error' , response.message);
});
request.end();
});
}
}
}
}
});
module.exports = new graphql.GraphQLSchema({
query: QueryType
});
回复@YakirNa 的评论:
我不能说我描述的其他需求,但我已经做了相当多的测试。我最终完成了所有过程中的测试。
大多数测试最终都是解析器测试,我通过一个夹具来完成,该夹具使用测试查询调用 graphql 库的 graphql
函数,然后验证响应。
我还有一个(几乎)端到端测试层,它在 express 的 http 处理级别工作。它创建一个伪造的 HTTP 请求并验证进程中的响应。这一切都在服务器进程中;什么都没有通过电线。我很少使用它,主要用于测试 JWT 身份验证和其他独立于 graphql 请求主体的请求级行为。
Apollo Client 在 Node.js 上应该可以正常工作。您只需安装 cross-fetch.
这是在 Node.js 上工作的 Apollo Client 的完整 TypeScript 实现。
import { ApolloClient, gql, HttpLink, InMemoryCache } from "@apollo/client";
import { InsertJob } from "./graphql-types";
import fetch from "cross-fetch";
const client = new ApolloClient({
link: new HttpLink({ uri: process.env.PRODUCTION_GRAPHQL_URL, fetch }),
cache: new InMemoryCache(),
});
client.mutate<InsertJob.AddCompany, InsertJob.Variables>({
mutation: gql`mutation insertJob($companyName: String!) {
addCompany(input: { displayName: $companyName } ) {
id
}
}`,
variables: {
companyName: "aaa"
}
})
.then(result => console.log(result));
如果有人正在寻找 JavaScript 版本:
require('dotenv').config();
const gql = require('graphql-tag');
const ApolloClient = require('apollo-boost').ApolloClient;
const fetch = require('cross-fetch/polyfill').fetch;
const createHttpLink = require('apollo-link-http').createHttpLink;
const InMemoryCache = require('apollo-cache-inmemory').InMemoryCache;
const client = new ApolloClient({
link: createHttpLink({
uri: process.env.API,
fetch: fetch
}),
cache: new InMemoryCache()
});
client.mutate({
mutation: gql`
mutation popJob {
popJob {
id
type
param
status
progress
creation_date
expiration_date
}
}
`,
}).then(job => {
console.log(job);
})
我 运行 遇到了你同样的问题,因为我想创建一个中间件服务来准备从 graphQL 到最终前端应用程序的数据,
有 :
- 优化数据表示(和标准输出数据接口)
- 更快的响应时间
假设 graphQL 服务器由外部提供商提供,因此没有数据模型的所有权,直接使用 GQL
所以我不想直接在 React / Angular、Vuejs 等前端框架中实现 GraphQL Apolloclient...而是通过 REST API 后端的 Nodejs 管理查询。
所以这是我能够assemble(使用打字稿)的 Apolloclient 的 class 包装器:
import ApolloClient from "apollo-client";
import { ApolloLink } from 'apollo-link'
import { HttpLink } from 'apollo-link-http'
import { onError } from 'apollo-link-error'
import fetch from 'node-fetch'
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'
import introspectionQueryResultData from '../../fragmentTypes.json';
import { AppConfig } from 'app-config';
const config: AppConfig = require('../../../appConfig.js');
export class GraphQLQueryClient {
protected apolloClient: any;
constructor(headers: { [name: string]: string }) {
const api: any = {
spaceId: config.app.spaceId,
environmentId: config.app.environmentId,
uri: config.app.uri,
cdnApiPreviewToken: config.cdnApiPreviewToken,
};
// console.log(JSON.stringify(api));
const ACCESS_TOKEN = api.cdnApiPreviewToken;
const uri = api.uri;
console.log(`Apollo client setup to query uri: ${uri}`);
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData
});
this.apolloClient = new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError }:any) => {
if (graphQLErrors) {
graphQLErrors.map((el:any) =>
console.warn(
el.message || el
)
)
graphQLErrors.map(({ message, locations, path }:any) =>
console.warn(
`[GraphQL error - Env ${api.environmentId}]: Message: ${message}, Location: ${JSON.stringify(locations)}, Path: ${path}`
)
)
}
if (networkError) console.log(`[Network error]: ${networkError}`)
}),
new HttpLink({
uri,
credentials: 'same-origin',
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`
},
fetch
})
]),
cache: new InMemoryCache({ fragmentMatcher }),
// fetchPolicy as network-only avoids using the cache.
defaultOptions: {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
}
});
}
}
在此构造函数之后,我 运行 查询如下:
let response = await this.apolloClient.query({ query: gql`${query}` });
您可能已经注意到:
我需要在 Httplink 上注入 fetch
我必须设置授权 headers 才能访问外部提供商 graphQL 端点
我使用了 IntrospectionFragmentMatcher 以便在我的查询中使用 Fragments 以及构建模式类型("fragmentTypes.json" 使用初始化脚本)
发布这个只是为了增加我的经验,也许还有更多关于这个问题的信息。
也期待对此包装器的评论和改进点。
较新的 Apollo 版本提供了一种更简单的方法来执行此操作,如 Apollo docs 中所述,请查看“独立”部分。基本上可以简单地使用 ApolloLink
来执行查询或突变。
以下是撰写本文时文档中示例代码的副本,node-fetch
用法作为 createHttpLink
的配置。查看文档以获取有关如何使用这些工具的更多详细信息。
import { execute, makePromise } from 'apollo-link';
import { createHttpLink } from 'apollo-link-http';
import gql from 'graphql-tag';
import fetch from 'node-fetch';
const uri = 'http://localhost:4000/graphql';
const link = createHttpLink({ uri, fetch });
const operation = {
query: gql`query { hello }`,
variables: {} //optional
operationName: {} //optional
context: {} //optional
extensions: {} //optional
};
// execute returns an Observable so it can be subscribed to
execute(link, operation).subscribe({
next: data => console.log(`received data: ${JSON.stringify(data, null, 2)}`),
error: error => console.log(`received error ${error}`),
complete: () => console.log(`complete`),
})
// For single execution operations, a Promise can be used
makePromise(execute(link, operation))
.then(data => console.log(`received data ${JSON.stringify(data, null, 2)}`))
.catch(error => console.log(`received error ${error}`))
您可以使 apollo-client 工作,但这不是此用例的最佳选择。
试试 graphql-request。
Minimal GraphQL client supporting Node and browsers for scripts or simple apps
每个 npmjs 的功能:
- 最简单轻量级的 GraphQL 客户端
- Promise-based API(与异步/等待一起使用)
- 打字稿支持
- 同构(适用于 Node/浏览器)
示例:
import { request, gql } from 'graphql-request'
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
request('https://api.graph.cool/simple/v1/movies', query).then((data) => console.log(data))
我与这个包裹没有任何关系。
我需要一个 graphql 客户端库 到 运行 在 node.js 上进行一些测试和一些数据混搭 - 不在生产能力中。我在其他任何地方都使用 apollo(react-apollo
,apollo 的 graphql-server-express
)。我的需求很简单。
apollo-client
是一个可行的选择吗?我找不到在节点上使用它的示例或文档 - 如果您知道,请分享。
或者我 should/can 在节点上使用参考 graphql 客户端?
这里是简单的node js实现。
'graphiql' 客户端足以进行开发活动。
1. run npm install
2. start server with "node server.js"
3. hit "http://localhost:8080/graphiql" for graphiql client
server.js
var graphql = require ('graphql').graphql
var express = require('express')
var graphQLHTTP = require('express-graphql')
var Schema = require('./schema')
// This is just an internal test
var query = 'query{starwar{name, gender,gender}}'
graphql(Schema, query).then( function(result) {
console.log(JSON.stringify(result,null," "));
});
var app = express()
.use('/', graphQLHTTP({ schema: Schema, pretty: true, graphiql: true }))
.listen(8080, function (err) {
console.log('GraphQL Server is now running on localhost:8080');
});
schema.js
//schema.js
var graphql = require ('graphql');
var http = require('http');
var StarWar = [
{
"name": "default",
"gender": "default",
"mass": "default"
}
];
var TodoType = new graphql.GraphQLObjectType({
name: 'starwar',
fields: function () {
return {
name: {
type: graphql.GraphQLString
},
gender: {
type: graphql.GraphQLString
},
mass: {
type: graphql.GraphQLString
}
}
}
});
var QueryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: function () {
return {
starwar: {
type: new graphql.GraphQLList(TodoType),
resolve: function () {
return new Promise(function (resolve, reject) {
var request = http.get({
hostname: 'swapi.co',
path: '/api/people/1/',
method: 'GET'
}, function(res){
res.setEncoding('utf8');
res.on('data', function(response){
StarWar = [JSON.parse(response)];
resolve(StarWar)
console.log('On response success:' , StarWar);
});
});
request.on('error', function(response){
console.log('On error' , response.message);
});
request.end();
});
}
}
}
}
});
module.exports = new graphql.GraphQLSchema({
query: QueryType
});
回复@YakirNa 的评论:
我不能说我描述的其他需求,但我已经做了相当多的测试。我最终完成了所有过程中的测试。
大多数测试最终都是解析器测试,我通过一个夹具来完成,该夹具使用测试查询调用 graphql 库的 graphql
函数,然后验证响应。
我还有一个(几乎)端到端测试层,它在 express 的 http 处理级别工作。它创建一个伪造的 HTTP 请求并验证进程中的响应。这一切都在服务器进程中;什么都没有通过电线。我很少使用它,主要用于测试 JWT 身份验证和其他独立于 graphql 请求主体的请求级行为。
Apollo Client 在 Node.js 上应该可以正常工作。您只需安装 cross-fetch.
这是在 Node.js 上工作的 Apollo Client 的完整 TypeScript 实现。
import { ApolloClient, gql, HttpLink, InMemoryCache } from "@apollo/client";
import { InsertJob } from "./graphql-types";
import fetch from "cross-fetch";
const client = new ApolloClient({
link: new HttpLink({ uri: process.env.PRODUCTION_GRAPHQL_URL, fetch }),
cache: new InMemoryCache(),
});
client.mutate<InsertJob.AddCompany, InsertJob.Variables>({
mutation: gql`mutation insertJob($companyName: String!) {
addCompany(input: { displayName: $companyName } ) {
id
}
}`,
variables: {
companyName: "aaa"
}
})
.then(result => console.log(result));
如果有人正在寻找 JavaScript 版本:
require('dotenv').config();
const gql = require('graphql-tag');
const ApolloClient = require('apollo-boost').ApolloClient;
const fetch = require('cross-fetch/polyfill').fetch;
const createHttpLink = require('apollo-link-http').createHttpLink;
const InMemoryCache = require('apollo-cache-inmemory').InMemoryCache;
const client = new ApolloClient({
link: createHttpLink({
uri: process.env.API,
fetch: fetch
}),
cache: new InMemoryCache()
});
client.mutate({
mutation: gql`
mutation popJob {
popJob {
id
type
param
status
progress
creation_date
expiration_date
}
}
`,
}).then(job => {
console.log(job);
})
我 运行 遇到了你同样的问题,因为我想创建一个中间件服务来准备从 graphQL 到最终前端应用程序的数据, 有 :
- 优化数据表示(和标准输出数据接口)
- 更快的响应时间
假设 graphQL 服务器由外部提供商提供,因此没有数据模型的所有权,直接使用 GQL
所以我不想直接在 React / Angular、Vuejs 等前端框架中实现 GraphQL Apolloclient...而是通过 REST API 后端的 Nodejs 管理查询。
所以这是我能够assemble(使用打字稿)的 Apolloclient 的 class 包装器:
import ApolloClient from "apollo-client";
import { ApolloLink } from 'apollo-link'
import { HttpLink } from 'apollo-link-http'
import { onError } from 'apollo-link-error'
import fetch from 'node-fetch'
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'
import introspectionQueryResultData from '../../fragmentTypes.json';
import { AppConfig } from 'app-config';
const config: AppConfig = require('../../../appConfig.js');
export class GraphQLQueryClient {
protected apolloClient: any;
constructor(headers: { [name: string]: string }) {
const api: any = {
spaceId: config.app.spaceId,
environmentId: config.app.environmentId,
uri: config.app.uri,
cdnApiPreviewToken: config.cdnApiPreviewToken,
};
// console.log(JSON.stringify(api));
const ACCESS_TOKEN = api.cdnApiPreviewToken;
const uri = api.uri;
console.log(`Apollo client setup to query uri: ${uri}`);
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData
});
this.apolloClient = new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError }:any) => {
if (graphQLErrors) {
graphQLErrors.map((el:any) =>
console.warn(
el.message || el
)
)
graphQLErrors.map(({ message, locations, path }:any) =>
console.warn(
`[GraphQL error - Env ${api.environmentId}]: Message: ${message}, Location: ${JSON.stringify(locations)}, Path: ${path}`
)
)
}
if (networkError) console.log(`[Network error]: ${networkError}`)
}),
new HttpLink({
uri,
credentials: 'same-origin',
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`
},
fetch
})
]),
cache: new InMemoryCache({ fragmentMatcher }),
// fetchPolicy as network-only avoids using the cache.
defaultOptions: {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
}
});
}
}
在此构造函数之后,我 运行 查询如下:
let response = await this.apolloClient.query({ query: gql`${query}` });
您可能已经注意到:
我需要在 Httplink 上注入 fetch
我必须设置授权 headers 才能访问外部提供商 graphQL 端点
我使用了 IntrospectionFragmentMatcher 以便在我的查询中使用 Fragments 以及构建模式类型("fragmentTypes.json" 使用初始化脚本)
发布这个只是为了增加我的经验,也许还有更多关于这个问题的信息。 也期待对此包装器的评论和改进点。
较新的 Apollo 版本提供了一种更简单的方法来执行此操作,如 Apollo docs 中所述,请查看“独立”部分。基本上可以简单地使用 ApolloLink
来执行查询或突变。
以下是撰写本文时文档中示例代码的副本,node-fetch
用法作为 createHttpLink
的配置。查看文档以获取有关如何使用这些工具的更多详细信息。
import { execute, makePromise } from 'apollo-link';
import { createHttpLink } from 'apollo-link-http';
import gql from 'graphql-tag';
import fetch from 'node-fetch';
const uri = 'http://localhost:4000/graphql';
const link = createHttpLink({ uri, fetch });
const operation = {
query: gql`query { hello }`,
variables: {} //optional
operationName: {} //optional
context: {} //optional
extensions: {} //optional
};
// execute returns an Observable so it can be subscribed to
execute(link, operation).subscribe({
next: data => console.log(`received data: ${JSON.stringify(data, null, 2)}`),
error: error => console.log(`received error ${error}`),
complete: () => console.log(`complete`),
})
// For single execution operations, a Promise can be used
makePromise(execute(link, operation))
.then(data => console.log(`received data ${JSON.stringify(data, null, 2)}`))
.catch(error => console.log(`received error ${error}`))
您可以使 apollo-client 工作,但这不是此用例的最佳选择。
试试 graphql-request。
Minimal GraphQL client supporting Node and browsers for scripts or simple apps
每个 npmjs 的功能:
- 最简单轻量级的 GraphQL 客户端
- Promise-based API(与异步/等待一起使用)
- 打字稿支持
- 同构(适用于 Node/浏览器)
示例:
import { request, gql } from 'graphql-request'
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
request('https://api.graph.cool/simple/v1/movies', query).then((data) => console.log(data))
我与这个包裹没有任何关系。