`NextSSRInMemoryCache` is not exported by `@apollo/experimental-nextjs-app-support/ssr`
In node_modules/.pnpm/@[email protected]_@[email protected][email protected][email protected]/node_modules/@apollo/experimental-nextjs-app-support/dist/ssr/index.ssr.js
import { useContext } from 'react';
import { buildManualDataTransport } from '@apollo/client-react-streaming/manual-transport';
export { resetManualSSRApolloSingletons as resetNextSSRApolloSingletons } from '@apollo/client-react-streaming/manual-transport';
import { WrapApolloProvider, ApolloClient } from '@apollo/client-react-streaming';
export { DebounceMultipartResponsesLink, InMemoryCache as NextSSRInMemoryCache, RemoveMultipartDirectivesLink, SSRMultipartLink } from '@apollo/client-react-streaming';
import { ServerInsertedHTMLContext } from 'next/navigation.js';
export { useBackgroundQuery, useFragment, useQuery, useReadQuery, useSuspenseQuery } from '@apollo/client/index.js';
// src/ApolloNextAppProvider.ts
// src/bundleInfo.ts
var bundle = {
pkg: "@apollo/experimental-nextjs-app-support/ssr",
client: "NextSSRApolloClient",
cache: "NextSSRInMemoryCache"
};
// src/ApolloNextAppProvider.ts
var ApolloNextAppProvider = /* @__PURE__ */ WrapApolloProvider(
buildManualDataTransport({
useInsertHtml() {
const insertHtml = useContext(ServerInsertedHTMLContext);
if (!insertHtml) {
throw new Error(
"ApolloNextAppProvider cannot be used outside of the Next App Router!"
);
}
return insertHtml;
}
})
);
ApolloNextAppProvider.info = bundle;
var NextSSRApolloClient = class extends ApolloClient {
/**
* Information about the current package and it's export names, for use in error messages.
*
* @internal
*/
static info = bundle;
};
export { ApolloNextAppProvider, NextSSRApolloClient };
//# sourceMappingURL=out.js.map
//# sourceMappingURL=index.ssr.js.map
NextSSRInMemoryCache is not exported.
I am using version 0.9.1
Actually I am upgrading from 0.8.0 to 0.9.1 it became broken
NextSSRApolloClient is also not usable.
Error: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f2e$pnpm$2f40$apollo$2b$experimental$2d$nextjs$2d$app$2d$support$40$0$2e$9$2e$1_$40$apollo$2b$client$40$3$2e$9$2e$10_next$40$14$2e$1$2e$4_react$40$18$2e$2$2e$0$2f$node_modules$2f40$apollo$2f$experimental$2d$nextjs$2d$app$2d$support$2f$dist$2f$ssr$2f$index$2e$rsc$2e$js__$5b$app$2d$rsc$5d$__$28$ecmascript$29$__$7b$exports$7d$__.NextSSRApolloClient is not a constructor
I tried to import
import * as test from '@apollo/experimental-nextjs-app-support/ssr'
and the result:
Object [Module] {
DebounceMultipartResponsesLink: [Getter],
RemoveMultipartDirectivesLink: [Getter],
SSRMultipartLink: [Getter]
}
Hmm, it seems like you're getting the RSC entry point (where those shouldn't be available and using them was always a bug).
Do you still get that error when you mark the file importing it as "use client"?
Are you maybe building for another runtime such as edge? We got reports about that and I'm looking into that soon (just came back from vacation)
Assuming you are using the edge runtime, I believe this will be solved by https://github.com/apollographql/apollo-client-nextjs/pull/263
Could you please give
npm i @apollo/[email protected]
a try?
The same issue occurs when importing registerApolloClient
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
just copy pasted the example from the github readme
export const { getClient } = registerApolloClient(() => { return new ApolloClient({ ... }) }
@Giusti you should be getting an error there if you are not importing registerApolloClient from a Server Component import tree - and that's intentional, as registerApolloClient can only safely be used in server components.
What environment are you using this in?
I found the issue is that in version 0.9.0
the usage is changed, some exports is moved to another new package.
To fix the issue, simply change the import from:
import {
NextSSRApolloClient,
NextSSRInMemoryCache,
SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
to:
import {
ApolloClient,
InMemoryCache,
SSRMultipartLink,
} from '@apollo/client-react-streaming'
I also created a PR #269 to update the documents
Closing this as I found the solution
@nodegin as I commented in the PR, that's not the intended way of using it.
You should continue to use "@apollo/experimental-nextjs-app-support/ssr" - as you can see in the code that you yourself quoted up there, all those exports are still present:
export { DebounceMultipartResponsesLink, InMemoryCache as NextSSRInMemoryCache, RemoveMultipartDirectivesLink, SSRMultipartLink } from '@apollo/client-react-streaming';
import { ApolloClient } from '@apollo/client-react-streaming';
var NextSSRApolloClient = class extends ApolloClient {
static info = bundle;
};
export { NextSSRApolloClient };
If you are still encountering issues with that usage, we'll need to investigate that.
Is there any chance you can provide us with a reproduction of your issue?
@phryneas I see, I think you can reproduce it by just installing 0.9.1 and navigate to @apollo/experimental-nextjs-app-support/dist/ssr/index.ssr.js, as I posted the exports are missing.
However changing to import from '@apollo/client-react-streaming' did fix for me, at least my app is running normally.
I guess the root cause could be some build config error casuing the re-export not working?
the exports are missing.
That might be just a TypeScript error there, what your IDE sees and what the bundler sees are two very different things.
Are you importing from @apollo/experimental-nextjs-app-support/dist/ssr/index.ssr.js directly, or from @apollo/experimental-nextjs-app-support/ssr?
Depending on if you are in a RSC, SSR or Browser context, that import points to completely different files.
I do have an inkling though - you might have imports that accidentally pull Client files into RSC, or RSC files into Client Components. Could you read through #268 and see if that is similar to your situation?
Especially thinking about your solution - @apollo/client-react-streaming exports ApolloClient in the RSC, SSR and Browser entry points, while @apollo/experimental-nextjs-app-support/ssr exports NextSSRInMemoryCache only in the SSR and Browser entrypoints (as in the past it was always considered a bug to use it from RSC).
I believe you have an import chain somewhere that pulls the file with your NextSSRInMemoryCache import into a RSC environment (and likewise, in @Giusti's case, an import chain that pulls the file with registerApolloClient into a Client Component environment).
@phryneas Hmm, I see that could be the reason.
I have a apps/web/lib/apollo/index.ts in my setup:
export * from './apolloClient'
export * from './apolloProvider'
But that is just for simplifying the import statement, is that a problem?
How about if I import from @apollo/client-react-streaming as NextSSR* is basically just re-exporting.
The behavior was working fine before v0.9.0
The behavior was working fine before v0.9.0
Yes, with 0.9.0 we aligned with how a React Server Component package should be packaged according to the React team. Their philosophy is "fail early on bundling, not late with a runtime error", which makes sense but doesn't give any good error messages :/
I'm honestly really sorry for these errors, but this is pretty much the experience it is meant to be :(
Your barrel exports here look very much like they could be the problem.
I'd highly recommend not to switch over to the @apollo/client-react-streaming package for this, but to fix your bug here - you are likely ending up with a much bigger bundle size because you are bundling things that are not meant to be bundled.
I did ask around for tools that might help with this on Twitter, and https://github.com/pahen/madge was suggested - maybe that helps you identify these imports faster.
Especially thinking about your solution -
@apollo/client-react-streamingexportsApolloClientin the RSC, SSR and Browser entry points, while@apollo/experimental-nextjs-app-support/ssrexportsNextSSRInMemoryCacheonly in the SSR and Browser entrypoints (as in the past it was always considered a bug to use it from RSC).I believe you have an import chain somewhere that pulls the file with your
NextSSRInMemoryCacheimport into a RSC environment (and likewise, in @Giusti's case, an import chain that pulls the file withregisterApolloClientinto a Client Component environment).
Hm, I've got to confess, my understanding of SSR and its ways in Next.js 13+ are still lacking. But I'm facing the same error, even with a really minimal setup: https://github.com/JonasDoe/debug-apollo-client. There isn't a "use client" directive, and yet npm run build will result in the warning:
> build
> next build
▲ Next.js 14.2.2
Creating an optimized production build ...
⚠ Compiled with warnings
./app/layout.tsx
Attempted import error: 'NextSSRInMemoryCache' is not exported from '@apollo/experimental-nextjs-app-support/ssr' (imported as 'NextSSRInMemoryCache').
Import trace for requested module:
./app/layout.tsx
...
This is not just a type error, since - in the real, deployed application -, calling it will result in an error when the @apollo/experimental-nextjs-app-support is greater version 0.8.0.
@JonasDoe NextSSRInMemoryCache is an import for SSR only, which means "use client" files - you cannot import it from RSC, which you are doing.
There are three things in Next.js
- RSC - React Server Components. You didn't ever use
"use client"in the import path to this file - SSR - React Client Components running in an SSR pass on the Server
- Browser - React Client Components running in the browser
So you'd use NextSSRInMemoryCache in Client Components (it needs to be used in SSR and Browser), but not in RSC.
There isn't a "use client" directive, and yet npm run build will result in the warning:
Exactly, your example is a React Server Component trying to import something that should only be used in SSR and Browser. In RSC, you'd just use ApolloClient from @apollo/client (as we show in our examples).
Using the wrong import was always a bug in your app, we just enforce it the way the React team intends it to be enforced (with missing imports) since 0.9.0.
@phryneas Phew, thanks for the detailed explanation! So if I understand correcly, RSC is the "purest" form of a component and has the highest restrictions. It is encapsulated and doesn't need to synchronize with the client. It can reside in app. When it's done, it passes its data as RSC Payload to the SSR (i.e. a component in app) and indirectly to the CSR. When it comes to GraphQL data loading in a RSC, I utilize rsc/registerApolloClient from the experimental package - together with @apollo/client/ApolloClient -, to share the GraphQL client and it's cache between all RSCs in a single request (happens automagically due to the registerApolloClient logic).
In the next step (SSR), in your example you've added "use client" at the top to ensure that it won't accidentally become a RSC, i.e. you can safely use NextSSRApolloClient or NextSSRInMemoryCache. Is that correct?
SSR and CSR will, in turn, utilize NextSSRApolloClient and the alike. What's the gain compared to the ordinary @apollo/client/ApolloClient? I think I've read the SSR clients come with automatic cache hydration at the client side, but I can't really find anything about it right now. In this explanatory blog entry the "full snippet" looks like this:
// lib/client.js
import { HttpLink } from "@apollo/client";
import {
NextSSRInMemoryCache,
NextSSRApolloClient,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
export const { getClient } = registerApolloClient(() => {
return new NextSSRApolloClient({
cache: new NextSSRInMemoryCache(),
link: new HttpLink({
uri: "https://main--time-pav6zq.apollographos.net/graphql",
}),
});
});
So for some reason, RSC and SSR come together again, and it differs from the repo's README in that regard. So I'm a bit confused here.
Also, if I understand correctly, the @apollo/client/ApolloClient is completely decoupled from the experimental SSR client's. No cache data is shared between them and - if I understand RSC vs client component correctly - is not intended either. Is that right?
Using the wrong import was always a bug in your app, we just enforce it the way the React team intends it to be enforced (with missing imports) since 0.9.0.
I don't doubt that, but I wasn't experiencing any faulty behavior prior to 0.9.0, that's why I am a bit suprised.
@phryneas Phew, thanks for the detailed explanation! So if I understand correcly, RSC is the "purest" form of a component and has the highest restrictions. It is encapsulated and doesn't need to synchronize with the client. It can reside in
app. When it's done, it passes its data asRSC Payloadto the SSR (i.e. a component inapp) and indirectly to the CSR. When it comes to GraphQL data loading in a RSC, I utilizersc/registerApolloClientfrom the experimental package - together with@apollo/client/ApolloClient-, to share the GraphQL client and it's cache between all RSCs in a single request (happens automagically due to theregisterApolloClientlogic).
That pretty much sums it up.
In the next step (SSR), in your example you've added
"use client"at the top to ensure that it won't accidentally become a RSC, i.e. you can safely useNextSSRApolloClientorNextSSRInMemoryCache. Is that correct?
Yup.
SSR and CSR will, in turn, utilize
NextSSRApolloClientand the alike. What's the gain compared to the ordinary@apollo/client/ApolloClient? I think I've read the SSR clients come with automatic cache hydration at the client side, but I can't really find anything about it right now. In this explanatory blog entry the "full snippet" looks like this:
If you use useSuspenseQuery or useBackgroundQuery, we transport the result over from SSR into the browser and ensure you won't encounter hydration errors.
If you use useQuery, we prevent requests from happening on the server (because SSR only renders once, so all you'd see there is a loading indicator, but your server would still make an unneccessary request).
You can get more context in this RFC or in this conference talk.
// lib/client.js import { HttpLink } from "@apollo/client"; import { NextSSRInMemoryCache, NextSSRApolloClient, } from "@apollo/experimental-nextjs-app-support/ssr"; import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc"; export const { getClient } = registerApolloClient(() => { return new NextSSRApolloClient({ cache: new NextSSRInMemoryCache(), link: new HttpLink({ uri: "https://main--time-pav6zq.apollographos.net/graphql", }), }); });So for some reason, RSC and SSR come together again, and it differs from the repo's
READMEin that regard. So I'm a bit confused here.
🤦 I know you won't believe it, but I already fixed this blog article twice. This just seems to come back. I fixed it again and contacted some people internally to find out why it keeps switching back.
Also, if I understand correctly, the
@apollo/client/ApolloClientis completely decoupled from the experimental SSR client's. No cache data is shared between them and - if I understand RSC vs client component correctly - is not intended either. Is that right?
Yes, quoting from the README:
❗️ 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.
We will soon have a way of "prefetching for SSR/Browser in RSC" though, see #258.
I don't doubt that, but I wasn't experiencing any faulty behavior prior to 0.9.0, that's why I am a bit suprised.
Yeah, it doesn't really "error", but your bundle size might have been increased significantly, at least we had reports of that.
Again, I'm sorry for all of that. We will make some adjustments in the next version where we move the /ssr and /rsc entrypoints both into / and rename NextSSR* to just the plain names InMemoryCache and ApolloClient. If you import them in RSC, it will give you the plain ones from @apollo/client and if you import them in SSR/Browser, you'll get the SSR implementation.
That will hopefully make this a lot better.
You can get more context in this RFC or in this conference talk
Wow, this the RFC is impressive and rather helpful for some more insights, thank you! (Btw. in "as React does not a mechanism of injecting data into the stream at arbitrary points in time" a verb is missing.)
If you use useQuery, we prevent requests from happening on the server (because SSR only renders once, so all you'd see there is a loading indicator, but your server would still make an unneccessary request).
So where's the place I'm supposed to fetch initial data that might change later? I'ld rather do some general fetches at server-side for a performance gain. The RSC does fetches at server side, but isn't really supposed to have overlapping queries with the SSR/CSR, as you quote. In the SSR stage, in turn, doing data fetches (via hooks, now) isn't supported and will be skipped. I would expect that the RSC should fetch this data, and I stringify and pass it to the SSR as initial cache. Is this what https://github.com/apollographql/apollo-client-nextjs/pull/258 is there for?
Again, I'm sorry for all of that.
I'm really grateful that you take your time to explain the framework to users! Not only here in comments, but also at so many other places, which is quite some uphill fighting.
So where's the place I'm supposed to fetch initial data that might change later? [...] Is this what https://github.com/apollographql/apollo-client-nextjs/pull/258 is there for?
Yup. That, or you just use useSuspenseQuery in a client component, which will fetch the data in SSR, not RSC - but only on the first request, not on further navigation. (That's what you'll be using RSC+PreloadQuery from #258 for)