1

I have a backend with Nest + Graphql

  • and me resolver:
@Query(() => User)
@UseGuards(JwtAuthGuard)
me(@Context() { req }) {
  return this.usersService.findOne(req.user.id);
}
  • On the frontend, i use Nextjs, Apollo client and code-gen:
# codegen.yml

overwrite: true
schema: 'http://localhost:3030/graphql'
documents: 'src/graphql/**/*.gql'
generates:
  src/graphql/index.tsx:
    plugins:
      - 'typescript'
      - 'typescript-operations'
      - 'typescript-react-apollo'
    config:
      reactApolloVersion: 3
  • and with-next-apollo package
// utils/withApollo.ts

import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'
import { getCookie } from 'cookies-next'
import withApollo from 'next-with-apollo'

export default withApollo(
  ({ initialState, ctx }) => {
    const token = getCookie('token', ctx)
    return new ApolloClient({
      uri: 'http://localhost:3030/graphql',
      cache: new InMemoryCache().restore(initialState || {}),
      credentials: 'include',
      headers: {
        authorization: token ? `Bearer ${token}` : '',
      },
    })
  },
  {
    render: ({ Page, props }) => {
      return (
        <ApolloProvider client={props.apollo}>
          <Page {...props} />
        </ApolloProvider>
      )
    },
  }
)


  • and using it like this:
import { useMeQuery } from '@/graphql/_generated'
import withApollo from '@/utils/withApollo'
import { getDataFromTree } from '@apollo/client/react/ssr'

const Home = () => {
  const { loading, error } = useMeQuery()
  ...
}
export default withApollo(Home, { getDataFromTree }) // server side
// export default withApollo(Home) // client side

SO even though i specified a page as ssr, my graphql resolvers that are protected with jwt(@Query(() => User)) on the backend are not calling on ssr, it's calling on the client only, i clearly see in the network tab.

If i call multiple resolvers in one ssr page, jwt protected ones calling on the client, others are on the server(as expected)

// they all expected to run on the server, bcs page is ssr

// jwt protected(only calling on the client)
const {} = useMeQuery()
const {} = useUserDetailsQuery()
// not protected(working fine)
const {} = useProductsQuery()
const {} = useBlogsQuery()

export default withApollo(ThisPage, { getDataFromTree }) // ssr
A.Anvarbekov
  • 955
  • 1
  • 7
  • 21

1 Answers1

0

I'm not sure if that that's exactly the case, but it worth checking. For every application Apollo usually creates a new instance of ApolloClient. And in some cases during SSR (usually because of wrong configuration), an ApolloClient created on a server side stays the same for all requests. I.e. in contrast to new application per every framework-in-a-browser, server is considered one application, hence needs only one instance of ApolloClient. And as soon as the default caching options force the client to return the same data for the same queries if they are cached, it sometimes leads to resolver not being called. To check if that's the case, you could try to completely disable caching and see if something changed.

return new ApolloClient({
  uri: 'http://localhost:3030/graphql',
  cache: new InMemoryCache().restore(initialState || {}),
  credentials: 'include',
  headers: {
    authorization: token ? `Bearer ${token}` : '',
  },
  defaultOptions: { // <-- Add these options.
   query: {
     errorPolicy: 'all',
     fetchPolicy: 'no-cache'
   }
 }
})

If it turns out to be the root of a problem, then the logic of creation ApolloClient should be changed the way your app creates new instance of ApolloClient for every request made.

Igor Nikiforov
  • 611
  • 1
  • 7
  • 17