【问题标题】:How to load a .graphql file using `apollo-server`?如何使用 `apollo-server` 加载 .graphql 文件?
【发布时间】:2020-09-29 02:51:10
【问题描述】:

我目前正在使用单独的 .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 工作。

【问题讨论】:

标签: node.js graphql apollo apollo-server


【解决方案1】:

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

1.) 自己阅读文件:

const { readFileSync } = require('fs')

// we must convert the file Buffer to a UTF-8 string
const typeDefs = readFileSync('./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 pluginwebpack loader

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

【讨论】:

  • 这太棒了!不可能有与apollo-server 等效的GraphQLFileLoader 方法?
  • 也许在未来的版本中。
  • 需要注意的是readFileSync只有在指定编码的情况下才会返回字符串,例如:const typeDefs = readFileSync('./schema.graphql', 'utf-8')。如果不包含编码,它将作为 ApolloServer 的构造函数无法理解的 Buffer 返回。
  • 感谢您在readFileSync 中关注'utf-8',我会错过的
  • @DanielRearden 在联合图中加载子图架构时出现此错误ts Unknown directive "@key". Cannot extend type "Membership" because it is not defined. Unknown directive "@key". Unknown directive "@external". Unknown type "Query".
【解决方案2】:

过去我自己写了一个很小的.graphql loader。它非常小,非常简单,您唯一要做的就是在尝试导入任何.graphql 文件之前导入它。从那以后我就一直在使用它,尽管我确信有一些 3rd 方加载器可用。代码如下:

// 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... `;

【讨论】:

    【解决方案3】:

    这对我有用:

    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);
    
    

    【讨论】:

      【解决方案4】:

      使用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]!
      }
      

      【讨论】:

        【解决方案5】:

        这可以通过以下方式实现:

        // schema.ts
        import 'graphql-import-node';
        import {makeExecutableSchema} from 'graphql-tools';
        import {ApolloServer} from 'apollo-server-express';
        import * as typeDefs from './schema/schema.graphql';
        import resolvers from './resolverMap';
        
        const schema = new ApolloServer({
            schema: makeExecutableSchema({
                typeDefs,
                resolvers
            })
        });
        
        export default schema;
        

        【讨论】:

        • 与所询问的内容无关。
        猜你喜欢
        • 2020-10-01
        • 2020-03-08
        • 2020-12-02
        • 2019-09-14
        • 2017-01-15
        • 2021-03-02
        • 2019-12-10
        • 2021-11-25
        • 2021-09-09
        相关资源
        最近更新 更多