SSR: clerk с hasura

Эта статья поможет вам в достижении рендеринга (аутентификации) на стороне сервера с помощью clerk(withServerSideAuth) в next.js

Клерк
Множество стратегий аутентификации доступны через Clerk, чтобы легитимные пользователи могли получить доступ к вашему приложению и делать аутентифицированные запросы.

Внедрение SSR с помощью Nextjs и Clerk
Чтобы включить рендеринг на стороне сервера, Nextjs использует специальный экспорт getServerSideProps. Хелпер WithServerSideAuth из Clerk заполняется синглтоном auth.

шаги:

  1. настройка клиента apollo
  2. используйте getServerSideProps и withServerSideAuth для ssr
  3. использование запроса graphql
  4. тестирование для аутентифицированного и неаутентифицированного пользователя
  5. если есть условие, при котором ваш запрос должен отвечать только после входа в систему, пожалуйста, не возвращайте ничего, иначе это приведет к проблемам.

фрагмент кода для этого:

1.настройка apolloclient:
import { useMemo } from 'react';
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client';
import merge from 'deepmerge';
import isEqual from 'lodash/isEqual';

let apolloClient;
const uri = process.env.NEXT_PUBLIC_HASURA_URI;
function createApolloClient(headers) {
  return new ApolloClient({
    ssrMode: typeof window === 'undefined', // set to true for SSR
    link: createHttpLink({
      uri,
      credentials: 'same-origin',
      headers: {
        Apitoken: process.env.YOUR_API_TOKEN,
      },
    }),
    cache: new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
            feed: {
              keyArgs: ['strategy', 'limit', 'gt_token'],
              // Concatenate the incoming list items with
              // the existing list items.
              merge(existing = [], incoming) {
                const result = Object.assign({}, incoming);
                if (existing?.hits) {
                  result.hits = [...existing.hits, ...incoming.hits];
                }
                return result;
              },
            },
            experts: {
              keyArgs: ['limit'],
              // Concatenate the incoming list items with
              // the existing list items.
              merge(existing = [], incoming) {
                const result = Object.assign({}, incoming);
                if (existing?.hits) {
                  result.hits = [...existing.hits, ...incoming.hits];
                }
                return result;
              },
            },
          },
        },
      },
    }),
  });
}

export function initializeApollo(initialState = null, ctx) {
  const headers = ctx?.headers ?? {};
  const _apolloClient = apolloClient ?? createApolloClient(headers);

  // If your page has Next.js data fetching methods that use Apollo Client,
  // the initial state gets hydrated here
  if (initialState) {
    // Get existing cache, loaded during client side data fetching
    const existingCache = _apolloClient.extract();

    // Restore the cache using the data passed from
    // getStaticProps/getServerSideProps combined with the existing cached data
    const data = merge(initialState, existingCache, {
      // combine arrays using object equality (like in sets)
      arrayMerge: (destinationArray, sourceArray) => [
        ...sourceArray,
        ...destinationArray.filter((d) =>
          sourceArray.every((s) => !isEqual(d, s))
        ),
      ],
    });
    _apolloClient.cache.restore(data);
  }

  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient;

  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient;
  return _apolloClient;
}

export function useApolloHasura(initialState) {
  return useMemo(
    () => initializeApollo(initialState, undefined),
    [initialState]
  );
}
Вход в полноэкранный режим Выйти из полноэкранного режима
2.использование getServerSideProps и withServerSideAuth для ssr:
import { initializeApollo } from '../apolloClient';
import { withServerSideAuth } from '@clerk/nextjs/ssr';

export const getServerSideProps = withServerSideAuth(
  async (ctx) => {
   const { getToken } = ctx.req.auth;
    const token = await getToken({ template: 'hasura' });
    const apolloClient = initializeApollo(null, ctx);

   const client = initialApollo(null, ctx);
    const sub =
      (await client.query({
        query: YOUR_QUERY,
        context: {
          headers: {
            authorization: 'YOUR_AUTHORIZATION_TOKEN',
          },
        },
      }));

    const status = sub?.data;

       return {
      props: {
        isStatus: status,
      },
    };
  },
  { loadUser: true }
);
Войти в полноэкранный режим Выйти из полноэкранного режима
3. условие, при котором ваш запрос должен отвечать только после входа в систему:

Здесь приведен фрагмент для запроса, который выдает ответ только для аутентифицированных пользователей пример запроса подписки… вам нужно сделать небольшие изменения в приведенном выше коде. статус вернется неопределенным, если token(hasuraToken) вернет ничего для неаутентифицированного пользователя, поэтому в этом случае вам нужно вернуть null, как показано ниже.

  const sub =
      token !== null &&
      (await client.query({
        query: PAYMENTS,
        context: {
          headers: {
            authorization: `Bearer ${token}`,
          },
        },
      }));

   const status = sub?.data;

   return {
      props: {
        isStatus: status === undefined ? null : status
      },
    };


Вход в полноэкранный режим Выход из полноэкранного режима

Для получения дополнительной информации, пожалуйста, обратитесь к примеру Clerk и Nextjs с SSR

Что вы думаете по этому поводу? Есть ли другой способ, который я не упомянул? Пожалуйста, дайте мне знать, комментируя ниже. Я не могу дождаться ответа. Спасибо

Счастливого кодинга!!!

Оцените статью
devanswers.ru
Добавить комментарий