• Stars
    star
    446
  • Rank 97,888 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 1 year ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Apollo Client support for the Next.js App Router
Apollo Client + Next.js App Router

Apollo Client support for the Next.js App Router

❗️ This package is experimental. Generally it should work well, you might run into race conditions when your Client Component is still rendering in SSR, and already making overlapping queries on the browser.
This cannot be addressed from our side, but would need API changes in Next.js or React itself.
If you do not use suspense in your application, this will not be a problem to you.

Detailed technical breakdown

You can find a detailed technical breakdown of what this package does and why it needs to do so in the discussion around the accompanying RFC.

Why do you need this?

React Server Components

If you want to use Apollo Client in your Next.js app with React Server Components, you will need a way of creating a client instance that is shared between all your server components for one request to prevent making duplicate requests.

React Client Components

When using the app directory, all your "client components" will not only run in the browser. They will also be rendered on the server - in an "SSR" run that will execute after React Server Components have been rendered.

If you want to make the most of your application, you probably already want to make your GraphQL requests on the server so that the page is fully rendered when it reaches the browser.

This package provides the tools necessary to execute your GraphQL queries on the server and to use the results to hydrate your browser-side cache and components.

Installation

This package has a peer dependency on the latest rc of @apollo/client, so you can install both this package and that Apollo Client version via

npm install @apollo/client@latest @apollo/experimental-nextjs-app-support

Usage

❗️ We do handle "RSC" and "SSR" use cases as completely separate.
You should generally try not to have overlapping queries between the two, as all queries made in SSR can dynamically update in the browser as the cache updates (e.g. from a mutation or another query), but queries made in RSC will not be updated in the browser - for that purpose, the full page would need to rerender. As a result, any overlapping data would result in inconsistencies in your UI.
So decide for yourself, which queries you want to make in RSC and which in SSR, and don't have them overlap.

In RSC

Create an ApolloClient.js file:

import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";

export const { getClient } = registerApolloClient(() => {
  return new ApolloClient({
    cache: new InMemoryCache(),
    link: new HttpLink({
      // this needs to be an absolute url, as relative urls cannot be used in SSR
      uri: "http://example.com/api/graphql",
      // you can disable result caching here if you want to
      // (this does not work if you are rendering your page with `export const dynamic = "force-static"`)
      // fetchOptions: { cache: "no-store" },
    }),
  });
});

You can then use that getClient function in your server components:

const { data } = await getClient().query({ query: userQuery });

In SSR

If you use the app directory, each Client Component will be SSR-rendered for the initial request. So you will need to use this package.

First, create a new file app/ApolloWrapper.jsx:

"use client";
// ^ this file needs the "use client" pragma

import { ApolloLink, HttpLink } from "@apollo/client";
import {
  ApolloNextAppProvider,
  NextSSRInMemoryCache,
  NextSSRApolloClient,
  SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";

// have a function to create a client for you
function makeClient() {
  const httpLink = new HttpLink({
    // this needs to be an absolute url, as relative urls cannot be used in SSR
    uri: "https://example.com/api/graphql",
    // you can disable result caching here if you want to
    // (this does not work if you are rendering your page with `export const dynamic = "force-static"`)
    fetchOptions: { cache: "no-store" },
    // you can override the default `fetchOptions` on a per query basis
    // via the `context` property on the options passed as a second argument
    // to an Apollo Client data fetching hook, e.g.:
    // const { data } = useSuspenseQuery(MY_QUERY, { context: { fetchOptions: { cache: "force-cache" }}});
  });

  return new NextSSRApolloClient({
    // use the `NextSSRInMemoryCache`, not the normal `InMemoryCache`
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === "undefined"
        ? ApolloLink.from([
            // in a SSR environment, if you use multipart features like
            // @defer, you need to decide how to handle these.
            // This strips all interfaces with a `@defer` directive from your queries.
            new SSRMultipartLink({
              stripDefer: true,
            }),
            httpLink,
          ])
        : httpLink,
  });
}

// you need to create a component to wrap your app in
export function ApolloWrapper({ children }: React.PropsWithChildren) {
  return (
    <ApolloNextAppProvider makeClient={makeClient}>
      {children}
    </ApolloNextAppProvider>
  );
}

Now you can wrap your RootLayout in this wrapper component:

import { ApolloWrapper } from "./ApolloWrapper";

// ...

export default function RootLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return (
    <html lang="en">
      <body>
        <ApolloWrapper>{children}</ApolloWrapper>
      </body>
    </html>
  );
}

☝️ This will work even if your layout is a React Server Component and will also allow the children of the layout to be React Server Components.
It just makes sure that all Client Components will have access to the same Apollo Client instance, shared through the ApolloNextAppProvider.

You can import the following Apollo Client hooks from "@apollo/experimental-nextjs-app-support/ssr" in your client components (make sure you are not importing these hooks from @apollo/client as this package wraps and re-exports them to support streaming SSR):

  • useQuery
  • useSuspenseQuery
  • useBackgroundQuery
  • useReadQuery
  • useFragment

If you want to make the most of the streaming SSR features offered by React & the Next.js App Router, consider using the useSuspenseQuery and useFragment hooks.

Resetting singletons between tests.

This package uses some singleton instances on the Browser side - if you are writing tests, you must reset them between tests.

For that, you can use the resetNextSSRApolloSingletons helper:

import { resetNextSSRApolloSingletons } from "@apollo/experimental-nextjs-app-support/ssr";

afterEach(resetNextSSRApolloSingletons);

Handling Multipart responses in SSR

Generally, useSuspenseQuery will only suspend until the initial response is received. In most cases, you get a full response, but if you use multipart response features like the @defer directive, you will only get a partial response.
Without further handling, your component will now render with partial data - but the request will still keep running in the background. This is a worst-case scenario because your server will have to bear the load of that request, but the client will not get the complete data anyways. To handle this, you can apply one of two different strategies:

  • remove @defer fragments from your query
  • wait for deferred data to be received

For this, we ship the two links RemoveMultipartDirectivesLink and AccumulateMultipartResponsesLink, as well as the SSRMultipartLink, which combines both of them into a more convenient-to-use Link.

You can also check out the Hack The Supergraph example, which shows this in use and allows you to adjust the speed deferred interfaces resolve in.

Removing @defer fragments from your query with RemoveMultipartDirectivesLink

Usage example:

new RemoveMultipartDirectivesLink({
  /**
   * Whether to strip fragments with `@defer` directives
   * from queries before sending them to the server.
   *
   * Defaults to `true`.
   *
   * Can be overwritten by adding a label starting
   * with either `"SsrDontStrip"` or `"SsrStrip"` to the
   * directive.
   */
  stripDefer: true,
});

This link will (if called with stripDefer: true) strip all @defer fragments from your query.

You can exclude certain fragments from this behavior by giving them a label starting with "SsrDontStrip".

Example:

query myQuery {
  fastField
  ... @defer(label: "SsrDontStrip1") {
    slowField1
  }
  ... @defer(label: "SsrDontStrip2") {
    slowField2
  }
}

You can also use the link with stripDefer: false and mark certain fragments to be stripped by giving them a label starting with "SsrStrip".

Waiting for deferred data to be received with AccumulateMultipartResponsesLink

Usage example:

new AccumulateMultipartResponsesLink({
  /**
   * The maximum delay in milliseconds
   * from receiving the first response
   * until the accumulated data will be flushed
   * and the connection will be closed.
   */
  cutoffDelay: 100,
});

This link can be used to "debounce" the initial response of a multipart request. Any incremental data received during the cutoffDelay time will be merged into the initial response.

After cutoffDelay, the link will return the initial response, even if there is still incremental data pending, and close the network connection.

If cutoffDelay is 0, the link will immediately return data as soon as it is received, without waiting for incremental data, and immediately close the network connection.

Combining both: SSRMultipartLink

Usage example:

new SSRMultipartLink({
  /**
   * Whether to strip fragments with `@defer` directives
   * from queries before sending them to the server.
   *
   * Defaults to `true`.
   *
   * Can be overwritten by adding a label starting
   * with either `"SsrDontStrip"` or `"SsrStrip"` to the
   * directive.
   */
  stripDefer: true,
  /**
   * The maximum delay in milliseconds
   * from receiving the first response
   * until the accumulated data will be flushed
   * and the connection will be closed.
   *
   * Defaults to `0`.
   */
  cutoffDelay: 100,
});

This link combines the behavior of RemoveMultipartDirectivesLink and AccumulateMultipartResponsesLink into a single link.

Debugging

If you want more information on what data is sent over the wire, enable logging in your app/ApolloWrapper.ts:

import { setVerbosity } from "ts-invariant";
setVerbosity("debug");

More Repositories

1

apollo-client

🚀  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
TypeScript
19,300
star
2

apollo-server

🌍  Spec-compliant and production ready JavaScript GraphQL server that lets you develop in a schema-first way. Built for Express, Connect, Hapi, Koa, and more.
TypeScript
13,522
star
3

react-apollo

♻️ React integration for Apollo Client
JavaScript
6,887
star
4

apollo-ios

📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.
Swift
3,737
star
5

apollo-kotlin

🤖  A strongly-typed, caching GraphQL client for the JVM, Android, and Kotlin multiplatform.
Kotlin
3,382
star
6

apollo-tooling

✏️ Apollo CLI for client tooling (Mostly replaced by Rover)
TypeScript
3,042
star
7

apollo

🚀 Open source tools for GraphQL. Central repo for discussion.
JavaScript
2,626
star
8

graphql-tag

A JavaScript template literal tag that parses GraphQL queries
TypeScript
2,275
star
9

graphql-subscriptions

📰 A small module that implements GraphQL subscriptions for Node.js
TypeScript
1,567
star
10

subscriptions-transport-ws

🔃 A WebSocket client + server for GraphQL subscriptions
TypeScript
1,524
star
11

apollo-client-devtools

Apollo Client browser developer tools.
TypeScript
1,481
star
12

apollo-link

🔗 Interface for fetching and modifying control flow of GraphQL requests
TypeScript
1,438
star
13

apollo-link-state

✨ Manage your application's state with Apollo!
TypeScript
1,405
star
14

apollo-cache-persist

🎏 Simple persistence for all Apollo Cache implementations
TypeScript
1,368
star
15

fullstack-tutorial

🚀 The Apollo platform tutorial app
TypeScript
1,233
star
16

eslint-plugin-graphql

🚦 Check your GraphQL query strings against a schema.
JavaScript
1,194
star
17

router

A configurable, high-performance routing runtime for Apollo Federation 🚀
Rust
793
star
18

apollo-link-rest

Use existing REST endpoints with GraphQL
TypeScript
783
star
19

federation

🌐  Build and scale a single data graph across multiple services with Apollo's federation gateway.
TypeScript
659
star
20

apollo-fetch

🐶 Lightweight GraphQL client that supports middleware and afterware
TypeScript
576
star
21

apollo-rs

Spec compliant GraphQL Tools in Rust.
Rust
566
star
22

reason-apollo

Reason binding for Apollo Client and React Apollo
Reason
552
star
23

federation-demo

Federation 2 supersedes this demo and this example is no longer the newest. See https://www.apollographql.com/docs/federation/ for migration steps!
JavaScript
502
star
24

ac3-state-management-examples

✨ Learn Apollo Client 3's state management best practices
TypeScript
493
star
25

apollo-tracing

A GraphQL extension for performance tracing
475
star
26

persistgraphql

A build tool for GraphQL projects.
TypeScript
424
star
27

rover

The CLI for Apollo GraphOS
Rust
404
star
28

gatsby-theme-apollo

💜 Themes that we use to build Gatsby sites at Apollo
JavaScript
371
star
29

apollo-link-persisted-queries

Persisted Query support with Apollo Link
TypeScript
307
star
30

xcode-graphql

🛠 Xcode add-ons that add syntax highlighting for GraphQL query document files
Shell
276
star
31

apollo-studio-community

🎡  GraphQL developer portal featuring an IDE (Apollo Explorer), auto-documentation, metrics reporting, and more. This repo is for issues, feature requests, and preview docs. 📬
249
star
32

federation-jvm

JVM support for Apollo Federation
Java
247
star
33

supergraph-demo-fed2

🍿 Supergraph demo for Federation 2 and Apollo Router
Shell
162
star
34

principled-graphql

📈 Best practices for implementing and scaling a data graph
JavaScript
148
star
35

apollo-cache-control

A GraphQL extension for cache control
146
star
36

supergraph-demo

🍿 Compose subgraphs into a Federation v1 supergraph at build-time with static composition to power a federated graph router at runtime.
Shell
135
star
37

apollo-feature-requests

🧑‍🚀 Apollo Client Feature Requests | (no 🐛 please).
130
star
38

spotify-showcase

A Spotify clone that showcases the Apollo GraphQL platform.
TypeScript
126
star
39

meteor-integration

🚀 meteor add apollo
JavaScript
108
star
40

frontpage-ios-app

📄 Apollo "hello world" app, for iOS
Swift
101
star
41

space-kit

👩‍🚀 Home base for Apollo's design system: https://space-kit.netlify.com
TypeScript
88
star
42

apollo-scalajs

Use Apollo GraphQL from Scala.js apps!
Scala
88
star
43

invariant-packages

Packages for working with invariant(condition, message) assertions
TypeScript
88
star
44

apollo-federation-subgraph-compatibility

A repo to test subgraph libraries compatibility with the Apollo Federation Specification
TypeScript
77
star
45

starwars-server

JavaScript
73
star
46

blog

📝 Blog website built with Wordpress and Gatsby
JavaScript
68
star
47

iOSTutorial

The tutorial application for the Apollo iOS SDK
Swift
68
star
48

odyssey-lift-off-part1

JavaScript
64
star
49

federation-jvm-spring-example

Apollo Federation JVM example implementation using Spring for GraphQL
Java
64
star
50

vscode-graphql

Apollo GraphQL VS Code extension
TypeScript
55
star
51

apollo-kotlin-tutorial

The code for the Apollo Kotlin Tutorial
Kotlin
52
star
52

docs-examples

Example code supporting the Apollo docs
TypeScript
50
star
53

docs

📚 Apollo's docs framework
MDX
42
star
54

apollo-kotlin-2-tutorial

The code for the Apollo Android Tutorial
Kotlin
38
star
55

iOSCodegenTemplate

A template for the code you need to set up to get Swift Scripting up and running.
Swift
38
star
56

datasource-rest

A caching data source for REST APIs
TypeScript
37
star
57

apollo-workbench-vscode

Apollo Workbench is a design tool that facilitates planning changes to your supergraph. It enables you to understand the overall composition and execution of any given query at design time.
TypeScript
37
star
58

apollo-utils

Monorepo of common utilities related to Apollo and GraphQL
TypeScript
35
star
59

graphql-testing-library

Testing utilities that encourage good practices for apps built with GraphQL.
TypeScript
35
star
60

federation-rs

Contains source code for Apollo Federation's Rust<--> JavaScript interop
Rust
34
star
61

react-apollo-error-template

Apollo Client issue reproduction.
JavaScript
33
star
62

embeddable-explorer

TypeScript
32
star
63

federation-migration-example

🚀Example app migrated from schema stitching to Apollo federation
JavaScript
32
star
64

odyssey-lift-off-part5-server

Odyssey Lift-off V - Server - Course Companion App
JavaScript
31
star
65

odyssey-lift-off-part5-client

Odyssey Lift-off V - Client - Course Companion App
JavaScript
28
star
66

GraphiQL-Subscriptions-Fetcher

GraphiQL's fetcher that supports GraphQL-Subscriptions with the `subscriptions-transport-ws` package
TypeScript
28
star
67

supergraph-demo-k8s-graph-ops

Archived: GitOps config repo for an Apollo GraphQL federated graph with a supergraph router and subgraph services deployed to Kubernetes.
Shell
28
star
68

apollo-ios-dev

Apollo iOS Development Repo
Swift
28
star
69

apollo-ios-pagination

Swift
26
star
70

odyssey-lift-off-part2

Odyssey Lift-off Part 2 Course Companion App
JavaScript
26
star
71

spacex

A re-creation of https://github.com/SpaceXLand/api
TypeScript
21
star
72

apollo-graphql-stream-scenes

This is used for hosting streaming scenes for OBS - for Apollo GraphQL stream
JavaScript
19
star
73

federation-next

Moved to the Router repository
Rust
19
star
74

subgraph-template-typescript-apollo-server-boilerplate

A template for a minimal setup Apollo Server 4.x using TypeScript
TypeScript
17
star
75

federation-hotchocolate

HotChocolate support for Apollo Federation
C#
16
star
76

odyssey-lift-off-part3

Odyssey Lift-off Part 3 Course Companion App
JavaScript
15
star
77

odyssey-voyage-I

JavaScript
14
star
78

typescript-repo-template

A template for TypeScript projects with pre-configured tooling
TypeScript
14
star
79

subgraph-template-typescript-apollo-server

A Typescript template for Apollo Server as a subgraph using Apollo Federation
TypeScript
13
star
80

next-apollo-example

Template for creating Apollo Client + Next.js reproductions
JavaScript
13
star
81

community

Apollo community guidelines
JavaScript
13
star
82

design-principles

Where we are defining and collaborating on our Apollo internal design principles (individually and collaboratively). This is a public repo, but intended only for use by Apollo employees.
13
star
83

odyssey-lift-off-part4

Odyssey Lift-off Part 4 Course Companion App
JavaScript
12
star
84

core-schema-js

Typescript library for processing core schemas
TypeScript
12
star
85

apollo-client-swift-playground

Swift
11
star
86

apollo-ios-codegen

Apollo iOS Code Generation
Swift
11
star
87

test-span

Rust
11
star
88

specs

Apollo Library of Technical Specifications
CSS
10
star
89

router-template

A general purpose self-hosted Apollo Router template connected to GraphOS
Dockerfile
10
star
90

apollo-midnight

A VS Code color theme based on Apollo Studio Explorer color palette.
9
star
91

serde_json_bytes

a JSON Value object with strings backed by Bytes, parsed by serde_json
Rust
8
star
92

hack-the-supergraph

JavaScript
8
star
93

subgraph-template-rust-async-graphql

A boilerplate template project for building a subgraph with async-graphql
Rust
8
star
94

router-biscuit-plugin

⚠️experimental⚠️ plugin for the router using Biscuit tokens for authorization
Rust
7
star
95

devhub

🔭 Explore all the latest resources for building apps with Apollo
JavaScript
7
star
96

client-router-e2e-tests

Apollo Client ↔️ Router E2E Test Suite
JavaScript
7
star
97

odyssey-lift-off-lab

Odyssey Lift-off Lab starter repo
JavaScript
7
star
98

graphchat

TypeScript
6
star
99

introspector-gadget

GraphQL introspection utilities
Rust
6
star
100

zen-observable-ts

Thin wrapper around zen-observable and @types/zen-observable, to support ESM exports
JavaScript
6
star