From 5df8aee44445e631e7acebad8e5885140db5c332 Mon Sep 17 00:00:00 2001 From: Ernie Turner Date: Mon, 10 Apr 2023 16:59:44 -0700 Subject: [PATCH] Add blog post highlighting changes in Relay 15 (#4258) Summary: Try to highlight the biggest improvements in the latest releases. Some of these sections need more work and details and I also left an empty section at the end in case we want to highlight any upcoming changes to folks. Also open to reorganizing these highlights in any way we think is worthwhile, I might not have the most unbiased view of order of importance of these. cc davidmccabe captbaritone Pull Request resolved: https://github.com/facebook/relay/pull/4258 Reviewed By: captbaritone Differential Revision: D44848864 Pulled By: davidmccabe fbshipit-source-id: 03f8157a9e1829faf27657f3b9bef7b8f6a45c92 --- website/blog/2023-03-30-relay-15.mdx | 135 +++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 website/blog/2023-03-30-relay-15.mdx diff --git a/website/blog/2023-03-30-relay-15.mdx b/website/blog/2023-03-30-relay-15.mdx new file mode 100644 index 0000000000000..4f5c3d4891df3 --- /dev/null +++ b/website/blog/2023-03-30-relay-15.mdx @@ -0,0 +1,135 @@ +--- +title: Relay v15.0 +author: The Relay Team +hide_table_of_contents: false +--- + +The Relay team is happy to announce the release of Relay v15. While this release is a major version bump and includes a couple of breaking changes, we expect that most users will be unaffected and will experience a seamless upgrade. You can find the full list of changes in the [v15 Release Notes](https://github.com/facebook/relay/releases/tag/v15.0.0). + +## What's new in Relay 15? + +### Support for `@refetchable` on interfaces + +Previously it wasn't possible to add the `@refetchable` directive on fragment definitions on server interface types. + +``` +// schema.graphql + +interface RefetchableInterfaceFoo @fetchable(field_name: "id") { + id: ID! +} + +extend type Query { + fetch__RefetchableInterfaceFoo(id: ID!): RefetchableInterfaceFoo +} + +// fragment + +fragment RefetchableFragmentFoo on RefetchableInterfaceFoo + @refetchable(queryName: "RefetchableFragmentFooQuery") { + id +} +``` + +### Persisted query improvements + +If you use URL-based persisted queries, you can now specify custom headers to send with the request that persists the query. For example, this can be used to send auth headers to your query persistence URL endpoint. + +```js +persistConfig: { + url: 'example.com/persist', + headers: { + Authorization: 'bearer TOKEN' + } +} +``` + +For file-based persisted queries, we added a new feature flag, `compact_query_text`, that removes all whitespace from the persisted query text. This can make the file more than 60% smaller. This new feature flag can be enabled within your Relay config file. + +```js +persistConfig: { + file: 'path/to/file.json', + algorithm: 'SHA256' +}, +featureFlags: { + compact_query_text: true +} +``` + +### Typesafe updates now support missing field handlers + +Typesafe updaters now support missing field handlers. Previously, if you selected `node(id: 4) { ... on User { name, __typename } }` in a typesafe updater, but that user was fetched in a different way (e.g. with `best_friend { name }`), you would not be able to access and mutate that user using the typesafe updater. + +In this release, we add support for missing field handlers in typesafe updaters, meaning that if a missing field handler is set up for node (as in [this example](https://relay.dev/docs/next/guided-tour/reusing-cached-data/filling-in-missing-data/#internaldocs-banner)), you will be able to update the user's name with this missing field handler. + +In order to support this, the signature of [missing field handlers](https://relay.dev/docs/guided-tour/reusing-cached-data/filling-in-missing-data) has been changed. The `record` argument to the handler used to recieve a `Record` type (which is an untyped grab-bag of data). It now receives a `ReadOnlyRecordProxy`. Furthermore, the field argument of type `NormalizationLinkedField` is now `CommonLinkedField`, which is a type containing the properties found in both `ReaderLinkedField` and `NormalizationLinkedField`. + +### Flow type improvements + +Flow users will now get types inferred from `graphql` literals with more Relay APIs. No longer do Flow users need to explicitly type the return value of the `usePreloadedQuery`, `useQueryLoader`, `useRefetchableFragment`, `usePaginationFragment`, and `useBlockingPaginationFragment` API methods. + +### Relay Resolver improvements + +A significant portion of our development effort since our last release has gone into improving [Relay Resolvers](https://relay.dev/docs/guides/relay-resolvers) (a mechanism for exposing derived data in the graph). It is worth noting that Relay Resolvers are still experimental and API changes might occur in the future. + +#### Terser docblock tags + +The annotation for Relay Resolver functions has been simplified. In many scenarios you can now use the `ParentType.field_name: ReturnType` syntax to define what new field your Relay Resolver exposes. + +Before: + +```js +/** + * @RelayResolver + * @onType User + * @fieldName favorite_page + * @rootFragment myRootFragment + */ +``` + +After: + +```js +/** + * @RelayResolver User.favorite_page: Page + * @rootFragment myRootFragment + */ +``` + +In the above example, the `Page` type is a schema type. If your Relay Resolver doesn't return a schema type, you can use fixed `RelayResolverValue` value as your return type + +```js +/** + * @RelayResolver User.best_friend: RelayResolverValue + * @rootFragment myRootFragment + */ +``` + +#### Define multiple resolvers per file + +Prior to this release we only allowed a single Relay Resolver per file and required the Relay Resolver function to be the default export. In Relay 15 you're now able to define multiple Relay Resolvers per file and use named exports. + +```js +/** + * @RelayResolver User.favorite_page: Page + * @rootFragment favoritePageFragment + */ +function usersFavoritePage(){ + ... +} + +/** + * @RelayResolver User.best_friend: RelayResolverValue + * @rootFragment bestFriendFragment + */ +function usersBestFriend(){ + ... +} + +module.exports = { + usersFavoritePage, + usersBestFriend +} +``` + +Happy Querying!