apollo-client.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { cache as reactCache } from "react";
  2. import { GRAPHQL_URL } from "@/utils/constants";
  3. import {
  4. ApolloClient,
  5. HttpLink,
  6. InMemoryCache,
  7. from,
  8. } from "@apollo/client";
  9. import { setContext } from "@apollo/client/link/context";
  10. import { getSession } from "next-auth/react";
  11. import { getCartToken } from "@/utils/getCartToken";
  12. import { BagistoSession } from "@/types/types";
  13. let sessionCache: { session: BagistoSession | null; timestamp: number } | null = null;
  14. const SESSION_CACHE_TTL = 5000;
  15. const getSessionForRequest = reactCache(async () => {
  16. return (await getSession()) as BagistoSession | null;
  17. });
  18. async function getCachedSession(): Promise<BagistoSession | null> {
  19. if (typeof window === "undefined") {
  20. return getSessionForRequest();
  21. }
  22. const now = Date.now();
  23. if (sessionCache && now - sessionCache.timestamp < SESSION_CACHE_TTL) {
  24. return sessionCache.session;
  25. }
  26. const session = (await getSession()) as BagistoSession | null;
  27. sessionCache = { session, timestamp: now };
  28. return session;
  29. }
  30. function createApolloClient() {
  31. const ssrMode = typeof window === "undefined";
  32. const cache = new InMemoryCache();
  33. // 服务端渲染的话请求的地址是bagisto后端地址,否则的话请求的是nextjs的代理接口
  34. const httpLink = new HttpLink({
  35. uri: ssrMode ? GRAPHQL_URL : "/api/graphql",
  36. credentials: "include",
  37. });
  38. // 如果是服务端渲染,因为直接调用bagisto后端接口,需要设置storefront key
  39. const authLink = setContext(async (_, { headers }) => {
  40. if (ssrMode) {
  41. const storefrontKey =
  42. process.env.BAGISTO_STOREFRONT_KEY ||
  43. process.env.NEXT_PUBLIC_BAGISTO_STOREFRONT_KEY ||
  44. "";
  45. return {
  46. headers: {
  47. ...headers,
  48. "X-STOREFRONT-KEY": storefrontKey,
  49. },
  50. };
  51. }
  52. const session = await getCachedSession();
  53. const userToken = session?.user?.accessToken;
  54. const guestToken = !userToken ? getCartToken() : null;
  55. const token = userToken || guestToken;
  56. return {
  57. headers: {
  58. ...headers,
  59. ...(token && { Authorization: `Bearer ${token}` }),
  60. "Content-Type": "application/json",
  61. },
  62. };
  63. });
  64. const link = from([authLink, httpLink]);
  65. return new ApolloClient({
  66. ssrMode,
  67. link,
  68. cache,
  69. defaultOptions: {
  70. watchQuery: {
  71. fetchPolicy: ssrMode ? "network-only" : "cache-first",
  72. nextFetchPolicy: ssrMode ? "network-only" : "cache-first",
  73. },
  74. query: {
  75. fetchPolicy: ssrMode ? "network-only" : "cache-first",
  76. },
  77. },
  78. });
  79. }
  80. const getClient = reactCache(createApolloClient);
  81. export default function initializeApollo() {
  82. if (typeof window === "undefined") {
  83. return getClient();
  84. }
  85. return createApolloClient();
  86. }