Bu sayfa @lentystyle/ssr içindeki iki ayrı config katmanını açıklar:
- request-time render için
LentySsrConfig luis.config.mjsiçindeki project-levelssrbloğu
En Kısa Kurulum
Section titled “En Kısa Kurulum”pnpm add @lentystyle/ssrnpm install @lentystyle/ssryarn add @lentystyle/ssrİki Ayrı Config Katmanı
Section titled “İki Ayrı Config Katmanı”LentySsrConfig, renderLentySsrSnapshot(), createLentySsrIntegration() ve diğer request-time SSR yüzeylerine geçen public config tipidir.
Bu katman:
- runtime option default'larını tanımlar
- HTML injection metadata'sını taşır
modevehtmlGuardModegibi alanları resolved biçimde tutar
LuisSsrProjectConfig, luis.config.mjs içindeki ssr bloğudur.
Bu katman:
- paylaşılan app-level preview ayarlarını tutar
outDirName,include,excludevemaxEntriesgibi alanlar eklerloadLuisSsrProjectConfig()üzerinden yüklenir
LentySsrConfig
Section titled “LentySsrConfig”interface LentySsrConfig { mode?: 'static' | 'ssr' htmlGuardMode?: 'ssr' | 'hybrid' performance?: boolean debug?: boolean map?: boolean lazy?: boolean worker?: 'auto' | 'main' | 'worker' assetBaseUrl?: string globalCssHref?: string bootstrapScriptSrc?: string styleNonce?: string scriptNonce?: string runtimeOptions?: string | Partial<LentySsrRuntimeOptions> /** @deprecated 0.2.0'da deprecate edildi ve ignore edilir. */ adapter?: 'none' | 'vue' | 'svelte' | 'react' | 'astro' /** @deprecated 0.2.0'da deprecate edildi ve ignore edilir. */ rewritePolicy?: 'auto' | 'prefer-static' | 'prefer-runtime'}Varsayılanlar
Section titled “Varsayılanlar”| Field | Default |
|---|---|
mode | 'ssr' |
htmlGuardMode | 'ssr' (proje runner'ı varsayılan olarak 'hybrid' kullanır) |
debug | false |
performance | false |
map | false |
lazy | false |
worker | 'auto' |
assetBaseUrl | /_hybrid |
globalCssHref | null |
bootstrapScriptSrc | null |
styleNonce | null |
scriptNonce | null |
output.payloadMode | 'inline-json' (proje config'i 'external-json''a geçebilir; aşağıya bakın) |
Hızlı Örnek
Section titled “Hızlı Örnek”import { createLentySsrIntegration } from '@lentystyle/ssr'
const ssr = createLentySsrIntegration({ mode: 'ssr', globalCssHref: '/assets/site.css', bootstrapScriptSrc: '/assets/browser-entry.js', runtimeOptions: 'performance,!worker',})Bu örnekte:
- ortak global CSS her render'da
<link rel="stylesheet">olarak enjekte edilir - bootstrap script her render'da enjekte edilir
- runtime options çözümlemesi
performance: trueveworker: 'main'verir
CSP Nonce'ları
Section titled “CSP Nonce'ları”SSR'ın üretebileceği iki tag için iki bağımsız nonce alanı vardır:
const result = await renderLentySsrSnapshot( { styleNonce: 'STYLE_NONCE', bootstrapScriptSrc: '/entry.js', scriptNonce: 'SCRIPT_NONCE' }, input,)styleNonceyalnızca CSS boş değilse inline<style>tag'ine yazılırscriptNonceyalnızcabootstrapScriptSrcverilmişse bootstrap<script src>tag'ine yazılır- inline JSON payload script'i hiçbir zaman çalıştırılabilir olmadığı için nonce almaz
Her iki nonce değeri de result.artifacts üzerinde (styleNonce, scriptNonce) geri yansıtılır; ilgili tag üretilmediyse null olur.
Payload Modları
Section titled “Payload Modları”type LentySsrPayloadMode = 'inline-json' | 'external-json'inline-json(varsayılan, request-time API'nin her zaman resolve olduğu tek mod): route payload'ı doğrudan<script type="application/json">tag'i içine gömülür.external-json: yalnızca project-levelssr.payloadModeayarı üzerinden,lenty-ssrrunner tarafından kullanılabilir. Runner her route içinassetBaseUrlaltına<route-token>.payload.jsonyazar; HTML de inline body yerine<script src="...">referansı taşır.
export default defineLuisConfig({ ssr: { payloadMode: 'external-json' },})Yerleşik Guard Ayarları
Section titled “Yerleşik Guard Ayarları”SSR request helper'ları kendi dahili guard policy'si ile gelir; config üzerinden guardPolicy geçmezsiniz. Html tarama modu htmlGuardMode alanını izler ve varsayılan olarak strict 'ssr' allowlist'ini kullanır.
| Surface | Guard behavior |
|---|---|
renderLentySsrSnapshot() | preset: 'strict', htmlMode: htmlGuardMode (varsayılan 'ssr') |
createLentySsrIntegration().renderRequest() | preset: 'strict', htmlMode: htmlGuardMode (varsayılan 'ssr') |
createLentySsrFrameworkAdapter().render() | preset: 'strict', htmlMode: htmlGuardMode (varsayılan 'ssr') |
Kısa örnek:
import { renderLentySsrSnapshot } from '@lentystyle/ssr'
await renderLentySsrSnapshot({}, { routeId: '/docs/', html: '<html><head></head><body><div class="card"></div></body></html>', sources: [ { sourceId: 'docs.luis', source: '.card { color: #0f172a; }', }, ],})Ek guard config vermeseniz bile bu çağrı request envelope'u validate eder ve downstream hybrid compile adımında strict doğrulamayı korur.
HTML Injection Noktası
Section titled “HTML Injection Noktası”Injection sırasıyla şu konumları dener:
<!-- lenty-ssr -->placeholder — html bu comment'i içeriyorsa, üretilen tag'ler yerine yazılır (comment kaybolur; yalnız ilk eşleşme kullanılır)</head>— placeholder yoksa, tag'ler head close'un hemen önüne eklenir- prepend — ikisi de yoksa, tag'ler html'in en başına eklenir
<html> <head> <title>Docs</title> <!-- lenty-ssr --> </head> ...Production Cache Seçenekleri
Section titled “Production Cache Seçenekleri”createLentySsrProd() ve createLentySsrProdFromProjectConfig() aynı cache seçeneklerini kabul eder:
interface LentySsrProdOptions { maxEntries?: number // varsayılan 100, default in-memory store için geçerlidir ttlMs?: number // varsayılan undefined -> entry'ler kendiliğinden expire olmaz cacheStore?: LentySsrCacheStore<LentySsrProdRenderResult> // varsayılan: yerleşik in-memory store}Integration ayrıca cache yönetim metodları sunar:
await prod.invalidate(routeId) // yalnız o route'un cache entry'lerini unuturawait prod.clear() // her şeyi unutur (hit/miss sayaçları SIFIRLANMAZ)const stats = await prod.stats() // { hitCount, missCount, entryCount }Pluggable Cache Store
Section titled “Pluggable Cache Store”interface LentySsrCacheStore<TValue> { get: (key: string) => Promise<{ value: TValue; expiresAt: number | null } | undefined> set: (key: string, entry: { value: TValue; expiresAt: number | null }) => Promise<void> delete: (key: string) => Promise<void> clear: () => Promise<void> keys?: () => Promise<string[]> // opsiyonel; key enumerate edemeyen store'lar atlayabilir}Cache'i varsayılan process-local Map yerine Redis vb. paylaşılan bir store ile desteklemek için bunu implemente edin:
import { createLentySsrProd } from '@lentystyle/ssr'
const prod = createLentySsrProd({}, { ttlMs: 60_000, cacheStore: { async get(key) { /* ... */ }, async set(key, entry) { /* ... */ }, async delete(key) { /* ... */ }, async clear() { /* ... */ }, // keys() yok -> bu store için eviction ve kesin entryCount atlanır },}).luis Parse Cache
Section titled “.luis Parse Cache”Bu, yukarıdaki production result cache'inden ayrı, daha küçük bir cache — yalnızca .luis metninin tekrar parse edilmesini atlar, route başına CSS işini değil.
import { createLentySsrCompileCache, createLentySsrProd, getLentySsrCompileCacheStats } from '@lentystyle/ssr'
const compileCache = createLentySsrCompileCache({ maxEntries: 500 }) // varsayılan 500const prod = createLentySsrProd({}, { compileCache })
getLentySsrCompileCacheStats(compileCache) // { entryCount, maxEntries }.luissource içeriğinin hash'iyle key'lenir, bu yüzden her zaman doğrudur: aynı.luisdosyasını paylaşan iki farklı route tam olarak bir cache entry'si üretir- her route'un html'ine karşı observed-rule eşleştirmesi her render'da her zaman taze çalışır — cache asla eski veya eksik CSS'e yol açmaz, yalnızca değişmemiş
.luismetninin yeniden parse edilmesini atlar createLentySsrProd(),createLentySsrProdIntegration(),createLentySsrFromProjectConfig()vecreateLentySsrProdFromProjectConfig()compileCacheverilmediğinde otomatik olarak bir tane oluşturur- aynı örneği birden fazla integration'a vererek parse sonuçlarını aralarında paylaştırabilirsiniz
renderLentySsrSnapshot()ve diğer tek seferlik doğrudan çağrılar varsayılan olarak compile cache kullanmaz
Runtime Option Merge Sırası
Section titled “Runtime Option Merge Sırası”SSR içindeki runtime option merge sırası sabittir:
package defaults-> config.debug / performance / map / lazy / worker-> config.runtimeOptions-> source.runtimeOptionsTemel default'lar uygulanır
{debug: false,performance: false,map: false,lazy: false,worker: 'auto',}Top-level config flag'leri uygulanır
debug,performance,map,lazyveworkerbu aşamada uygulanır.config.runtimeOptionspatch'i uygulanırString veya object patch, top-level flag'leri override eder.
Source-level override uygulanır
input.sources[].runtimeOptions, config-level sonucu source bazında override eder.
String syntax
Section titled “String syntax”runtimeOptions: 'debug,performance,!worker'Sonuç:
{ debug: true, performance: true, map: false, lazy: false, worker: 'main',}Desteklenen token'lar:
debug,performance,map,lazy!debug,!performance,!map,!lazyworker->worker: 'worker'!worker->worker: 'main'
Source-level override örneği
Section titled “Source-level override örneği”const result = await renderLentySsrSnapshot( { runtimeOptions: 'debug,worker' }, { routeId: '/docs/', html, sources: [ { sourceId: 'docs.luis', source, runtimeOptions: '!debug,lazy,!worker', }, ], },)Bu source için final runtime options:
{ debug: false, performance: false, map: false, lazy: true, worker: 'main',}Request-level default ve source-level override birlikte
Section titled “Request-level default ve source-level override birlikte”Config:
const config = { runtimeOptions: 'debug,performance,worker',}Source:
const input = { routeId: '/docs/', html: '<html><head></head><body><div class="card"></div></body></html>', sources: [ { sourceId: 'docs.luis', source: '.card { color: #0f172a; }', runtimeOptions: '!debug,lazy,!worker', }, ],}Bu source için final runtime options:
{ debug: false, performance: true, map: false, lazy: true, worker: 'main',}luis.config.mjs İçindeki ssr Bloğu
Section titled “luis.config.mjs İçindeki ssr Bloğu”Project-level SSR config tipi LuisSsrProjectConfig'dir. LentySsrConfig alanlarını devralır ve preview veya project-level alanlar ekler.
import { defineLuisConfig } from '@lentystyle/core'
export default defineLuisConfig({ ssr: { mode: 'ssr', outDirName: 'dist-ssr', maxEntries: 100, defaultRuntimeOptions: '', include: ['docs/**', '**/*.html'], exclude: ['admin/**'], },})Ek project alanları
Section titled “Ek project alanları”| Field | Purpose | Default |
|---|---|---|
htmlDirName | Runner'ın okuduğu build edilmiş HTML girdi dizininin adı | 'dist' |
outDirName | Preview HTML kök dizininin adı | 'dist-ssr' |
maxEntries | Prod helper için app-level cache limiti | 100 |
defaultRuntimeOptions | Runner'ın otomatik keşfettiği ve config'te eşlenen route source'larına merge edilen varsayılan runtime option string'i | '' |
include | Dahil edilecek relative HTML path pattern'leri | [] |
exclude | Atlanacak relative HTML path pattern'leri | [] |
routes | Request-time renderRoute() için route-pattern -> .luis source eşlemeleri | [] |
payloadMode | Runner tarafından render edilen route'lar için payload taşıma modu ('inline-json' | 'external-json') | 'inline-json' |
routes girdileri { match, sourceDirs?, sources? } şeklindedir: match '/docs/**' gibi bir route id pattern'i (veya listesi), sourceDirs .luis dosyaları için taranacak dizinler, sources ise açık dosya listesidir — ikisi de config dizinine göredir. Tam request-time tarifleri için Framework'ler sayfasına bakın.
Project-level default örneği
Section titled “Project-level default örneği”import { defineLuisConfig } from '@lentystyle/core'
export default defineLuisConfig({ ssr: { mode: 'ssr', outDirName: 'dist-ssr', defaultRuntimeOptions: 'performance', include: ['docs/**'], },})Bu kurulumda defaultRuntimeOptions, auto-discovered source'lara ortak bir baseline verir. Bir source farklı davranmalıysa source-level runtimeOptions ile override edin.
Project Config Nasıl Yüklenir
Section titled “Project Config Nasıl Yüklenir”loadLuisSsrProjectConfig(configOrPath?, overrides?)
Section titled “loadLuisSsrProjectConfig(configOrPath?, overrides?)”import { loadLuisSsrProjectConfig } from '@lentystyle/ssr'
const config = await loadLuisSsrProjectConfig(undefined, { cwd: appDir })Bu helper:
luis.config.mjsdosyasını yüklerssrbloğunu okur- request-level config alanlarını çözümler
outDirName,maxEntries,includeveexcludegibi project-level default'ları uygular
Validation kuralları:
- config dosyası gerçek bir
ssrobject export etmiyorsa throw eder includeveexcludeverildiyse string array olmalıdıroutDirNameboş olamaz ve/ile\içeremez
Normalize edilmiş sonuç
Section titled “Normalize edilmiş sonuç”{ configPath: '.../luis.config.mjs', configDir: '.../apps/site', outDirName: 'dist-ssr', outDir: '.../apps/site/dist-ssr', maxEntries: 100, defaultRuntimeOptions: '', include: [], exclude: [], runtimeOptions: { debug: false, performance: false, map: false, lazy: false, worker: 'auto', },}include ve exclude Nasıl Çalışır
Section titled “include ve exclude Nasıl Çalışır”shouldProcessLuisSsrProjectHtmlFile(htmlFilePath, config) üretilen HTML yolunu config.outDir altındaki relative path'e çevirir ve pattern match yapar.
import { loadLuisSsrProjectConfig, shouldProcessLuisSsrProjectHtmlFile,} from '@lentystyle/ssr'
const config = await loadLuisSsrProjectConfig(undefined, { cwd: appDir })
shouldProcessLuisSsrProjectHtmlFile( `${appDir}/dist-ssr/docs/index.html`, config,)Match kuralları:
includeboşsa dosya varsayılan olarak dahil edilirincludeboş değilse en az bir pattern eşleşmelidir- sonra
excludeeşleşirse dosya reddedilir
ssr: { include: ['docs/**', 'blog/**'], exclude: ['blog/drafts/**'],}| Relative path | Decision |
|---|---|
docs/index.html | işlenir |
blog/post-1/index.html | işlenir |
blog/drafts/demo/index.html | atlanır |
admin/index.html | atlanır |
Desteklenen küçük-glob davranışı:
***?
Path normalization her zaman / kullanır.
Bilinmesi Gereken Sınırlar
Section titled “Bilinmesi Gereken Sınırlar”adapterverewritePolicy0.2.0'da deprecate edildi ve ignore edilir- request-time
LentySsrConfigher zamanoutput.payloadMode'u'inline-json''a resolve eder;'external-json'yalnız project-levelssr.payloadModeayarı üzerinden (runner-only) erişilebilir - browser runtime'ın
external-jsonpayload dosyalarını fetch edip boot etmesi henüz uygulanmadı defaultRuntimeOptionslenty-ssrrunner tarafından vessr.routes'tanrenderRoute()tarafından otomatik uygulanır; low-level render API bunu doğrudan okumazincludeveexcludeyalnızca generated HTML relative path'lerine göre karar verir; source discovery runner'a aittirmaxEntrieseviction ve kesinstats().entryCountcache store'unkeys()desteklemesini gerektirir; desteklemeyen custom store'lar (örn. bazı remote cache'ler) ikisini de atlar