Skip to content

Files

Latest commit

 

History

History
205 lines (129 loc) · 8.16 KB

File metadata and controls

205 lines (129 loc) · 8.16 KB

Relay Compiler

Introduction - What is the Relay compiler?

Relay is a JavaScript framework for building data-driven React applications powered by GraphQL, designed from the ground up to be easy to use, extensible and, most of all, performant. Relay accomplishes this with static queries and ahead-of-time code generation.

Source: Introduction to Relay

All modern JavaScript web apps face the challenge of managing data effectively and performantly. Relay is a library that addresses this problem for React apps.

Relay allows us to specify the data needed for each component within each component. This makes for a nice developer experience because the data is defined right next to the code rendering it.

Independently querying for the data that each component needs would be terribly inefficient. To address this, Relay aggregates the data needed for all components in a tree into one top-level query — so one network request is made for all the required data on the page.

At build-time, Relay's compiler inspects the component tree to discover all data needed, and generates the appropriate infrastructure to execute optimized GraphQL queries at runtime.

🎯 In this exercise we'll see how the Relay compiler generates the artifacts it needs to make efficient data requests.

Exercise 0: Compiling with Relay

Setting up

Start the app:

💻 Run yarn start-exercise-0 from a console pointed at the root of this project

View the app for this exercise in a browser:

💻 Visit localhost:1234/exercise-0

Orient yourself

This app renders information about an artist.

The app for this exercise, running in a browser

The component rendering the artist information is the Artist0 component. It emits the artist name:

return (
  <div>
    <h1>{props.artist.name}</h1>
  </div>
)

Artist0.tsx, lines 10-14

The component is connected to Relay (don't worry about how yet). It queries for data on the Artist type of our GraphQL schema by defining a query fragment:

fragment Artist0_artist on Artist {
  name
}

Artist0.tsx, lines 19-21

The Relay compiler inspects fragments like this one to generate the infrastructure it needs to efficiently query our GraphQL endpoint at runtime.

Enhance the Artist0 component

It'd be nice if our users could see the artist's year of birth in addition to their name. Lucky for us: our GraphQL schema exposes that data for us! In addition to id and name, the Artist type defined in our schema also holds a birthYear property:

type Artist {
  id: ID!
  name: String!
  birthYear: Int!
}

src/graphql/schema/fakeArtsy.graphql, lines 5-9

We want to update our component to query and emit this field.

Add the field to the component

Start by adding the birthYear property to the GraphQL query fragment.

💻 Add birthYear to line 21 in the Artist0 component:

fragment Artist0_artist on Artist {
  name
  birthYear
}

Artist0.tsx, lines 19-22

Then we'll need to render the field in the React component.

💻 Add a line to render the birthYear field in the Artist0 component:

return (
  <div>
    <h1>{props.artist.name}</h1>
    <h2>b. {props.artist.birthYear}</h2>
  </div>
)

Artist0.tsx, lines 10-15

💻 Save the Artist0.tsx file.

Your browser should auto-refresh. You should see.....

A place for the birth year to display, but no actual birth year.

No birth year showing yet

🤔 Why doesn't this work?

We added the field to the component, and the GraphQL query...but Relay hasn't compiled this new field into its runtime infrastructure. Relay needs to aggregate all the requested data at build-time, so that it knows the proper query to send to the server. Our app is not requesting this new field from GraphQL yet because the Relay compiler hasn't included it yet.

Let's fix this!

Run the Relay compiler

💻 Run yarn relay from a terminal.

This shouldn't take long to run, and the output shouldn't contain any errors. When it's finished your page should reload with the artist's birth year now showing!

The birth year is showing!

🎉 We did it!

What did the Relay compiler do?

You might have noticed a __generated__ subfolder in ./src/exercises/00-Relay-Compiler. This folder contains all the infrastructure generated by the Relay compiler — everything it needs to query our GraphQL endpoint at runtime.

There's a file in here named Artist0_artist.graphql.ts. If we look inside, we'll find a couple changes that Relay made when we ran the compiler:

Relay added the new field to the query that will be used at runtime.

Toward the bottom of Artist0_artist.graphql.ts you'll see a variable named node defined. This defines the shape of the query that Relay will be making for this component at runtime, and it now contains the field we added:

const node: ReaderFragment = {
  // ....
  name: "Artist0_artist",
  // ....
  selections: [
    // ....
    {
      alias: null,
      args: null,
      kind: "ScalarField",
      name: "birthYear",
      storageKey: null,
    },
  ],
  type: "Artist",
  // ....
}

__generated__/Artist0_artist.graphql.ts, lines 20-43

Relay added the new field to the associated types.

We're using TypeScript in this tutorial, and we've configured our compiler to generate TypeScript types for our Relay components via the relay-compiler-language-typescript language plugin. TypeScript is not required to work with Relay, but it is extremely helpful. It greatly reduces the chances that you'll reference a property that doesn't exist or that you haven't queried for, because TypeScript will show you an error in those situations.

You might have noticed that before we ran the compiler, we had red squigglies complaining about types missing in our Artist0.tsx:

A TypeScript error: "Property 'birthYear' does not exist on type 'Artist0_artist'."

This was a clue to us that Relay hadn't run. The type for this query fragment didn't yet include the property we added.

Once we ran the compiler, the error went away because the property had been added to the type associated with this component:

export type Artist0_artist = {
  readonly name: string
  readonly birthYear: number
  readonly " $refType": "Artist0_artist"
}

__generated__/Artist0_artist.graphql.ts, lines 7-11

Note: VS Code sometimes holds on to these type errors even after you've compiled Relay. Reloading the VS Code window can fix this.

Wrapping up

In this exercise, we added a new property to an existing Relay-connected component. We saw how the component didn't render our new field until after we ran the Relay compiler. We also looked at the artifacts generated by the Relay compiler.

In day-to-day development with Relay, adding or removing fields from Relay-connected components is a frequent activity. Inspecting the artifacts generated by the Relay compiler is a much less frequent activity — most useful for debugging and other scenarios where things aren't working as expected.

Recommendations

Run Relay compilation automatically

Watch for changes and automatically run Relay compilation by including the --watch flag in your npm/yarn development task. We excluded it for this exercise so that you were in control of running compilation.

The remaining exercises are configured to automatically run Relay compilation when you make changes. You won't need to run it manually anymore.

Note: if you get an error when starting watch mode that you need watchman installed, install it with brew install watchman and retry.

Resources

The Thinking In Relay doc is a great resource for understanding how Relay efficiently renders data from a GraphQL endpoint.