Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions examples/app-dir-experiments/app/ApolloClient.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
import { ApolloClient, InMemoryCache } from "@apollo/client";
import { SchemaLink } from "@apollo/client/link/schema";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
import { schema } from "./api/graphql/route";

export const { getClient } = registerApolloClient(() => {
return new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: "http://localhost:3000/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" },
}),
link: new SchemaLink({ schema }),
});
});
9 changes: 7 additions & 2 deletions examples/app-dir-experiments/app/api/graphql/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { startServerAndCreateNextHandler } from "@as-integrations/next";
import { ApolloServer } from "@apollo/server";
import { makeExecutableSchema } from "@graphql-tools/schema";
import { gql } from "graphql-tag";

const typeDefs = gql`
Expand Down Expand Up @@ -37,9 +38,13 @@ const resolvers = {
},
};

const server = new ApolloServer({
resolvers,
export const schema = makeExecutableSchema({
typeDefs,
resolvers,
});

const server = new ApolloServer({
schema,
});

const handler = startServerAndCreateNextHandler(server);
Expand Down
16 changes: 9 additions & 7 deletions examples/app-dir-experiments/app/ssr/ApolloWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,18 @@ import {
HttpLink,
SuspenseCache,
} from "@apollo/client";
import { SchemaLink } from "@apollo/client/link/schema";
import {
ApolloNextAppProvider,
NextSSRInMemoryCache,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { setVerbosity } from "ts-invariant";
import { schema } from "../api/graphql/route";

Choose a reason for hiding this comment

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

I'm wondering about how importing schema here could expose credentials, schema with resolvers would need access to the DB driver, which in turn would need some credentials, we have a check for isServer so SchemaLink is only used in the server side, but the schema is imported for both, meaning the bundle might end up with the driver setup in the client, and depending on how it's bundled it would have the credentials embedded somewhere, do you think I'm making a correct assumption here?

Copy link
Member Author

Choose a reason for hiding this comment

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

From my experiences with the Nextjs bundler, I would assume that the typeof window !== "undefined" check would remove SchemaLink as well as schema from the client bundle shipped to the browser, but I'd be grateful if you could validate that further :)

Choose a reason for hiding this comment

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

Can't validate, my setup uses Neo4j GraphQL schema, which is generated async, creating the wrapper with the schema makes it harder since the makeClient function would need to be async, and Next.js complains about functional components that can't be async, sorry.

Copy link

@luchillo17 luchillo17 Feb 21, 2024

Choose a reason for hiding this comment

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

I am dumb, dunno why I didn't think about this before but to solve my issue of schema generator being async, I could just wrap makeClient into an async factory, declare <ApolloWrapper> component as async and inside the component, await the factory to get the makeClient function to pass it to ApolloNextAppProvider's makeClient prop in a synchronous way, can't believe it took me this long to think about this solution...


setVerbosity("debug");

function makeClient() {
const httpLink = new HttpLink({
uri: "http://localhost:3000/api/graphql",
fetchOptions: { cache: "no-store" },
});

return new ApolloClient({
cache: new NextSSRInMemoryCache(),
link:
Expand All @@ -29,9 +26,14 @@ function makeClient() {
new SSRMultipartLink({
stripDefer: true,
}),
httpLink,
new SchemaLink({
schema,

Choose a reason for hiding this comment

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

what if we need to create a context here with req to determine user's authentication state in graphql resolvers?

}),
])
: httpLink,
: new HttpLink({
uri: "http://localhost:3000/api/graphql",
fetchOptions: { cache: "no-store" },
}),
});
}

Expand Down