graphql-tag icon indicating copy to clipboard operation
graphql-tag copied to clipboard

Fix: Concatenate document definitions

Open nhodges opened this issue 5 years ago • 2 comments

Issue Fixed #159

Proposed Changes

  • Concatenate document definitions while filtering for duplicates

Based on PR #105 by @evanrs, updated for current version of graphql-tag

Document fragments parsed by graphql-tag/loader lose their definitions when used with a gql tagged template literal. This is fixed by concatenating the document definitions—filtering for duplicates.

Without this, the following would fail:

import catFaceFragment from './catFaceFragment.gql';

const query = gql`
  query Kitten($name: String) {
    kitten(name: $name) {
      ... CatFace
    }
  }
  ${catFaceFragment}
`
#import "./whiskers.gql"

fragment CatFace on Cat {
  ... Whiskers
}
fragment Whiskers on Cat {
  whiskers {
    quantity
    length
    areWiderThanBody
  }  
}
Unknown fragment "Whiskers".

Why?

Currently, to make an example like the above work, you would have to do something like:

import { parse, print } from 'graphql'
import catFaceFragment from './catFaceFragment.gql';

const query = parse`
  query Kitten($name: String) {
    kitten(name: $name) {
      ... CatFace
    }
  }
  ${print(catFaceFragment)}
`

This has an outsized impact on bundle size due to having to pull in both parse/print instead of having graphql-tag do the lifting

nhodges avatar Jan 22 '20 17:01 nhodges

@nhodges: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/

apollo-cla avatar Jan 22 '20 17:01 apollo-cla

There seems to be a bug in the current PR BTW - it's not enough to just add one if in gql() function, one needs to track ALL pieces of each GraphQL fragment and re-glue them over and over doing de-duplication. Otherwise it won't work for rhombus-like structure.

For future googlers, I wrote a small extension which wraps gql and just does this - removes duplicates of fragments. To use, just replace import gql from "graphql-tag" to import gql from "gql-dedup", no other changes are required.

https://www.npmjs.com/package/gql-dedup

dimikot avatar Jun 26 '20 04:06 dimikot