Temel Kavramlar

Carats'in temel kavramlarını anlamak, uygulamalarınızı daha etkili kurmanıza yardımcı olur.

JJSX

JJSX, PHP'ye benzer şekilde saf bir HTML ve JavaScript deneyimi sunar. React'e benzer şekilde TSX dosyaları içine JavaScript kodu yazmanıza izin verir, ancak React hook'ları veya React DOM kullanmaz. Bileşenler HTML döndüren düz fonksiyonlar olduğu için aynı bileşen sunucuda ve tarayıcıda birebir aynı şekilde işlenir.

Temel Özellikler

  • Saf HTML ve JavaScript söz dizimi
  • React bağımlılığı yok
  • Otomatik sunucu ve istemci tarafı işleme

JJSX bir fonksiyon çağrısına derlenir; bu yüzden bir bileşen, HTML dizesi döndüren sıradan bir fonksiyondur. Karşılaştırılacak bir sanal DOM ve yaşatılacak bir bileşen örneği yoktur; bu yüzden aynı fonksiyonu sunucuda ve ardından tarayıcıda çalıştırmak güvenlidir.

export default function Greeting(props: { name: string }) {
    return <p>Hello {props.name}</p>
}

Facet'ler

Facet'ler Carats içindeki yönlendirme sistemidir. Rota kalıplarını sayfa bileşenlerine eşleyen tek bir nesnedir ve aynı nesne hem istemci hem sunucu tarafından kullanılır; böylece bir rota ikisi arasında asla ayrışamaz. Facet'ler src/client/facets.cara.ts içinde tanımlanır ve rota parametrelerini, suspense durumlarını ve uygulama içi yönlendirmenin açık olup olmadığını bildirebilir.

Facet Tanımlama

import { defineFacets } from '@carats/render';
import ErrorPage from './pages/_error';
import NotFound from './pages/_not_found';
import Home from './pages/home';
import Profile from './pages/profile';

export default defineFacets({
    routes: {
        '/': Home,
        '/profile': Profile
    },
    suspense: {
        error: ErrorPage,
        notFound: NotFound
    },
    inAppRouting: true
});

defineFacets kısmi bir tanım kabul eder; bu yüzden hem routes hem suspense isteğe bağlıdır. Referans şablon yalnızca error ve notFound bildirir; bir sayfa gerçekten askıya alınmıyorsa loading'i atlayın.

Bir facet aynı zamanda veri çekme birimidir. `routes` içindeki bir rota, bir culet'in kayıt edilmesi gereken rotadır; `Burnish` ile sarılan bir sayfa ise o culet'in döndürdüğü değeri alır.

Culet'ler

Culet'ler bileşenlere veri sağlayan sunucu tarafı fonksiyonlardır. src/server/culets içinde tanımlanır ve sunucu giriş noktasında oturtulur. Sunucu tarafı veri gerektiren bileşenler burnished olur; bu durumda framework onların culet'inden otomatik olarak veri çeker. Bir culet, rota dizesiyle sayfaya eşleştirilir; bu yüzden culet'in rotası ile facet'in rotası birebir aynı olmalıdır.

Culet Tanımlama

// src/server/culets/profile.ts
import { culet } from '@carats/ssr';

export default culet<User>('/profile', (req) => {
    return {
        id: '1',
        name: 'John Doe',
        username: 'johndoe',
        email: 'john@example.com'
    };
});

Dinamik bir rotada parametre `req.params` üzerinden okunur:

// src/server/culets/trade.ts
import { culet } from '@carats/ssr';

export default culet<TradeData>('/trade/:symbol', async (req) => {
    const symbol = req.params.symbol.toUpperCase();
    const quote = await fetchQuote(symbol);
    return { symbol, price: quote.price };
});

Culet'leri Oturtma

Kendi dosyasında tanımlanan bir culet, culet(route, handler) ile oluşturulur ve ardından seat() ile kaydedilir. seat culet'i olduğu gibi döndürür; bu yüzden oturtmak yalnızca bir kayıt adımıdır. Aynı culet'i başka bir culet() çağrısıyla ikinci kez kaydetmeyin.

// src/server/entrypoint.ts
import { defineServerEntry, seat } from '@carats/ssr';
import facets from '../client/facets.cara';
import getTradeData from './culets/trade';

seat(getTradeData);

export default defineServerEntry(facets);

Sunucu Prop'ları

Sunucu prop'ları bir culet'in döndürdüğü değerlerdir. Framework bunları sunucu tarafı işleme sırasında çözer, sayfaya serileştirir ve burnished bileşene ilk argüman olarak geçirir. Bileşen hiçbir şeyi kendisi çekmez.

Sunucu prop'ları, burnished bir bileşenin ilk argümanı olarak gelir:

import { Burnish } from '@carats/render';
import Layout from '../_layout';

export default Burnish<TradeData>(function (data) {
    this.head = <title>Trade {data.symbol}</title>;
    return (
        <Layout>
            <h1>{data.symbol}</h1>
        </Layout>
    );
});

Burnished olmayan bir sayfa yalnızca prop almaz; bu, statik sayfalar için olağan durumdur.

İşleme Modeli

Her sayfa önce sunucuda işlenir. HTML şablonu doldurulur, sayfa bileşeni çalışır ve oluşan işaretleme, çözülen sunucu prop'larıyla birlikte tarayıcıya gönderilir. Tarayıcıda aynı facet'ler bağlanır ve uygulama devralır. Dolayısıyla bir bileşen fonksiyonu her iki yerde de çalışır; işte bu yüzden yan etkiler afterMount veya beforeMount'a ertelenmelidir.

Pratik sonucu şudur: bir bileşen gövdesindeki ifadeler normal bir sayfa yüklemesinde iki kez çalışır; bir kez sunucuda, bir kez tarayıcıda. `document` ile ilgili olan, `window` okuyan veya yan etki üreten her şey bir hook'a ertelenmelidir, aksi halde sunucu tarafı işleme hata verir.

İstemci Çalışma Zamanı

@carats/csr facet'leri bağlar, uygulama içi yönlendirme açıkken iç bağlantı tıklamalarını yakalar ve serileştirilmiş sunucu prop'larını sunar. window.carats.ssp.for, mevcut sunucu prop'larının ait olduğu rotayı tutar; window.carats.ssp.data ise prop'ların kendisini. HTML'i ayrıştırmak yerine bunları framework üzerinden okumak ve programatik gezinme için goTo kullanmak tercih edilir.

import { goTo } from '@carats/csr';
import { afterMount } from '@carats/hooks';
import './search-bar.sass';

export default function SearchInput() {
    afterMount(() => {
        const form = document.getElementById('search-bar');
        const submit = (e: Event) => {
            e.preventDefault();
            const q = (document.getElementById('search-input') as HTMLInputElement).value;
            goTo(`/search?q=${q}`);
        };
        form?.addEventListener('submit', submit);
        return () => form?.removeEventListener('submit', submit);
    });

    return (
        <form id="search-bar">
            <input id="search-input" name="q" type="text" />
        </form>
    );
}

`goTo`, yakalanan bir bağlantı tıklamasıyla aynı şekilde gezinir; bu yüzden uygulama içi yönlendirme açıkken belge yeniden yüklenmez.