معرفی مفهوم BFF (Backend for Frontend) با برنامه ساده با SvelteKit، Supabase و GraphQL Code Generator
BFF (Backend for Frontend)
. مفهوم افزایش بهره وری توسعه با پیاده سازی یک لایه سرور دوستدار frontend با ترکیب بلوک های سرور کاربردی. اما در واقع MicroService Architecture
این مفهومی است که فقط برای خدمات در مقیاس بزرگ که بر آن استوار است معنی دارد.
با این حال، بکارگیری این مفاهیم ساختاری در پروژه های کوچک غیرممکن نیست.
در این پست، برنامه Full Stack SvelteKit
و BaaS Supabase
از این طریق، می خواهم محتویات آزمایش مفاهیم مشابه را از قبل در مقیاس کوچک معرفی کنم.
در این زمان نقش DB و Functional Server Block منبع باز است BaaS (Backend as a Service)
شخص Supabase
بنابراین، نقش های Frontend و BFF هستند Svelte-kit
اجرا شده به عنوان
همچنین موجود REST
متفاوت از روش GraphQL Codegen
من می خواهم نحوه برقراری ارتباط بین سرور و مشتری با استفاده از .
توصیه می کنیم قبل از خواندن این پست، پست زیر را مطالعه کنید.
https://dev.to/soom/how-to-use-graphql-and-react-query-with-graphql-code-generator-based-on-nextjs-23jj
شروع شدن
راه اندازی Supabase
پس از ثبت نام در Supabase، ایجاد پروژه و ورود به داشبورد
در این پست، طرح و جداول DB را جداگانه ایجاد نمی کنیم. Quick Start
کار با مثال ها
SQL Editor > Countries > Run
پس از ایجاد DB، ویرایشگر جدول را برای بررسی داده ها انتخاب کنید
برای جستجوی داده های فردی function
تولید کردن (Supabase
ویژگی)
SQL Editor > New Query
پس از اجرای دستور زیر در
SQL Editor > New Query
/* Create Function */
create or replace function get_country()
returns setof countries
language sql
as $$
select * from countries;
$$;
/* Check Result */
select *
from get_country()
where id = 1;
راه اندازی SvelteKit
پس از ایجاد پوشه پروژه مورد نظر SvelteKit
یک پروژه ایجاد کنید
pnpm create svelte@latest
✔ Where should we create your project?
(leave blank to use current directory) … simple-bff
✔ Which Svelte app template? › Skeleton project
✔ Add type checking with TypeScript? › Yes, using TypeScript syntax
✔ Add ESLint for code linting? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
? Add Playwright for browser testing? › No / Yes
راه اندازی Supabase Client در SvelteKit
Supabase
کلاینت را نصب کنید
پایانه
pnpm add -S @supabase/supabase-js
src/lib/db/index.ts
کلاینت Supabase را به صورت زیر تعریف کنید
src/lib/db/index.ts
import { createClient } from '@supabase/supabase-js';
const supabase = createClient('https://<project>.supabase.co', '<your-anon-key>');
export default supabase;
توجه داشته باشید
اطلاعات مشتری در داشبورد Supabase موجود است.
Settings > API > URL
،Project API Keys
بررسی
src/lib/country/db/index.ts
، src/lib/countries/db/index.ts
تعریف درخواست DB مربوطه
بررسی کنید که آیا داده های DB درخواستی به خوبی بارگذاری شده است
src/lib/country/db/index.ts
import supabase from '$lib/db';
// request id = 18 country data
const country = await supabase.rpc('get_country').eq('id', 18);
export default country;
src/lib/countries/db/index.ts
import supabase from '$lib/db';
// request all the countries
const countries = await supabase.from('countries').select();
export default countries;
راه اندازی Graphql Yoga Server در سرور SvelteKit
SvelteKit Server
ترکیب بندی. اینجا Graphql Yoga
با استفاده از Graphql Server
پیاده سازی
src/routes/graphql/+server.ts
نوشتن فایل سرور به
url api سرور است /graphql
قابل دسترسی با
توجه داشته باشید
از آنجایی که این پروژه ساختار پایه دامنه است، پرس و جو و طرح graphql مربوطه پراکنده هستند.
لودر فایل graphql فایل های graphql که در پروژه پخش شده اند را به یکباره جمع آوری می کند
اینجا
country.data[0]
،countries.data
استSupabase
درخواست مقدار بازگشت ازبرای بقیه به لینک مراجعه کنید:
https://the-guild.dev/graphql/yoga-server/docs/integrations/integration-with-sveltekit
پایانه
pnpm add -S graphql graphql-yoga
pnpm add -D @graphql-tools/graphql-file-loader @graphql-tools/load
src/routes/graphql/+server.ts
import { createYoga, createSchema } from 'graphql-yoga';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { loadSchema, loadDocuments } from '@graphql-tools/load';
import country from '$lib/country/db';
import countries from '$lib/countries/db';
import type { RequestEvent } from '@sveltejs/kit';
const typeDefs = await loadSchema('./src/lib/**/graphql/schema.graphql', {
loaders: [new GraphQLFileLoader()],
});
const defaultQuery = await loadDocuments('./src/lib/countries/graphql/query.graphql', {
loaders: [new GraphQLFileLoader()],
}).then((res) => res[0].rawSDL);
const yogaApp = createYoga<RequestEvent>({
schema: createSchema({
typeDefs,
resolvers: {
Query: {
countries: () => countries.data,
country: () => country.data[0],
},
},
}),
graphiql: {
defaultQuery,
},
fetchAPI: globalThis,
});
export { yogaApp as GET, yogaApp as POST };
ایجاد طرح و فایل پرس و جو graphql مربوطه (کشور، کشورها)
src/lib/country/graphql/schema.graphql
type Country {
id: Int!
name: String!
iso2: String!
iso3: String!
local_name: String
continent: String
}
type Query {
country: Country
}
src/lib/country/graphql/query.graphql
query Country {
country {
id
name
iso2
iso3
local_name
continent
}
}
src/lib/countries/graphql/schema.graphql
type Query {
countries: [Country]!
}
src/lib/countries/graphql/query.graphql
query Countries {
countries {
id
name
iso2
iso3
local_name
continent
}
}
حالا اجراش کن /graphql
به آن متصل شوید و بررسی کنید که آیا زمین بازی به طور معمول ظاهر می شود
تولید خودکار Query Svelte با Graphql Codegen
بسته های مربوط به کدژن را نصب کنید
پایانه
pnpm add -S graphql-request
pnpm add -D @graphql-codegen/cli @graphql-codegen/near-operation-file-preset @graphql-codegen/typescript @graphql-codegen/typescript-graphql-request @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-query
pnpm add -D @sveltestack/svelte-query
توجه داشته باشید
دلایل نصب @graphql-codegen/typescript-react-query
- کدژن graphql از پرس و جوی svelte پشتیبانی نمی کند
- با این حال، react query و svelte query ارائه شده توسط tanstack دارای ساختار یکسانی با نامگذاری متفاوت هستند، بنابراین می توانید با تغییر این قسمت از آن استفاده کنید.
کدgen.yml را در پوشه root ایجاد کنید
همچنین اسکریپت codegen را در package.json بنویسید
توجه داشته باشید
codegen.yml
schema: http://localhost:5173/graphql
documents: './src/lib/**/graphql/!(*.generated).{gql,graphql}'
require:
- ts-node/register
generates:
src/lib/types/index.ts:
plugins:
- typescript
src/:
preset: near-operation-file
presetConfig:
extension: .generated.ts
baseTypesPath: 'lib/types'
plugins:
- typescript-operations
- typescript-react-query
config:
pureMagicComment: true
exposeQueryKeys: true
exposeFetcher: true
withHooks: true
fetcher: graphql-request
config:
interfacePrefix: 'I'
typesPrefix: 'I'
skipTypename: true
declarationKind: 'interface'
noNamespaces: true
hooks:
afterOneFileWrite: 'prettier --plugin-search-dir . --write .'
package.json
{
...
"scripts": {
...
"codegen": "graphql-codegen --config codegen.yml"
},
...
}
تنظیمات محیط پیش فرض پرس و جوی svelte
src/lib/plugin/svelteQuery.ts
import { QueryClient } from '@sveltestack/svelte-query';
// Configure for static fetching from Server
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
});
src/routes/+layout.svelte
<script lang="ts">
import '../app.css';
import { queryClient } from '$lib/plugin/svelteQuery';
import { QueryClientProvider } from '@sveltestack/svelte-query';
</script>
<QueryClientProvider client={queryClient}>
<main class="flex justify-center items-center w-full h-[100vh]">
<slot />
</main>
</QueryClientProvider>
بعد از اجرای کدجن نتیجه را بررسی کنید
پایانه
# first, run svelte-kit app with server
pnpm dev
# auto generating!
pnpm codegen
> graphql-codegen --config codegen.yml
✔ Parse Configuration
✔ Generate outputs
src/lib/country/graphql
، src/lib/countries/graphql
در پوشه query.generated.ts
تولید کردن
src/lib/types/index.ts
ایجاد فایل
در اینجا، نوع به طور معمول ایجاد می شود، اما مشکل اینجاست query.generated.ts
همانطور که در بالا ذکر شد، بر اساس react-query ایجاد شده است، بنابراین باید مطابق با svelte-query اصلاح شود.
مانند مثال زیر react-query
بسته وارداتی svelte query
ترتیب دادن به تناسب
src/lib/country/graphql/query.generated.ts
// auto-generated react-query
// import * as Types from '../../types';
// import { GraphQLClient } from 'graphql-request';
// import { RequestInit } from 'graphql-request/dist/types.dom';
// import { useQuery, UseQueryOptions } from '@tanstack/react-query';
// Convert for svelte-query
import type * as Types from '$lib/types';
import { GraphQLClient } from 'graphql-request';
import { useQuery } from '@sveltestack/svelte-query';
import type { RequestInit } from 'graphql-request/dist/types.dom';
import type { UseQueryOptions } from '@sveltestack/svelte-query';
اکنون view
ایجاد سطح
SPA
همانطور که نصب شده خالی است index.html
برای سئو بسیار مضر است زیرا رندر با بارگذاری بسته js در آن انجام می شود SSR
نقره Hydration technique
شما می توانید با بارگذاری اطلاعات لازم از قبل از سئو استفاده کنید.
توجه داشته باشید
src/routes/country/+page.ts
import { error } from '@sveltejs/kit';
import { dehydrate } from '@sveltestack/svelte-query';
import { queryClient } from '$lib/plugin/svelteQuery';
import { useCountryQuery } from '$lib/country/graphql/query.generated';
import { GraphQLClient } from 'graphql-request';
import type { PageLoad } from './$types';
export const load = (async ({ route }) => {
const gqlClient = new GraphQLClient('http://localhost:5173/graphql');
await queryClient.prefetchQuery(useCountryQuery.getKey(), useCountryQuery.fetcher(gqlClient));
if (route.id === '/country') {
return {
title: 'country',
dehydratedState: dehydrate(queryClient),
};
}
throw error(404, 'Not found');
}) satisfies PageLoad;
src/routes/country/+page.svelte
<script lang="ts">
import { GraphQLClient } from 'graphql-request';
import { useCountryQuery } from '$lib/country/graphql/query.generated';
import type { PageData } from './$types';
export let data: PageData;
const gqlClient = new GraphQLClient('http://localhost:5173/graphql');
const countriesQueryResult = useCountryQuery(gqlClient);
const { country } = $countriesQueryResult.data!;
</script>
<svelte:head>
<title>{data.title}</title>
</svelte:head>
<div class="text-center">
<h1 class="text-3xl font-bold">Hello Country!</h1>
<a href="/"> > Back Home</a>
<div class="my-2">
{country?.iso2}
{country?.name}
</div>
</div>
نتیجه
➕➕ نمونه Stackblitz
نتیجه
در این پست BFF
یک مدل مفهومی ساده Supabase
، SvelteKit
من اجراش کردم با
در یک سرویس در مقیاس بزرگ، Client، Server (BFF)، سرور، DB و غیره همه به طور جداگانه پیکربندی می شوند، اما هیچ مشکل بزرگی در درک خود مفهوم از طریق یک مثال ساده در مقیاس کوچک وجود ندارد.
همچنین، GraphQL Code Generator
راهی برای دسترسی به ارتباط بین سرور و کلاینت از طریق ایجاد خودکار با استفاده از .
موجود Swagger
به همین ترتیب، هنوز محدودیتی برای ارتباط بین کلاینت و سرور وجود داشت. با این حال GQL Codegen
به طور خودکار تولید می شود Schema
استفاده از روش بسیار توصیه می شود زیرا می تواند خطاهای انسانی را بدون نیاز به پرس و جو از سمت سرور به حداقل برساند.
ps
اکثر سرورها و کلاینت های GraphQL Apollo Server
، Apollo Client
و غیره، اما اینجا GraphQL Yoga
، Svelte Query
نحوه استفاده معرفی شده است.GraphQL Yoga
به نسخه 3 منتقل شد Apollo Server
ما راه حلی ارائه می دهیم که تا حد زیادی ناراحتی را برطرف می کند GraphQL Guild
خیلی زیاد GraphQL
از آنجایی که صادقانه است، در آینده می توان پیشرفت بزرگی را انتظار داشت.
آدرس انجمن: https://the-guild.dev/