Introducing @graphql-tools/external-fragment-loader

Igor Kusakov
Igor Kusakov
On this page

We’re excited to introduce @graphql-tools/external-fragment-loader, a new package in GraphQL Tools that makes sharing GraphQL fragments across packages easier!

The loader resolves missing GraphQL fragments by following direct and transitive dependencies in package.json. It loads the external fragments your package needs.

Why we built it

At Yelp, we have a large monorepo where GraphQL fragments are shared across packages. Although we try to avoid reusing fragments directly, they still need to be imported and spread into page-level operations. An operation in one package can use a fragment from a dependency listed in package.json. That fragment can, in turn, use fragments from other dependencies.

Previously, we had to manually maintain a list of files containing these external fragments, both to assemble complete GraphQL operations for execution and to run GraphQL Code Generator. Adding a fragment dependency meant updating the list with its file and the files containing any fragments it referenced transitively. As packages evolved, keeping the list up to date became tedious.

For example, a package might use a fragment named FragmentA from a shared package. Its file must be added manually to the consuming package’s list. If FragmentA starts referencing FragmentB from another package, the list must include that fragment’s file too, even though the consuming package’s own operation hasn’t changed.

Here is an example of a manually maintained list:

project:
  package-a:
    external-fragment-files:
      - path/to/file/with/FragmentA.ts
      - path/to/file/with/FragmentB.ts

Loading fragments from package dependencies automatically

The external fragment loader resolves missing GraphQL fragments by following direct and transitive dependencies in package.json. It loads only the external fragments the package needs. In the example above, it finds both FragmentA and FragmentB automatically.

The external fragment loader checks direct and transitive package dependencies to find missing fragments and return them in the result.

Here is an example configuration for GraphQL Code Generator using the new loader, assuming Codegen runs from the monorepo root:

import { resolve } from 'node:path'
import type { CodegenConfig } from '@graphql-codegen/cli'

const packageDir = resolve('packages/my-app')

const config: CodegenConfig = {
  schema: './schema.graphql',
  documents: ['./packages/my-app/src/**/*.graphql'],
  externalDocuments: [
    {
      [packageDir]: {
        loader: '@graphql-tools/external-fragment-loader',
        packageDir,
        externalPackagesDirs: [resolve('packages')],
        async: true
      }
    }
  ],
  generates: {
    './packages/my-app/src/__generated__/types.ts': {
      plugins: ['typescript', 'typescript-operations']
    }
  }
}

export default config

With this setup, the loader uses the dependencies declared in package.json to find the required external fragments as they change, without requiring a manually maintained list of files.

See the new loader documentation for more configuration options.

What’s next

We originally built this loader to resolve fragment dependencies before executing GraphQL operations and to support GraphQL Code Generator. Now we’re exploring integrations with GraphQL ESLint and Apollo’s persisted query manifest generator to bring the same fragment resolution to more GraphQL workflows.

Explore

Dive deeper into related topics.

GraphQL

Hive Gateway: Local Subgraph Development Just Got Easier

Jeff Dolle
GraphQL

GraphQL Codegen: Consistent Watcher, a Faster Server Preset, and Fixed Windows Support

Eddy Nguyen

Get your API game right.