How Woovi uses Relay?
Tags: frontend, datafetching, performance
Published: 2023-03-13 15:44:16

## What is Relay?

If you look at [relay.dev](https://relay.dev/), Relay is the GraphQL client that scales with you. This definition is simple and defines Relay pretty well for the ones that already know all the features that Relay brings to the table.

For the ones that still having used Relay or still do not understand all the benefits of using Relay, this article provides practical examples of how Woovi is using Relay to scale their backend and frontend.

## Relay Architecture
Relay is composed by many packages. Understanding each package, can help you understand how Relay works.

### Relay Compiler

Relay Compiler will read all GraphQL operations (queries, mutations, subscriptions), and fragments. It will parse, transform and optimize.

You can play with some Relay Compiler transforms here [Relay Compiler Repl](https://relay-compiler-repl.netlify.app/).

There is also a new [Relay Compiler Explorer](https://relay.dev/compiler-explorer)

Relay Compiler also polyfill GraphQL fragments to enable variables at fragment level, as GraphQL still do not support variables at fragment level yet.

Relay Compiler also ensure everything is correct, you won't be able to send a broke query to production, it won't even compile.

The output of this optimization uses AST, and it is stored on `__generated__` folders. You can explore GraphQL AST using [AST Explorer](https://astexplorer.net/).

### babel-plugin-relay

Relay provides a babel plugin that replaces the `graphql` tag to require the artifact generated static query generated by Relay Compiler.

Here is an example of this transformation

```jsx
const user = useFragment(
    graphql`
      fragment App_user on User {
        app
      }
    `,
    props.user,
  );
```

Transforms into

```jsx
const user = useFragment(require('./__generated__/App_user.graphql.ts'),
    props.user,
  );
```

### Relay Test Utils

We use Relay Test Utils in our integration tests at frontend. It makes it pretty easy to mock Relay environment and any GraphQL query or field.

Below is an example of a mock resolver that tells relay test utils to mock every `User` to have a name `Woovi`. I don't need to mock the whole GraphQL operation, just the fields that make sense for my test case. It reduces a lot the number of fixtures.

```jsx
const mockResolver = {
   User: () => ({ name: 'Woovi'}),
};
```

### Relay Runtime

Relay Runtime is the core part of Relay. It handles how Relay will do the requests (network layer), it will says how Relay will store the data. It also handles mutations and subscriptions.

If you wanna port Relay to angular or vue, you just take the Relay Runtime and add your favorite framework on top of it.

### React Relay

It is the React bindings for Relay Runtime.
It evolved a lot since Relay Classic, to Relay Modern, and now Relay hooks with support to Suspense and render as you fetch.

Relay hooks provides the best DX. `useFragment` let you declare what data your components needs, and Relay will figure it out how to bring this data to that component, from the store? from the network? you don't need to care about it.

`useMutation` will execute GraphQL Mutations and will also ensure you don't double execute them, so you don't need to worry when an user clicks the form button twice or more.

## Partial Rendering

One of the Relay unique feature is to partial render your components based on existing data in your store.

```jsx
<>
  <PostTitle post={post} />
  <Suspense>
     <PostComments post={post} />
  </Suspense>
</>
```

Imagine that you already have `post.title` in your Relay store, but you don't have `post.comments`. 
Relay will be able to render `<PostTitle />` component, and it will suspend `<PostComments />` until it gets the post comments. This provides a faster first render experience, and better UX for our users.

## Relay at Backend

![relay-at-backend](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26jv86vfrs3zga6jrnv3.jpeg)

We also use Relay at Backend.

We use Relay Compiler to compile and generate types for queries/mutations/subscriptions of our tests in the backend. This workflow provides typesafe testing and a better DX and asserting resulting of GraphQL tests.

Here is some code showing how to use it:

```jsx
const graphql = (strings: TemplateStringsArray) => {
  if (strings?.schema) {
    throw new Error('use graphqlExecute');
  }

  return strings[0];
};

export const graphqlExecute = async <T extends OperationType>(
  args: GraphQLArgs<T['variables']>,
) => {
  const result = await graphql(args);

  return result as unknown as ExecutionResult<T['response']>;
};

const source = graphql`
  query AppQuery($id: ID) {
    user: node(id: $id) {
      ... on User {
        name
     }
   }
  } 
`;

const result = await graphqlExecute<AppQuery>({
    schema,
    source,
    rootValue,
    contextValue,
    variableValues,
  });
```

`AppQuery` type is generated by Relay Compiler, and `result` has the correct type of it, if you change the query, it will change the `result` type. It is a great DX.

## More Relay at Woovi

We are using more and more Relay at Woovi. Relay let us decouple our components. It lets us easily refactor without breaking anything. Relay Compiler in rust is faster than ever.

## In Conclusion
My first contribution to Relay was December 15th, 2015, check it here [https://github.com/facebookarchive/relay-starter-kit/commits?author=sibelius](https://github.com/facebookarchive/relay-starter-kit/commits?author=sibelius).

Since there, GraphQL and Relay evolved a lot. Relay has a step learning curve, because it requires you to do the right thing, not the easiest thing. Relay requires a new mental model of how to deal with data in components.

We are going to keep using more Relay at Woovi to help us scale.

## Relay Workshop

If you want to learn Relay, the best resource is [Relay Workshop](https://github.com/sibelius/relay-workshop). It has 12 practical exercises to learn the most used Relay features.

---
Woovi
[Woovi](https://www.woovi.com) is a Startup that enables shoppers to pay as they like. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.

If you want to work with us, we are [hiring](https://woovi.com/jobs/)!