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

chore(blog): add schema customization blog post release #12522

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 45 additions & 17 deletions docs/blog/2019-03-18-releasing-new-schema-customization/index.md
@@ -1,17 +1,31 @@
---
title: Gatsby 2.2.0 Released - new schema customization API
title: New Schema Customization API - Available in Gatsby 2.2.0
date: 2019-03-18
author: Mikhail Novikov
tags: ["schema", "graphql"]
tags:
- schema
- graphql
---

Two weeks ago, we talked about [new schema customization API](../2019-03-04-new-schema-customization). Today we are releasing it as a part of our 2.2.0 release.
Two weeks ago, we announced our plans for a [new schema customization API](/blog/2019-03-04-new-schema-customization/). Today we are making this set of new APIs and enhancements available to all in `gatsby`@`2.2.0`.

First, install the latest and greatest version of `gatsby`, like so:

```shell
npm install gatsby --save
```

Next, continue reading below to see if any of the great, new features we've enabled scratch a particular itch. We feel very confident you're going to love these new features 💜
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe:

Suggested change
Next, continue reading below to see if any of the great, new features we've enabled scratch a particular itch. We feel very confident you're going to love these new features 💜
Next, continue reading below to see if any of the great, new features we've enabled scratch a particular itch. We feel very confident they will 💜

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Very open to tweaks here :))


# Recap of schema customization

Before this change, Gatsby GraphQL schema was generated from the data that user has fed to Gatsby. While very convenient and easy to start, changes to the data could cause changes to the schema, which could cause breakage in unrelated locations. Those bugs were confusing and hard to debug. To alleviate this problem, we've added a schema customization API, that lets you customize and fix types in your Gatsby GraphQL schema.
Before this change, the Gatsby GraphQL schema was generated automatically from the data that the user added to Gatsby. While very convenient and easy to start, changes to the data could cause changes to the schema, which could cause breakage in unrelated locations. Those bugs were confusing and hard to debug. To alleviate this problem, we've added a schema customization API that lets you customize, fix, and enhance types in your Gatsby GraphQL schema.

There are two new APIs, `createTypes` and `createResolvers`. `createTypes` can be used to define or fix your Node types GraphQL representation.
There are two new APIs, `createTypes` and `createResolvers`.

## `createTypes`

`createTypes` can be used to define, fix, or extend a Node's GraphQL type representation. Think of it like an escape hatch to politely inform Gatsby of your data's shape.

```js:title=gatsby-node.js
exports.sourceNodes = ({ actions }) => {
Expand All @@ -26,9 +40,12 @@ exports.sourceNodes = ({ actions }) => {
}
```

After adding this to your gatsby-node, `AuthorJson` type will always have fields name and birthday, regardless of the data shape in it's source. The rest of the fields will still be inferred normally, allowing you to still enjoy the benefits of Gatsby schema inference.
After adding this to your [gatsby-node](/docs/gatsby-project-structure/#files) file, the `AuthorJson` type will always have fields name and birthday, regardless of the automatically inferred data shape. The rest of the fields will still be inferred normally, allowing you to enjoy the default benefits of Gatsby schema inference.

## `createResolvers`

`createResolvers` allows doing additional customization after all schema processing has been finished. Thus it can be used to add fields to any types, including root types like `Query` and types from third party schemas.

`createResolvers` allows doing additional customization after all schema processing has been finished. Thus it can be used to add fields to any types, including root types like `Query` and types from 3rd party schemas.

```js:title=gatsby-node.js
createResolvers({
Expand All @@ -46,13 +63,13 @@ createResolvers({
})
```

# Type builder API
## The Type Builder API

While `createTypes` accepts `graphql-js` types along with SDL string. We've added option to use `graphql-js` types so that user could create types with resolvers. However, `graphql-js` is pretty verbose and it's hard to refer to types that don't yet exist or don't exist in a current scope. Therefore, we decided to add another programmatic API, that combines brevity of SDL with flexibility of `graphql-js`.
While `createTypes` accepts `graphql-js` types along with a [Schema Definition Language (SDL)](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51) string, we've also added an option to use `graphql-js` types so that users could create types with resolvers. However, `graphql-js` is somewhat verbose and it can be hard to refer to types that don't yet exist or don't exist in a current scope. Therefore, we decided to add another programmatic AP that combines brevity of SDL with flexibility of `graphql-js`.

We can this API _Type Builder API_. One can access it under `schema` field of the arguments object passed to Gatbsy Node APIs.
We refer to this API as the _Type Builder API_. It is available in the `schema` field of the arguments object passed to [Gatsby Node APIs](/docs/node-apis/).

```js
```js:title=gatsby-node.js
exports.sourceNodes = ({ actions, schema }) => {
const { createTypes } = actions
createTypes([
Expand Down Expand Up @@ -85,17 +102,28 @@ exports.sourceNodes = ({ actions, schema }) => {
}
```

# Possible breaking changes
# Potential for Breaking Changes

We have tried to avoid any breaking changes in this refactor of the underlying GraphQL layer, testing it in notable Gatsby sites and ensuring all tests were passing. However, there are areas where we needed to introduce more stable naming, and in these instances it _could_ be possible that a breaking change was introduced if you were relying on this undocumented API.

Specifically, before this refactor Gatsby type names weren't stable. They could have names like `frontmatter_2` because of some quirks in our schema generation. Now the types names are **stable** and **defined**. For a `Node`, it's always a Pascal Camel Cased name of the `Node` type (for example, `AllMarkdownRemark`). For an inline object, it's the name of the node plus the name of the field, again Pascal Camel Cased. So `frontmatter_2` would be available as `MarkdownRemarkFrontmatter` now. If you've had fragments referring to some types by their old names, you may need to change it to new names, e.g.:

```diff
- fragment someFragment on frontmatter_2 {
+ fragment someFragment on MarkdownRemarkFrontmatter {
title
}
```

We have tried to avoid any breaking changes in this big refactoring and we replicated even the weird quirks of the previous system to make sure it stays compatible. However, there was some undefined behaviour that is now defined and it could cause breakage if you relied on that behaviour.
Another change relates to inference. Previously, ordering of the Nodes in your data source could affect which type Gatsby inferred. Now, we always consider all possible types, thus you might experience type conflicts for conflicting data sources. They can be solved by either fixing the data or defining a type using new schema customization APIs that we've exposed.

Previously, Gatsby type names weren't stable. They could have names like `frontmatter_2`, because of the quirk of our double schema generetion. Now the types names are stable and defined. For Nodes, it's always pascal camel cased name of the Node type. For inline object, it's name of the node plus the name of the field, again Pascal Camel Cased. So `frontmatter_2` would be called `MarkdownRemarkFrontmatter` now. If you've had fragments referring to some types by their old names, you would have to change it to new names.
# Wrap-up

Another change relates to inference. Before, ordering of the Nodes in your data source could affect which type Gatsby inferred. Now, we always consider all possible types, thus you might experience type conflicts for conflicting data sources. It can be solved by either fixing the data or defining a type using new schema customization API.
As next steps, we will work on adding more convenient tooling to "freeze" your schema type definitions, so that you can quickly start using this feature. We will also be working on improving API docs for this.

# Conclusion and further work
We strongly believe that these new APIs are the foundation of an evolutionary leap of the Gatsby GraphQL API. These changes make the GraphQL API more stable, more robust, and more easily customizable. They will enable further customization and use cases, like [theming][/blog/2018-11-11-introducing-gatsby-themes/] and more still that we haven't even envisioned yet. We truly can't wait to see the great things you build and how you use these new APIs and improvements powered by Gatsby and its improved GraphQL layer.

As next steps, we will work on adding more convenient tooling to "freeze" your schema type defininions, so that you could quickly start using this feature. We will also be working on improving API docs for this. Here are some useful links:
## Additional Resources

- [Meta issue](https://github.com/gatsbyjs/gatsby/issues/12272) for bug reports
- [API docs for createTypes](/docs/actions/#createTypes)
Expand Down