Эта статья поможет вам в достижении рендеринга (аутентификации) на стороне сервера с помощью clerk(withServerSideAuth) в next.js
Клерк
Множество стратегий аутентификации доступны через Clerk, чтобы легитимные пользователи могли получить доступ к вашему приложению и делать аутентифицированные запросы.
Внедрение SSR с помощью Nextjs и Clerk
Чтобы включить рендеринг на стороне сервера, Nextjs использует специальный экспорт getServerSideProps. Хелпер WithServerSideAuth из Clerk заполняется синглтоном auth.
шаги:
- настройка клиента apollo
- используйте getServerSideProps и withServerSideAuth для ssr
- использование запроса graphql
- тестирование для аутентифицированного и неаутентифицированного пользователя
- если есть условие, при котором ваш запрос должен отвечать только после входа в систему, пожалуйста, не возвращайте ничего, иначе это приведет к проблемам.
фрагмент кода для этого:
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
Что вы думаете по этому поводу? Есть ли другой способ, который я не упомянул? Пожалуйста, дайте мне знать, комментируя ниже. Я не могу дождаться ответа. Спасибо
Счастливого кодинга!!!