Atualmente, se quisermos usar o cache HTTP no GraphQL, devemos usar um servidor GraphQL que suporte consultas persistentes. Isso ocorre porque a consulta persistente já terá a consulta GraphQL armazenada no servidor; como tal, não precisamos fornecer essas informações em nossa solicitação.
Para que os servidores GraphQL também ofereçam suporte ao cache HTTP por meio de um único endpoint , a consulta GraphQL deve ser fornecido como um parâmetro de URL. Esperamos que a especificação GraphQL sobre HTTP atinja esse objetivo, fornecendo uma linguagem padronizada para todos os clientes, servidores e bibliotecas GraphQL para interagir uns com os outros.
Suspeito, porém, que todas as tentativas de passar uma consulta GraphQL por meio de um parâmetro de URL estarão longe do ideal. Isso ocorre porque um parâmetro de URL deve ser fornecido como um valor de linha única, então a consulta precisará ser codificada ou reformatada, dificultando a compreensão (para nós, humanos, não para máquinas).
Por exemplo, esta é a aparência de uma consulta GraphQL ao substituir todas as quebras de linha por espaços para caber em uma única linha:
{posts (limite: 5) {id title @titleCase excerpt @default (valor:"Sem título", condição: IS_EMPTY) autor {nome} marcações {id nome} comentários (limite: 3, ordem:"data | DESC") {id data (formato:"d/m/Y") autor {nome} conteúdo}}}
Você consegue entender isso? Eu também não.
E é assim que o cliente GraphiQL codifica a consulta simples {posts {id title}}
como um parâmetro de URL:
% 7B% 0A% 20% 20posts% 20% 7B% 0A% 20% 20% 20% 20id% 0A% 20% 20% 20% 20title% 0A% 20% 20% 7D% 0A% 7D
Mais uma vez, não sabemos o que está acontecendo aqui.
Ambos os exemplos evidenciam o problema: consultas GraphQL de uma linha podem funcionar do ponto de vista técnico, transmitindo as informações para o servidor, mas não é fácil para as pessoas lerem e escreverem essas consultas.
Ser capaz de operar com consultas de uma única linha teria muitos benefícios. Por exemplo, poderíamos compor a consulta diretamente na barra de endereço do navegador, dispensando a necessidade de algum cliente GraphQL.
Não é que eu não goste de clientes GraphQL-na verdade, eu amo GraphiQL. Mas não gosto da ideia de depender deles.
Em outras palavras, podemos nos beneficiar de uma sintaxe de consulta que permite às pessoas:
- Escreva uma consulta diretamente em uma única linha
- Compreenda rapidamente a consulta de uma linha
Este é um desafio formidável. Mas não é intransponível.
Neste artigo, apresentarei uma sintaxe alternativa, que permite ser “fácil de ler e escrever em uma única linha” por nós, humanos.
Na verdade, não estou propondo a introdução dessa sintaxe no GraphQL-entendo que isso nunca aconteceria. Mas o processo de design para esta sintaxe pode, no entanto, exemplificar o que devemos prestar atenção ao projetar a especificação GraphQL sobre HTTP.
Por que a sintaxe GraphQL é tão difícil de entender em uma única linha?
Vamos primeiro explorar qual é o problema com a sintaxe GraphQL e, em seguida, generalizá-la para outras sintaxes.
Identificando o problema
A meu ver, a dificuldade vem dos campos em uma consulta GraphQL sendo aninhados, em que o aninhamento pode avançar e retroceder ao longo da consulta. É esse comportamento de vaivém que o torna difícil de entender quando escrito em uma única linha.
Se o aninhamento na consulta apenas avançar, não será tão difícil entendê-lo. Faça esta consulta, por exemplo:
{ Postagens { eu ia título excerto comentários { eu ia data contente autor { eu ia nome url Postagens { eu ia título } } } } }
Aqui, o aninhamento apenas prossegue:
Ao examinar a consulta sempre progressiva e digitalizá-la da esquerda para a direita, ainda podemos entender a qual entidade cada campo pertence:
{posts {comentários do excerto do título do id {autor do conteúdo da data do id {post do url do nome do id {título do id}}}}}
Agora, considere a mesma consulta GraphQL, mas reorganizando os campos para que as folhas apareçam após as conexões:
{ Postagens { eu ia comentários { eu ia data autor { Postagens { eu ia título } eu ia nome url } contente } título excerto } }
Nesse caso, podemos dizer que os campos avançam e também recuam:
Esta consulta pode ser escrita em uma única linha, como esta:
{posts {id comentários {id data autor {posts {id title} id nome url} conteúdo} excerto do título}}
Agora, entender a consulta não é mais tão fácil. Depois de um nível de recuo (ou seja, logo após uma conexão), podemos não lembrar qual entidade veio antes dela, então não saberemos onde o campo pertence:
(Acho que isso está relacionado ao cérebro humano ter uma memória de curto prazo limitada, capaz de manter não mais do que um alguns itens de cada vez.)
E quando há muitos níveis de avanço e retrocesso, torna-se quase impossível compreendê-lo totalmente. Esta consulta é compreensível:
{ Postagens { eu ia comentários { eu ia data crianças { eu ia autor { nome url } contente } autor { Postagens { eu ia título Tag { nome } } eu ia nome amigos { eu ia nome } url } contente } título excerto } autor { nome } }
Mas não há como entendermos seu equivalente de linha única:
{posts {id comentários {id data filhos {id autor {name url} conteúdo} autor {posts {id title tags {name}} id name friends {id name} url} content} title excerpt} author {name} }
Em conclusão, as consultas GraphQL não podem ser facilmente representadas em uma única linha, de forma que nós, humanos, possamos entendê-las, devido ao seu comportamento de aninhamento.
Generalizando o problema
O problema não é específico do GraphQL. Na verdade, isso acontecerá com uma sintaxe-qualquer sintaxe-onde os elementos avançam e recuam.
Pegue JSON, por exemplo:
{ "nome":"leoloso/PoP", "descrição":"PoP monorepo", "repositórios": [ { "tipo":"pacote", "pacote": { "nome":"leoloso-pop-api-wp/newsletter-subscriptions-rest-endpoints", "version":"master", "tipo":"plugin-wordpress", "fonte": { "url":"https://gist.github.com/leoloso/6588f6c1bdcce82fc317052616d3dfb4", "type":"git", "referência":"mestre" } } }, { "tipo":"pacote", "pacote": { "nome":"leoloso-pop-api-wp/disable-user-edit-profile", "versão":"0.1.1", "tipo":"plugin-wordpress", "fonte": { "url":"https://gist.github.com/leoloso/4e367eb8d8014a7aa7580567608bd5b4", "type":"git", "referência":"mestre" } } }, { "tipo":"vcs", "url":"https://github.com/leoloso/wp-muplugin-loader.git" } ], "estabilidade mínima":"dev", "prefer-stable": verdadeiro, "requer": { "php":"~ 8.0", "getpop/api-rest":"dev-master", "getpop/engine-wp-bootloader":"dev-master" }, "extra": { "branch-alias": { "dev-master":"1.0-dev" }, "tipos de instalador": [ "cliente-gráfico", "graphql-voyager" ], "caminhos do instalador": { "wordpress/wp-content/mu-plugins/{$ name}/": [ "tipo: wordpress-muplugin" ], "wordpress/wp-content/plugins/{$ name}/": [ "type: wordpress-plugin", "getpop/engine-wp-bootloader" ] } }, "config": { "sort-packages": verdadeiro } }
Convertê-lo em uma única linha torna muito difícil de compreender:
{"nome":"leoloso/PoP","descrição":"PoP monorepo","repositórios": [{"tipo":"pacote","pacote": {"nome":"leoloso-pop-api-wp/newsletter-subscriptions-rest-endpoints","version":"master","type":"wordpress-plugin","source": {"url":"https://gist.github. com/leoloso/6588f6c1bdcce82fc317052616d3dfb4","type":"git","reference":"master"}}}, {"type":"package","package": {"name":"leoloso-pop-api-wp/disable-user-edit-profile","version":"0.1.1","type":"wordpress-plugin","source": {"url":"https://gist.github. com/leoloso/4e367eb8d8014a7aa7580567608bd5b4","type":"git","reference":"master"}}}, {"type":"vcs","url":"https://github.com/leoloso/wp-muplugin-loader.git"}],"minimum-stable":"dev","prefer-stable": true,"require": {"php":"~ 8.0","getpop/api-rest":"dev-master","getpop/engine-wp-bootloader":"dev-master"},"extra": {"branch-alias": {"dev-master":"1.0-dev"},"installer-types": ["graphiql-client","graphql-voyager"],"installer-caminhos": {"wordpress/wp-content/mu-plugins/{$ name}/": ["type: wordpress-muplugin"],"wordpress/wp-content/plugins/{$ name}/": ["type: wordpress-plugin","getpop/engine-wp-bootloader"]}},"config": {"sort-packages": true}}
Além do mais, quando a sintaxe usa espaçamento para aninhar seus elementos, nem será possível escrevê-la em uma única linha.
Esse é o caso, por exemplo, com YAML:
serviços: _defaults: public: true autowire: true autoconfigure: true PoP \ API \ PersistedQueries \ PersistedQueryManagerInterface: classe: \ PoP \ API \ PersistedQueries \ PersistedQueryManager # Substituir o serviço PoP \ ComponentModel \ Schema \ FieldQueryInterpreterInterface: classe: \ PoP \ API \ Schema \ FieldQueryInterpreter PoP \ API \ Hooks \: recurso:'../src/Hooks/*'
Projetando uma sintaxe de consulta diferente
Descreverei o design de uma alternativa à sintaxe GraphQL: a sintaxe PQL , usado por GraphQL por PoP (o servidor GraphQL em PHP que eu criei) para aceitar consultas baseadas em URL passadas via GET
.
Uma vez que o problema com a sintaxe GraphQL surge da retirada de campos aninhados, a solução parece evidente: o fluxo da consulta deve ser sempre para a frente.
Como o PQL consegue isso? Para demonstrar, vamos explorar a sintaxe PQL.
Sintaxe de campo
No GraphQL, um campo é escrito assim:
{ alias: fieldName (fieldArgs) @fieldDirective (DirectiveArgs) }
Em PQL, um campo é escrito assim:
fieldName (fieldArgs) [@ alias]
Portanto, é bastante semelhante, mas existem algumas diferenças:
- O alias não é colocado antes do campo, mas depois do campo
- O alias é identificado não com
:
, mas com@
(e, opcionalmente, cercado por[...]
(para “ favoritos ”, explicado mais tarde) - A diretiva não é identificada com
@
, mas entre<...>
Essas diferenças estão diretamente relacionadas ao fluxo sempre avançado necessário para a consulta.
Na minha própria experiência, ao escrever consultas diretamente na barra de endereço do navegador, sempre penso na necessidade do alias depois de ter escrito o nome do campo, não antes. Portanto, usando a ordem como em GraphQL, tive que voltar para essa posição (pressionando a tecla de seta para a esquerda), adicionar o alias e voltar para a posição final (pressionando a tecla de seta para a direita).
Isso foi bastante complicado. Fazia muito mais sentido colocar o alias após o nome do campo, tornando-o um fluxo natural.
Ao definir o alias após o nome do campo, não faz mais sentido usar :
. Este símbolo é usado pelo GraphQL para que a resposta JSON respeite o formato da consulta. Uma vez que a ordem entre o campo e o alias é invertida, usar @
parece um ajuste natural.
Isso, por sua vez, significava que não podíamos mais usar @
para identificar diretivas. Em vez disso, escolhi uma sintaxe envolvente <...>
(por exemplo,
) para que as diretivas também possam ser aninhadas (por exemplo,
), possibilitando que GraphQL por PoP ofereça suporte a recurso de diretivas composíveis .
Campos
No GraphQL, podemos adicionar dois ou mais campos adicionando um espaço ou quebra de linha entre eles:
{ foo bar }
Em PQL, usamos o caractere |
para separar campos:
foo | bar
Já podemos visualizar como a consulta é composta em uma única linha:
- Não há
{}
caracteres - Não há espaços ou quebras de linha
Também podemos apreciar que a consulta pode ser composta diretamente no navegador, passada através do parâmetro de URL query
.
Por exemplo, o URL para executar a consulta id | __typename
é: $ {endpoint}? query=id | __typename .
Usando DevTools, podemos ver como o cache HTTP é compatível com o ponto de extremidade único GraphQL:
Para todas as consultas demonstradas abaixo, haverá um link Executar consulta no navegador . Clique neles para visualizar como o PQL funciona em um site real em produção.
Fazer consultas visualmente atraentes
Semelhante ao GraphQL , novas linhas (e também espaços) não adicionam nenhum significado semântico. Assim, podemos adicionar quebras de linha de forma conveniente para ajudar a visualizar a consulta:
foo | bar
Ao usar o Firefox, esta consulta pode ser copiada (de um editor de texto, uma página da web, etc.) e colada na barra de endereço do navegador, e todas as quebras de linha serão removidas automaticamente, criando a consulta de linha única equivalente.
Conexões
GraphQL usa caracteres {}
para definir dados para conexões:
{ Postagens { autor { eu ia } } }
Em PQL, a consulta apenas avança, nunca recua. Portanto, há um equivalente para {
, que é .
, mas não há equivalente para }
, pois não será necessário.
posts. autor. eu ia
Execute a consulta no navegador .
Podemos combinar |
e .
para buscar vários campos para qualquer entidade. Considere esta consulta GraphQL:
{ Postagens { eu ia título autor { eu ia nome url } } }
Seu equivalente em PQL seria:
posts. id | título | autor. id | nome | url
Executar consulta no navegador .
Nesse ponto, podemos enfrentar o desafio: como o PQL aceita apenas campos de avanço?
Sintaxe para um fluxo apenas de avanço
As consultas vistas acima estavam sempre avançando. Vamos agora abordar as consultas que também precisam ser retiradas, como esta consulta GraphQL:
{ Postagens { eu ia autor { eu ia nome url } comentários { eu ia contente } } }
PQL usa o caractere ,
para unir elementos. É semelhante a |
para unir campos, mas com uma diferença fundamental: o campo à direita de ,
começa a percorrer o gráfico novamente a partir da raiz.
Então, a consulta acima tem este equivalente em PQL:
posts. id | autor. id | nome | url, Postagens. comentários. id | contente
Executar consulta no navegador .
Observe como, para torná-lo visualmente atraente, name |
e url
têm o mesmo preenchimento à esquerda, já que |
mantém o mesmo caminho posts.author.
. Mas não há preenchimento à esquerda logo após ,
porque a consulta começa novamente a partir da raiz.
Podemos pensar que esta consulta também recua:
No entanto, isso não é tanto um recuo, mas um”reset”. No GraphQL, podemos voltar à posição anterior na consulta-ou seja, o nó pai no gráfico-quantas vezes forem os níveis inferiores que percorremos. No PQL, porém, não podemos: sempre voltamos até a raiz do gráfico.
Começando da raiz novamente, devemos mais uma vez especificar o caminho completo para o nó para continuar adicionando campos. Isso torna a consulta mais detalhada. Por exemplo, o caminho posts
na consulta acima aparece uma vez no GraphQL, mas duas vezes no PQL.
Essa redundância força os humanos a recriar o caminho ao ler e escrever a consulta para cada nível do gráfico. Isso nos permite entender a consulta quando expressa em uma única linha:
posts.id | author.id | nome | url, posts.comments.id | conteúdo
Como estamos recriando o caminho em nossas cabeças, não sofremos o problema de memória de curto prazo que nos faz perder ao olhar para a consulta GraphQL.
Marcadores para remover verbosidade
Ter que recriar todo o caminho para o nó pode se tornar um incômodo.
Considere esta consulta GraphQL:
{ Comercial { Postagens { autor { eu ia nome } comentários { eu ia contente } } } }
E seu equivalente em PQL:
usuários
. Postagens. autor. id | nome, Comercial. Postagens. comentários. id | contente
Executar consulta no navegador .
Para recuperar o campo comentários
, novamente precisamos adicionar users.posts.
. Quanto mais o nível abaixo no gráfico, mais longo o caminho para replicar.
Para resolver esse problema, o PQL apresenta um novo conceito: um”marcador”, que fornece um atalho para um caminho já percorrido para que possamos continuar carregando dados de maneira conveniente a partir desse ponto.
Definimos um favorito colocando seu nome entre [...]
ao iterar por algum caminho, e então esse caminho é automaticamente recuperado ao fazer referência a seu favorito, novamente colocando seu nome entre [...]
, a partir da raiz da consulta.
Na consulta acima, podemos marcar users.posts
como [userposts]
:
usuários
. postagens [postagens do usuário]. autor. id | nome, [postagens do usuário]. comentários. id | contente
Execute a consulta no navegador .
Para facilitar a visualização, também podemos adicionar o preenchimento equivalente à esquerda do marcador aplicado, correspondendo ao mesmo preenchimento de seu caminho (de forma que comentários
apareça abaixo de posts
):
usuários
. postagens [postagens do usuário]. autor. id | nome, [postagens do usuário]. comentários. id | contente
Com os favoritos, ainda podemos entender a consulta quando expressa em uma única linha:
users.posts [userposts].author.id | name, [userposts].comments.id | content
Se precisarmos definir um favorito e um alias, podemos ter o símbolo @
embutido no [...]
:
usuários
. posts [@userposts]. autor. id | nome, [postagens do usuário]. comments.id | contente
Executar consulta no navegador .
Simplificando os argumentos de campo
No GraphQL, os valores String
em argumentos de campo devem ser colocados entre aspas "..."
:
{ Postagens { eu ia título data (formato:"d/m/Y") } }
Ter que digitar essas aspas ao compor a consulta no navegador provou ser muito chato; Muitas vezes eu os esquecia e precisava navegar para a esquerda e para a direita com as teclas de seta para adicioná-los.
Portanto, em PQL, as aspas de string podem ser omitidas:
posts. id | título | data (formato: d/m/Y)
Executar consulta no navegador .
Aspas de string são necessárias quando a consulta seria interrompida de outra forma:
posts. id | título | data (formato:"d M, Y")
Execute a consulta no navegador .
Além disso, o argumento do campo às vezes pode ser tornado implícito; por exemplo, quando o campo tem apenas um argumento de campo. Nesse caso, o PQL permite omiti-lo:
posts. id | título | data (d/m/A)
Executar consulta no navegador .
Variáveis
No GraphQL, as variáveis são definidas no corpo da solicitação como um JSON codificado:
{ "query":"query ($ format: String) { Postagens { eu ia título data (formato: $ format) } }", "variáveis":"{ \"format \": \"d/m/Y \" }" }
Em vez disso, o PQL usa as entradas padrão HTTP, passando variáveis via $ _GET
ou $ _POST
:
? query= Postagens. id | título | data (formato $) & format=d/m/Y
Executar consulta no navegador .
Também podemos passar variáveis nas variáveis
de entrada:
? query= Postagens. id | título | data (formato $) & variáveis [formato]=d/m/Y
Execute a consulta no navegador .
Fragmentos
GraphQL emprega fragmentos para reutilizar seções de consulta:
{ Comercial { ...dados do usuário Postagens { comentários { autor { ...dados do usuário } } } } } fragmento userData no usuário { eu ia nome url }
Em PQL, os fragmentos seguem o mesmo método das variáveis para sua definição: como entradas em $ _GET
ou $ _POST
. Eles são referenciados com -
:
? query= Comercial. --userData | Postagens. comentários. autor. --dados do usuário & userData= id | nome | url
Execute a consulta no navegador .
O fragmento também pode ser definido em fragmentos
de entrada:
? query= Comercial. --userData | Postagens. comentários. autor. --dados do usuário & fragmentos [userData]= id | nome | url
Execute a consulta no navegador .
Conversão de consultas entre as sintaxes GraphQL e PQL
PQL é um superconjunto da sintaxe de consulta GraphQL. Portanto, qualquer consulta escrita usando a sintaxe GraphQL padrão também pode ser escrita em PQL.
Por outro lado, nem todas as consultas escritas em PQL podem ser escritas usando a sintaxe GraphQL, porque PQL suporta recursos como campos composíveis e composíveis diretivas que não são suportadas pelo GraphQL.
PQL compreende a maioria dos mesmos elementos:
- Campos e argumentos de campo
- Diretivas e argumentos diretivos
- Aliases
- fragmentos
- Variáveis
Os elementos que não suporta são:
- Operação
- Nome da operação, definições de variáveis e variáveis padrão
- O elemento
on
, para indicar em qual tipo/interface um fragmento deve ser aplicado
Mesmo que esses elementos não sejam compatíveis, sua funcionalidade subjacente é compatível por meio de um método diferente.
A operação está faltando porque não há mais necessidade dela: agora temos a opção de solicitar a consulta usando GET
(para consultas) ou POST
(para mutações ).
The operation name is only needed in GraphQL when the document contains many operations, and we need to specify which one to execute, or maybe execute several of them together, tying them via @export
.
In the previous case, there’s no need for it for PQL — we only pass the query that must be executed, not all of them.
In the latter case, the multiple operations can be executed together in a single request, while guaranteeing their execution order, by joining them with ;
like so:
posts. author. id| name| url; posts. comments. id| content
In GraphQL, the variable definition is used to define the type of the variable, enabling clients like GraphiQL to show an error whenever the type is different. This is a nice-to-have, but not really needed for executing the query itself.
Default variable values can be defined like any variable: via a URL param.
The on
element is not needed since we can instead use the directive @include
, passing a composable field isType
as argument, to find out the type of the object and, based on this value, apply the intended fragment or not.
For instance, take this GraphQL query:
{ customPosts { __typename ... on Post { título } } }
This the PQL equivalent:
customPosts. __typename| title
Converting the introspection query
Let’s convert the introspection query used by GraphiQL (and other clients) to obtain the schema metadata from the GraphQL syntax to PQL.
The introspection query is this one:
query IntrospectionQuery { __schema { queryType { nome } mutationType { nome } subscriptionType { nome } types { ...FullType } directives { nome Descrição Localizações args { ...InputValue } } } } fragment FullType on __Type { Gentil nome Descrição fields(includeDeprecated: true) { nome Descrição args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { nome Descrição isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { nome Descrição type { ...TypeRef } defaultValue } fragment TypeRef on __Type { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome } } } } } } } }
Its equivalent PQL query is this one:
?query= __schema[schema]. queryType. name, [schema]. mutationType. name, [schema]. subscriptionType. name, [schema]. types. --FullType, [schema]. directives. name| description| locations| args. --InputValue &fragments[FullType]= kind| name| description| fields(includeDeprecated: true)[@fields]. name| description| args. --InputValue, [fields]. type. --TypeRef, [fields]. isDeprecated| deprecationReason, [fields]. inputFields. --InputValue, [fields]. interfaces. --TypeRef, [fields]. enumValues(includeDeprecated: true)@enumValues. name| description| isDeprecated| deprecationReason, [fields]. possibleTypes. --TypeRef &fragments[InputValue]= name| description| defaultValue| type. --TypeRef &fragments[TypeRef]= kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| nome
Execute query in browser. (Note that the query in this link is slightly different than the one above since I still need to add support for the ,
token within fragments.)
And this is the query written in a single line:
?query=__schema[schema].queryType.name,[schema].mutationType.name,[schema].subscriptionType.name,[schema].types.--FullType,[schema].directives.name|description|locations|args.--InputValue&fragments[FullType]=kind|name|description|fields(includeDeprecated: true)[@fields].name|description|args.--InputValue,[fields].type.--TypeRef,[fields].isDeprecated|deprecationReason,[fields].inputFields.--InputValue,[fields].interfaces.--TypeRef,[fields].enumValues(includeDeprecated: true)@enumValues.name|description|isDeprecated|deprecationReason,[fields].possibleTypes.--TypeRef&fragments[InputValue]=name|description|defaultValue|type.--TypeRef&fragments[TypeRef]=kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name
Some more examples
This query has a fragment containing nested paths, variables, directives, and other fragments:
?query= posts(limit:$limit, order:$order). --postData| author. posts(limit:$limit). --postData &postData= id| title| --nestedPostData| date(format:$format) &nestedPostData= comments. id| content &format=d/m/Y &include=true &limit=3 &order=title
This query applies a directive to a fragment, which is consequently applied on all the fields within the fragment:
?query= posts. id| --props&fragments[props]= title| data
Finally, there are many examples of single-line queries embedded directly as a URL param, and containing additional properties from the PQL syntax (not described in this article), in this blog post.
Conclusion
In order to support HTTP caching, we must currently use GraphQL servers that support persisted queries.
But what about the GraphQL single endpoint? Could it also support HTTP caching? And if so, could it be done in a way that people can write the query instead of having to depend on a client or library?
The response to these questions is: yes, it can be done. However, the GraphQL syntax currently stands in the way due to its nesting behavior.
In this article I demonstrated an alternative syntax, called PQL, that would enable GraphQL servers to accept the query via the URL param, while enabling people to read and write the query in a single line, even directly in the browser’s address bar.
The post Designing a URL-based query syntax for GraphQL appeared first on LogRocket Blog.