GraphQL 正在返回额外的信息,这会减慢初始加载速度

GraphQL is returning extra information which is slowing down the initial loading

我在 graphql 结果中得到了一些额外的信息。 除了 data 和结尾 errors 我得到

所以结果变得相当庞大。我注意到的另一个想法是文档的初始加载和智能感知需要很长时间才能加载。

知道如何删除这些额外数据吗?

graphQL 查询的结果:

GraphQL 控制器

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace ElectronConnectQuery.Controllers.v1
{
    [Route("[controller]")]
    public class GraphQLController : Controller
    {
        private readonly IDocumentExecuter _documentExecuter;
        private readonly ISchema _schema;
        private readonly DataLoaderDocumentListener _listener;
        private readonly ILogger<GraphQLController> _logger;

        public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter, DataLoaderDocumentListener listener, ILogger<GraphQLController> logger)
        {
            _schema = schema;
            _documentExecuter = documentExecuter;
            _listener = listener;
            _logger = logger;
        }

        [HttpPost]
        public async Task<IActionResult> Post([FromBody] GraphQLQuery query, [FromServices] IEnumerable<IValidationRule> validationRules)
        {
            if (query == null) { throw new ArgumentNullException(nameof(query)); }
            _logger.LogDebug("GraphQL received query:{Query}", query.Query);
            var inputs = query.Variables.ToInputs();
            var executionOptions = new ExecutionOptions
            {
                Schema = _schema,
                Query = query.Query,
                Inputs = inputs,
                ValidationRules = validationRules,
                EnableMetrics = false
            };

#if (DEBUG)
            executionOptions.EnableMetrics = true;
#endif

            executionOptions.Listeners.Add(_listener);

            var result = await _documentExecuter.ExecuteAsync(executionOptions).ConfigureAwait(false);

            if (result.Errors?.Count > 0)
            {
                return BadRequest(result);
            }

            return Ok(result);
        }
    }
}

如果您自己编写结果,请使用 IDocumentWriter,这将正确序列化结果。

/// <summary>
/// Serializes an object hierarchy to a stream. Typically this would be serializing an instance of the ExecutionResult class into a JSON stream.
/// </summary>
public interface IDocumentWriter
{
    /// <summary>
    /// Asynchronously serializes the specified object to the specified stream.
    /// </summary>
    Task WriteAsync<T>(Stream stream, T value, CancellationToken cancellationToken = default);
}

还有一种扩展方法可以序列化为string

public static async Task<string> WriteToStringAsync<T>(this IDocumentWriter writer, T value)

此示例显示使用中间件与控制器,但想法是相同的。

https://github.com/graphql-dotnet/examples/blob/529b530d7a6aad878b2757d776282fdc1cdcb595/src/AspNetCoreCustom/Example/GraphQLMiddleware.cs#L75-L81

private async Task WriteResponseAsync(HttpContext context, ExecutionResult result)
{
    context.Response.ContentType = "application/json";
    context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;

    await _writer.WriteAsync(context.Response.Body, result);
}

您需要包含 GraphQL.SystemTextJsonGraphQL.NewtonSoftJson 来选择 IDocumentWriter 的实现。

https://www.nuget.org/packages/GraphQL.SystemTextJson https://www.nuget.org/packages/GraphQL.NewtonsoftJson

我对控制器所做的更改是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.Instrumentation;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace ElectronConnectQuery.Controllers.v1
{
    [Route("[controller]")]
    public class GraphQLController : Controller
    {
        private readonly IDocumentExecuter _documentExecuter;
        private readonly ISchema _schema;
        private readonly DataLoaderDocumentListener _listener;
        private readonly ILogger<GraphQLController> _logger;
        private readonly IDocumentWriter _writer;

        public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter, DataLoaderDocumentListener listener, ILogger<GraphQLController> logger, IDocumentWriter writer)
        {
            _schema = schema;
            _documentExecuter = documentExecuter;
            _listener = listener;
            _logger = logger;
            _writer = writer;
        }

        [HttpPost]
        public async Task Post([FromBody] GraphQLQuery query, [FromServices] IEnumerable<IValidationRule> validationRules)
        {
            if (query == null) { throw new ArgumentNullException(nameof(query)); }
            _logger.LogDebug("GraphQL received query:{Query}", query.Query);
            var inputs = query.Variables.ToInputs();
            var executionOptions = new ExecutionOptions
            {
                Schema = _schema,
                Query = query.Query,
                Inputs = inputs,
                ValidationRules = validationRules,
                EnableMetrics = false,
            };

            executionOptions.Listeners.Add(_listener);

            var result = await _documentExecuter.ExecuteAsync(opts =>
            {   
                opts.Schema = _schema;
                opts.Query = query.Query;
                opts.Inputs = inputs;
                opts.ValidationRules = validationRules;
                opts.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
                opts.EnableMetrics = true;
            }).ConfigureAwait(false);

            result.EnrichWithApolloTracing(DateTime.Now);

            await _writer.WriteAsync(Response.Body, result);
        }


        private async Task WriteResponseAsync(HttpResponse response, ExecutionResult result)
        {
            response.ContentType = "application/json";
            response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;
            await _writer.WriteAsync(response.Body, result);
        }
    }
}

Startup.cs配置服务 我添加了以下几行

  // kestrel
            services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            // IIS
            services.Configure<IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

我也注册了DocumentWriter

services.AddScoped<IDocumentWriter, GraphQL.NewtonsoftJson.DocumentWriter>();