Sunucu adaları

Bazen başka türlü statik olan bir sayfanın tek bir bölgesi taze, isteğe özgü veri ister — önbelleğe alınmış bir blog yazısının altındaki yorumlar, bir ürün sayfasındaki stok rozeti. Sunucu adaları sayfayı statik tutar ve sayfa görüntülendiğinde yalnızca o bölgeyi bir sunucuda işler.

1. Adayı yazın

Bir ada, src/islands/ altındaki bir parça modülüdür — düz bir .js ya da .ts dosyası (.ht.js değil, çünkü adalar sayfa değil parçadır). sitelo’nun her yerindeki fikrin aynısı: HTML döndüren bir fonksiyon.

export default async function comments({ props, request }) {
  const comments = await fetchComments(props.postId)
  return `<ul>${comments.map((c) => `<li>${c.text}</li>`).join('')}</ul>`
}

{ name, props, request } alır ve bir HTML dizesi döndürmelidir. Ada modülleri yalnızca sunucuya aittir — src/ altındaki başvurulmayan kod tarayıcıya hiç gönderilmez.

2. Sayfaya yerleştirin

sitelo/islands içinden island() içe aktarın. Statik derleme yedek HTML’i yayımlar; proplar yer tutucuya gömülür, bu yüzden onları küçük ve gizli olmayan tutun.

import { html, body, article, script } from 'javascript-to-html'
import { island } from 'sitelo/islands'

export default ({ params }) =>
  html(
    body(
      article('…statik içerik…'),
      island('comments', { postId: params.slug }, '<p>Yorumlar yükleniyor…</p>'),
      script({ type: 'module', src: '/islands.js' }),
    ),
  )

3. İstemci yükleyicisini ekleyin

Küçük bir betik, işlenen her parçayı getirir ve yerine koyar. Normal varlık hattından geçer, bu yüzden düz bir src/islands.js girişi yeterlidir:

import { mountIslands } from 'sitelo/islands/client'

mountIslands()

sitelo (geliştirme) ve sitelo preview içinde bu zaten çalışır — ikisi de adaları src/islands/ dizininden /_sitelo/islands/<name> adresinde sunar. Önizleme yerel .js / .mjs modüllerini yükler (bir Node sunucusuyla aynı); TypeScript adaları geliştirmede Vite üzerinden desteklenir.

Üretim

Statik sunucunuz sayfaları sunmayı sürdürür. Sunucu kodu çalıştırdığınız yere küçük bir işleyici bağlayın — Node, sunucusuz ya da bir kenar fonksiyonu — ve aynı ada modüllerini işlesin. Çalıştırılabilir bir Node sunucusu ile Netlify ve Vercel taslaklarını içeren tam bir anlatım için Sunucu adaları örneğine bakın.

// örneğin bir Node sunucusu ya da bir serverless/edge işlevi
import { createIslandsHandler } from 'sitelo/islands/server'

const handleIslands = createIslandsHandler({
  islands: {
    comments: () => import('./src/islands/comments.js'),
  },
})

// web Request → Response | null (null = ada isteği değil)
export default { fetch: (request) => handleIslands(request) }

Düz Node http ya da express üzerinde bunun yerine createIslandsNodeHandler(options) kullanın — aynı seçenekler, (req, res, next) imzası. src/islands/ altındaki her .js / .mjs modülünü createIslandsFromDirectory ile kendiliğinden bağlayın. Yükleyici farklı bir kaynaktan ya da yoldan getiriyorsa mountIslands({ endpoint: 'https://api.example.com/islands' }) geçirin ve işleyicinin endpoint seçeneğiyle eşleştirin.

Kararlılık listesi

Yükleme stratejileri

Varsayılan olarak her ada sayfa yüklenir yüklenmez getirir, bu yüzden sekiz adalı bir sayfa ilk boyama sırasında sekiz eşzamanlı istek yapar. Hemen görünmeyenleri ertelemek için when geçirin.

// Sayfa yüklenir yüklenmez yükle — varsayılan.
island('cart', { id }, '<p>…</p>')

// Boşta kalma geri çağrısını bekle.
island('recommendations', { id }, '<p>…</p>', { when: 'idle' })

// Görünüme girene dek bekle.
island('comments', { postId }, '<p>Yorumlar yükleniyor…</p>', {
  when: 'visible',
  rootMargin: '400px',   // 400px erken yüklemeye başla
})

rootMargin yalnızca 'visible' için geçerlidir ve varsayılanı '200px' değeridir. Adalar sonsuza dek dönmek yerine zaman aşımına da uğrar:

mountIslands({
  timeout: 5000,        // ada başına; 0 devre dışı bırakır. Varsayılan 10000
  rootMargin: '300px',  // `when: 'visible'` adaları için varsayılan
})

mountIslands() anlık adalar yerine oturduğunda çözülür — ertelenenler kendi başlarına sonradan yüklenir ve bilerek beklenmez. Başarısız olan ya da zaman aşımına uğrayan bir ada yedek HTML’ini korur.

Proplar güvenilmez girdidir

Ada propları istemciden gelir. Sayfaya gömülür, istekte geri gönderilir ve herkes önce onları düzenleyebilir:

GET /_sitelo/islands/profile?props={"userId":"someone-else"}

Adanızın aldığı propları tam olarak bir sorgu parametresi gibi değerlendirin — doğrulayın ve onları, görüntüleyenin görmeye zaten hakkı olmayan verileri aramak için asla kullanmayın.

Proplar ayrıcalıklı veri seçiyorsa onları imzalayın. Bir sır belirleyin; sitelo her yer tutucuyu derleme sırasında imzalar ve başka her şeyi bir 403 ile reddeder:

SITELO_ISLANDS_SECRET=$(openssl rand -hex 32) sitelo build

Aynı değişkeni sitelo, sitelo preview ve createIslandsHandler okur, böylece geliştirme, önizleme ve üretim uyuşur. Üretim sunucunuza aynı sırrı verin. Kod içinde ayarlamayı mı tercih edersiniz?

import { configureIslands } from 'sitelo/islands'

configureIslands({ secret: process.env.MY_SECRET })

İmzalar, ada adı ve propları üzerinde HMAC-SHA256’dır; bu yüzden bir ada için verilen bir imza bir başkasına karşı yeniden oynatılamaz. İmzalama, propların sizin derlemenizden geldiğini kanıtlar — onları gizlemez, dolayısıyla yine de gizli olmamaları gerekir. Sır olmadan proplar olduğu gibi kabul edilir ve onları doğrulamak tümüyle ada modülünüzün işidir.

Bilmekte fayda var