Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How does this compare to graphql-normalizer? #28

Closed
drejohnson opened this issue Jun 16, 2019 · 12 comments
Closed

How does this compare to graphql-normalizer? #28

drejohnson opened this issue Jun 16, 2019 · 12 comments

Comments

@drejohnson
Copy link
Contributor

No description provided.

@jonaskello
Copy link
Member

I haven't used graphql-normalizer but it says:

A GraphQL response normalizer designed to work with apollo-client.

This library OTOH is designed to be as simple and independent (and fast) as possible. It does only normalization (responses to a flat strucutre) and denormalization (flat structure to response). You can use it as a building block to build a normalized client-side cache or you can use it on the server side to normalize (deduplicate) the returned data (although that would require the client to be able to received normalized data and denormalize it before handing it to the app).

Not sure if that helps tough, do you have any specific use-case in mind?

@drejohnson
Copy link
Contributor Author

Thanks. That's actually the wrong library. I spelled the name wrong. Here's the one I was referring to: graphql-normalizr. I'm experimenting with creating a lighweight graphql client for svelte.js and was looking for a library helps provide a caching solution similar to Apollo's InMemoryCache.

@jonaskello
Copy link
Member

jonaskello commented Jun 16, 2019

Ah, yes that makes more sense. We have the same use-case, building a client-side cache and I looked into that library too. It seems to be similar to this, in fact I started an issue there about aliases since that was not supported. However, since that library did not fully support all of graphql syntax (eg. aliases and probably @skip, @include) and I did not fully understand how to use for my purpose, I went ahead and built this library instead.

This library has only normalize and denormlize stateless/pure functions and thus it is very simple. It does not cache anything by itself (so the name is probably not the best :-)). But it does support all of graphql syntax and has a farily good test suite to prove it. Also it is built for speed, for example we use a stack-based approach when parsing to avoid the cost of recursive function calls. (We tried apollo first but it was too slow for our use-case).

graphql-normalizr does have a "addRequiredFields" function that this library does not have. It is handy for adding the __typename to all queries so that you can use that to create unique IDs in the cache. We made a separate library for that in graphql-add-remove-fields

@jonaskello
Copy link
Member

If you are familiar with the normalizr library, the best way to describe gql-cache would be to say it is the exact same thing except it does not need the schema part that normalizr requires since we use the graphql queries to figure out the structure instead.

@drejohnson
Copy link
Contributor Author

Awesome. Thanks for taking time to reply and for creating this library. Very useful and a time saver. I'll continue testing to see if I run into any issues. I did notice that the docs needs updating, specifically in regards to the merge function actually being named mergeEntityCache.

@jonaskello
Copy link
Member

Yes, the docs could use some polishing. I think the plan was to rename mergeEntityCache to merge so from that standpoint it is actually the code that is wrong. PRs for this would certainly be welcome :-).

@stalniy
Copy link

stalniy commented Jun 23, 2019

Does this library support arguments on fields?

Update: some explanation of the challenges can be found in relay docs: https://relay.dev/docs/en/thinking-in-graphql#populating-the-cache

@jonaskello
Copy link
Member

@stalniy Yes it support all of the graphql syntax. See for example this test. To get a unique cache key for the field, we JSON.stringify() the arguments.

Not sure what you mean by the relay link, can you be more specific?

@stalniy
Copy link

stalniy commented Jun 23, 2019

All works fine. Thanks for explanation, I’ve already tried :)

@jonaskello
Copy link
Member

@drejohnson @stalniy FYI, the package has been renamed from gql-cache to graphql-norm. It is basically the same API but I cleaned up a few things. All changes are noted in the changelog.

@monojack
Copy link

If you are familiar with the normalizr library, the best way to describe gql-cache would be to say it is the exact same thing except it does not need the schema part that normalizr requires since we use the graphql queries to figure out the structure instead.

@jonaskello , hi! Nice to see you built your own solution to handle your needs. One thing I would like to point out, though: graphql-normalizr doesn't require the schema, nor the query just the __typename field to be present in the response.

@jonaskello
Copy link
Member

jonaskello commented Jul 21, 2019

Yes that's a good point. The reference in the readme is for the paularmstrong/normalizr package. I used that once with graphql and it worked but I had to hand-code normalizr schemas for every part of the graphql schema which is one of the main reasons I went ahead and made graphql-norm. Both graphql-normalizr and graphql-norm have better approaches that are more integrated with graphql.

In graphql-norm there are no required fields, instead you pass a callback function that will extract the ID of each object during normalization. That callback can of course use __typename if you want. This is the same approach that apollo uses. The callback approach is more flexible but one drawback is that graphql-norm cannot divide the cache into sections according to entity type like graphql-normalizr (and normalizer) does. Instead graphql-norm has a flat cache which can be a bit hard to work during debugging when it grows large. Prefixing all IDs with __typename helps tough.

The graphql schema is not required by graphql-norm either but the query is. You can get quite far with normalization without knowing the query but there are some cases that are not possible without it. For example if a field is aliased in the query, the data will only contain the alias, not the original field name from the graphql schema. To know the original name you need the query. If normalization happens using the alias and the same field is queried multiple times with different aliases it will be stored multiple times under different names. Another feature that requires the query during normaliztion is using varriables on fields as they are not derivable from the data alone.

@monojack Btw, I think you may have an old version of the readme cached since it referes to the old package name (gql-cache). You may want to refresh to get the latest version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants