Следующий js 14, как вызвать запрос Graphql как ssr

Я создал следующий js-проект и настроил apolo-клиент. Я читал этим своим детям. это мой layout.tsx код файла

import { Inter } from "next/font/google";
import "./globals.css";
import ApolloProviderClient from "@/components/ApolloProviderClient";

const inter = Inter({ subsets: ["latin"] });

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

и код ApolloProviderClient -

"use client";

import { ApolloProvider } from "@apollo/client";
import { CheckoutProviderOwn } from "@/context/checkoutContextOwn";
import { SingleTimeLoader } from "@/components/singleTimeLoader/SingleTimeLoader";
import { client } from "@/utils/apollo-clients";

const ApolloProviderClient = ({ children }: { children: React.ReactNode }) => {
  return (
    <ApolloProvider client = {client}>
      <CheckoutProviderOwn client = {client}>
        <SingleTimeLoader />
        {children}
      </CheckoutProviderOwn>
    </ApolloProvider>
  );
};

export default ApolloProviderClient;`

и клиентский код это

import { ApolloClient, createHttpLink, InMemoryCache } from "@apollo/client";
import { setContext } from "@apollo/client/link/context";
import { baseUrl } from "@/utils/constant/baseUrl";

const httpLink = createHttpLink({
  uri: baseUrl,
});

const authLink = setContext((_, { headers }) => {
  const sessionToken = sessionStorage.getItem("accessToken");
  const localToken = localStorage.getItem("accessToken");
  const token = sessionToken || localToken;
  return {
    headers: {
      ...headers,
      Authorization: token ? `Bearer ${token}` : "",
    },
  };
});

export const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});

Итак, как я могу создать компонент ssr, вызвать данные Graphql API для извлечения и отобразить их без использования "use client"

Я хотел создать страницу продукта, на которой я хочу разместить все продукты с SSR из-за возможностей SEO.

🤔 А знаете ли вы, что...
JavaScript можно использовать для создания ботов и автоматизации задач в браузерах с помощью Puppeteer.


2
162
1

Ответ:

Решено

Вам нужны немного другие настройки для использования клиента Apollo с серверными страницами. Вам нужно будет переписать компоненты, чтобы использовать клиент Apollo напрямую, не полагаясь на контекст ApolloProvider и перехватчик useQuery. Вот хорошая артлиса , объясняющая, как это сделать.

Вот реализация crud (на основе статьи):


// src/lib/client.ts

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({
      uri: "put your api endpoint here",
    }),
  });
});

//src/lib/apollo-wrapper.ts
"use client";

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

function makeClient() {
  const httpLink = new HttpLink({
      uri: "put your api endpoint here",
  });

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === "undefined"
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true,
            }),
            httpLink,
          ])
        : httpLink,
  });
}

export function ApolloWrapper({ children }: React.PropsWithChildren) {
  return (
    <ApolloNextAppProvider makeClient = {makeClient}>
      {children}
    </ApolloNextAppProvider>
  );
}

// src/app/layout.js
import { ApolloWrapper } from "/@lib/apollo-wrapper";

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


// here is a server component called UserProfile and here we want to get the user data

import { gql } from "@apollo/client";
import { getClient } from "@/lib/client";
import { cookies } from "next/headers";


const USER_QUERY = gql`
  query Query {
    user {
      id
      firstName
      email
      phone
    }
  }
`;


const UserProfile = async () => {
  const client = getClient();
  const ourCookies = cookies();

  let token = await ourCookies.get("jwtToken")!.value;

  let jwtToken = JSON.parse(token);

  const { data } = await client.query({
    query: USER_QUERY,
    context: {
      headers: {
        Authorization: `Bearer ${jwtToken}`,
      },
    },
  });
  console.info("🚀 ~ user ~ data:", data?.user);
  return (
    <>
      <h1>{data?.user?.firstName}</h1>
      <h2>{data?.user?.email}</h2>
    </>
  );
};