برنامه نویسی

معرفی مفهوم 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، ویرایشگر جدول را برای بررسی داده ها انتخاب کنید

supabase2

supabase3


برای جستجوی داده های فردی 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 بررسی

کلیدهای api


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/

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

همچنین ببینید
بستن
دکمه بازگشت به بالا