Reputation: 11
Consider the example:
query myListQuery($someTest: Boolean) {
id
price
taxRate
expensiveField @skip(if: $someTest)
}
here, the graphQL query will be executed; in its server resolvers, GQL operation body will be translated to an appropriate REST request, e.g. POST
/list
. REST API responds with an array of full entities, e.g.:
[
{ id, product, color, size, price, taxRate, expensiveField },
{ id, product, color, size, price, taxRate, expensiveField },
{ id, product, color, size, price, taxRate, expensiveField },
]
Mind, the expensiveField
; it is expensive, because it is computed in the runtime of a backend, on-request. (Even though its Math.multiply(price, taxRate)
).
Now that the GQL server received the response from REST, it starts applying some filtering of properties: firstly it returns me fields that I requested originally (id, price, taxRate only), but secondly it applies the directive of @skip
(here, for expensiveField
). The filtering is happening in post-processing! This is bad, IMO.
I tried to fine-tune the POST
/list
endpoint, that would accept the ?fields=
argument. That way I can whitelist the exact fields that I request from the GraphQL. Easy. But I, eventually, realized, that the Apollo Client and Apollo Server anyway sends me those properties to REST, even if they are under the directive of @skip
. As directive is applied for post-processing.
As a workaround, I need to implement a custom logic on the fronted now, to strip out the fields marked with a directive.
query myListQuery($someTest: Boolean) {
id
price
taxRate
-expensiveField @skip(if: $someTest)
+#expensiveField @skip(if: $someTest)
}
Is there any library that works in pair with import gql from 'graphql-tag';
/gql``
and can strip out the directives automatically for me, on the client-side?
Upvotes: 1
Views: 285
Reputation: 11
After searching for some time online, I came to this Apollo Link (read more about Links concept) @freshcells/apollo-link-field-keep
This is exactly what I was looking for. Let me give an example:
This is how you write the code in the source
query myListQuery {
id
price
taxRate
expensiveField @keep(if: false)
}
eventually directive does strip out the expensiveField
field away on a Client side, producing such request body:
query myListQuery {
id
price
taxRate
}
It also works perfectly with subfields.
query myQuery {
post(id: 123) {
id
name
author @keep(if: false) {
firstName
lastName
}
}
}
will strip out the author {}
completely on the Client side, resulting in:
query myQuery {
post(id: 123) {
id
name
}
}
Plus, cherry on top, it will remove the whole field query including arguments. It will also clean up all variables that might be used (if not used by other fields).
P.S. There are also use cases for feature-flagging
Upvotes: 0