如何使用 `apollo-server` 加载 .graphql 文件?

35

我目前正在使用单独的.graphql文件加载GraphQL架构,但它被封装在字符串中:

schema.graphql

const schema = `
  type CourseType {
    _id: String!
    name: String!
  }

  type Query {
    courseType(_id: String): CourseType
    courseTypes: [CourseType]!
  }
`

module.exports = schema

然后将其用于 apollo-server

index.js

const { ApolloServer, makeExecutableSchema } = require('apollo-server')
const typeDefs = require('./schema.graphql')

const resolvers = { ... }

const schema = makeExecutableSchema({
  typeDefs: typeDefs,
  resolvers
})

const server = new ApolloServer({
  schema: schema
})

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}.`)
})

有没有一种简单的方法来加载一个看起来像这样的.graphql文件? schema.graphql
type CourseType {
  _id: String!
  name: String!
}

type Query {
  courseType(_id: String): CourseType
  courseTypes: [CourseType]!
}

那么它将在 index.js 中进行解析?我注意到 graphql-yoga 支持此功能,但想知道 apollo-server 是否也支持。我在文档中找不到任何信息。我也无法让 fs.readFile 正常工作。


https://github.com/apollographql/graphql-tag#importing-graphql-files - xadm
6个回答

42

如果您将类型定义放在一个.graphql文件中,可以通过以下几种方式之一读取它:

1.) 自己读取文件:

const { readFileSync } = require('fs')

// we must convert the file Buffer to a UTF-8 string
const typeDefs = readFileSync(require.resolve('./type-defs.graphql')).toString('utf-8')

2.) 使用像graphql-tools这样的库来为您执行此操作:

const { loadDocuments } = require('@graphql-tools/load');
const { GraphQLFileLoader } = require('@graphql-tools/graphql-file-loader');

// this can also be a glob pattern to match multiple files!
const typeDefs = await loadDocuments('./type-defs.graphql', { 
    file, 
    loaders: [
        new GraphQLFileLoader()
    ]
})

3.) 使用 Babel 插件Webpack loader

import typeDefs from './type-defs.graphql'

1
太棒了!竟然没有与apollo-serverGraphQLFileLoader方法相等的东西吗? - Sam Sverko
1
也许会在未来版本中实现。 - Daniel Rearden
谢谢您注意到readFileSync中的'utf-8',否则我可能会错过它。 - Paul Mikulskis
@DanielRearden 当我在联合图中加载子图模式时,出现以下错误:未知指令“@key”。 无法扩展类型“Membership”,因为它未被定义。 未知指令“@key”。 未知指令“@external”。 未知类型“Query”。 - Hazem Alabiad
@Hazem Alabiad 我使用了这个答案中的第一种选项,并将其包装在 gql 中,用于联合子图。 const typeDefs = gql(readFileSync(require.resolve('./schema.graphql')).toString('utf-8')); - MMH
显示剩余3条评论

2

早些时候,我自己写了一个非常小、非常简单的 .graphql 加载器。你只需要在尝试导入任何 .graphql 文件之前将其导入即可。虽然我确信有一些第三方加载器可用,但我从那时起就一直在使用它。代码如下:

// graphql-loader.js

const oldJSHook = require.extensions[".js"];

const loader = (module, filename) => {
  const oldJSCompile = module._compile;
  module._compile = function (code, file) {
    code = `module.exports = \`\r${code}\`;`;
    module._compile = oldJSCompile;
    module._compile(code, file);
  };
  oldJSHook(module, filename);
};

require.extensions[".graphql"] = loader;
require.extensions[".gql"] = loader;

然后在您的应用程序中:

// index.js

import "./graphql-loader"; // (or require("./graphql-loader") if you prefer)

就这样,你可以在任何你想要的地方 import typeDefs from "./type-defs.graphql"

加载器通过将你的 .graphql 文件中的文本包装在一个模板字符串中,并将其编译为简单的JS模块来工作:

module.exports = ` ...your gql schema... `;

1
这对我有效:

这对我有效:

const { gql } = require('apollo-server');
const fs = require('fs');
const path = require('path');

//function that imports .graphql files
const importGraphQL = (file) =>{
  return fs.readFileSync(path.join(__dirname, file),"utf-8");
}

const gqlWrapper = (...files)=>{
  return gql`${files}`;
}


const enums = importGraphQL('./enums.graphql');
const schema = importGraphQL('./schema.graphql');

module.exports = gqlWrapper(enums,schema);


0

我使用这个帮助程序:

import { readFileSync } from "fs";
const requireGQL = (file) =>
  gql`${readFileSync(require.resolve(file)).toString("utf-8")}`;

将其放在文件顶部,然后你就可以:

const client = new ApolloClient({ uri: 'https://myendpoint.com/graphql' });
const { data } = await client.query({ query: requireGQL("./myquery.gql") });

0

通过使用fs(感谢Tal Z)解决了这个问题:

index.js

const fs = require('fs')
const mongoUtil = require('./mongoUtil')
const { ApolloServer, makeExecutableSchema } = require('apollo-server')

function readContent (file, callback) {
  fs.readFile(file, 'utf8', (err, content) => {
    if (err) return callback(err)
    callback(null, content)
  })
}

mongoUtil.connectToServer((error) => {
  if (error) {
    console.error('Error connecting to MongoDB.', error.stack)
    process.exit(1)
  }

  console.log('Connected to database.')

  const Query = require('./resolvers/Query')

  const resolvers = {
    Query
  }

  readContent('./schema.graphql', (error, content) => {
    if (error) throw error

    const schema = makeExecutableSchema({
      typeDefs: content,
      resolvers
    })

    const server = new ApolloServer({
      schema: schema
    })

    server.listen().then(({ url }) => {
      console.log(`Server ready at ${url}.`)
    })
  })
})

schema.graphql

type CourseType {
  _id: String!
  name: String!
}

type Query {
  courseType(_id: String): CourseType
  courseTypes: [CourseType]!
}

0
对于任何正在寻找Apollo文档的人,这里是相关问题的文档链接:https://www.apollographql.com/docs/apollo-server/workflow/generate-types 文档中描述了使用readFileSync的方法,就像这里的许多答案一样,但我在找到他们实际描述这种方法的地方时遇到了困难。这里也附上了代码片段:
// ...other imports

import { readFileSync } from 'fs';


// Note: this uses a path relative to the project's

// root directory, which is the current working directory

// if the server is executed using `npm run`.

const typeDefs = readFileSync('./schema.graphql', { encoding: 'utf-8' });


const server = new ApolloServer<MyContext>({

  typeDefs,

  resolvers,

});


// ... start our server

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接