jskelet 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +2 -0
- package/docs/02-mimari.md +1 -0
- package/docs/04-render-ve-sablonlar.md +9 -3
- package/docs/06-cache.md +53 -9
- package/docs/07-yapilandirma.md +1208 -1191
- package/docs/08-build.md +2 -1
- package/docs/10-dagitim.md +16 -6
- package/docs/12-panel-ve-oturum.md +2 -1
- package/docs/en/02-architecture.md +2 -1
- package/docs/en/04-rendering.md +9 -3
- package/docs/en/06-caching.md +54 -9
- package/docs/en/07-configuration.md +24 -9
- package/docs/en/08-build.md +2 -1
- package/docs/en/10-deployment.md +17 -6
- package/docs/en/12-dashboards-and-sessions.md +2 -1
- package/package.json +1 -1
- package/src/config/defaults.js +541 -518
- package/src/config/index.js +1500 -1456
- package/src/init.mjs +2 -0
- package/src/server/cache-blob.js +70 -0
- package/src/server/cache-control.js +45 -0
- package/src/server/data-cache.js +118 -27
- package/src/server/disk-cache.js +233 -0
- package/src/server/html-cache.js +90 -16
- package/src/server/image-optimizer.js +95 -2
- package/src/server/logs/file-sink.js +159 -32
- package/src/server/logs/pipeline.js +10 -3
- package/src/server/middleware/static-precompressed.js +31 -10
- package/src/server/og-image.js +17 -4
- package/src/server/prewarm.js +25 -1
- package/src/server/redis.js +31 -12
- package/src/server/render.js +910 -910
- package/types/config/defaults.d.ts +21 -1
- package/types/config/index.d.ts +14 -0
- package/types/server/cache-blob.d.ts +13 -0
- package/types/server/cache-control.d.ts +28 -0
- package/types/server/data-cache.d.ts +9 -0
- package/types/server/disk-cache.d.ts +36 -0
- package/types/server/html-cache.d.ts +26 -3
- package/types/server/logs/file-sink.d.ts +16 -5
- package/types/server/og-image.d.ts +5 -0
- package/types/server/redis.d.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,24 @@ one is listed under a **Breaking** heading.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Shared cache entries of 1 KB or more are stored as brotli (`JSK\x01`
|
|
14
|
+
prefix) instead of plain JSON. With Redis off, the same body is written
|
|
15
|
+
under `.jskelet/cache/<buildId>/` so a restart can skip the render. The
|
|
16
|
+
in-process cache is unchanged, smaller records stay JSON, and existing
|
|
17
|
+
plain JSON values are still read.
|
|
18
|
+
- Early HTML refresh no longer marks every due page in one second. A pass
|
|
19
|
+
soft-stales at most four entries (soonest expiry first), and the expiry
|
|
20
|
+
warmer refetches them at one request at a time, two per second, instead of
|
|
21
|
+
the classic prewarm rate.
|
|
22
|
+
- The data cache stops growing past 64 MB of stored JSON. A single value
|
|
23
|
+
larger than that is not stored; the caller still receives it. HTML cache
|
|
24
|
+
entries keep the raw body plus only the compressed encoding last requested.
|
|
25
|
+
- In production, precompressed asset `stat` results (hit or miss) stay in
|
|
26
|
+
memory for the process lifetime. The remote image disk cache drops the
|
|
27
|
+
oldest file once `.jskelet/image-cache/` passes 256 MB.
|
|
28
|
+
|
|
11
29
|
### Added
|
|
12
30
|
|
|
13
31
|
- `robots.txt` responses gain a trailing JSkelet note that disallows framework
|
|
@@ -18,6 +36,20 @@ one is listed under a **Breaking** heading.
|
|
|
18
36
|
|
|
19
37
|
### Breaking
|
|
20
38
|
|
|
39
|
+
- HTML edge headers
|
|
40
|
+
Cacheable HTML and OG images no longer send `s-maxage`. `route()` writes
|
|
41
|
+
`Cache-Control: public, max-age=0` and
|
|
42
|
+
`CDN-Cache-Control: max-age=<html ttl>, stale-while-revalidate=<cache().staleWhileRevalidate>`
|
|
43
|
+
(default 60; `0` omits the directive). OG images keep their own durations
|
|
44
|
+
(86400 / 604800) on `CDN-Cache-Control`. A layer that only reads
|
|
45
|
+
`Cache-Control` / `s-maxage` (nginx `proxy_cache`) no longer caches this
|
|
46
|
+
HTML. Cloudflare reads `CDN-Cache-Control`.
|
|
47
|
+
- File logs are no longer daily plain-text files. With `logs.file.enabled`,
|
|
48
|
+
lines are sealed as zstd chunks (`jskelet-<time>-<n>.ndjson.zst`) and kept
|
|
49
|
+
for at most 5 minutes; the oldest expired chunk is deleted. `logs.drainLog`
|
|
50
|
+
receives each sealed chunk (`{ body, encoding: "zstd", bytes, lines, at }`)
|
|
51
|
+
so the app can forward it. A throwing hook warns and leaves the site up.
|
|
52
|
+
With the file sink off, `drainLog` still runs and nothing is written to disk.
|
|
21
53
|
- Dev gate is opt-in
|
|
22
54
|
`DEV_TOKEN` in the environment no longer locks the site. Require the token
|
|
23
55
|
only with `devGate: true` or `DEV_GATE=1`. `DEV_GATE=0` turns the gate off
|
package/README.md
CHANGED
|
@@ -257,6 +257,8 @@ export default {
|
|
|
257
257
|
async cache() {
|
|
258
258
|
return {
|
|
259
259
|
html: { "/": 3600, "/pricing": 3600 },
|
|
260
|
+
// Edge stale window after the HTML TTL. 0 omits the directive.
|
|
261
|
+
staleWhileRevalidate: 60,
|
|
260
262
|
query: { "/search": ["q"] }, // only these params enter the cache key
|
|
261
263
|
prewarm: { enabled: true, max: 50, concurrency: 4 },
|
|
262
264
|
// redis: { enabled: true, url: process.env.REDIS_URL },
|
package/docs/02-mimari.md
CHANGED
|
@@ -80,6 +80,7 @@ sebebi var ve yer değiştirmek sessiz bozulmalara yol açıyor.
|
|
|
80
80
|
`.br`/`.gz` kopyalar varsa onlar servis edilir (brotli kalite 11); yoksa
|
|
81
81
|
istek altındaki `static`e düşer ve middleware anında sıkıştırır (kalite 5).
|
|
82
82
|
Hash'li ve `immutable` bir dosyayı her istekte yeniden sıkıştırmak boşa CPU.
|
|
83
|
+
Üretimde `stat` sonucu (var ya da yok) süreç belleğinde kalır; dev'de kalmaz.
|
|
83
84
|
- **Admin paneli** (açıksa, `admin().enabled` / `JSKELET_ADMIN`): statikten
|
|
84
85
|
sonra, body parser ve route'lardan önce. Kendi gövde ayrıştırıcısını taşır;
|
|
85
86
|
uygulama aynı yolu gölgeleyemez. Kapalıyken modül yüklenmez.
|
|
@@ -582,9 +582,15 @@ app.get("/og/custom.png", async (req, res) => {
|
|
|
582
582
|
});
|
|
583
583
|
```
|
|
584
584
|
|
|
585
|
-
Varsayılan
|
|
586
|
-
|
|
587
|
-
|
|
585
|
+
Varsayılan başlıklar (süreler HTML ayarına bağlı değildir):
|
|
586
|
+
|
|
587
|
+
```
|
|
588
|
+
Cache-Control: public, max-age=0
|
|
589
|
+
CDN-Cache-Control: max-age=86400, stale-while-revalidate=604800
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
`cacheControl` seçeneği `Cache-Control`'ü ezer; bu durumda `CDN-Cache-Control`
|
|
593
|
+
yazılmaz. Çalışan örnek: `examples/blog/routes/35-og.mjs`.
|
|
588
594
|
|
|
589
595
|
## Hook'lar
|
|
590
596
|
|
package/docs/06-cache.md
CHANGED
|
@@ -85,6 +85,9 @@ export default {
|
|
|
85
85
|
"/haber/:slug": 300,
|
|
86
86
|
"/etiket/:slug": 120,
|
|
87
87
|
},
|
|
88
|
+
// Edge'in taze penceresi bittikten sonra eski HTML'i sunacağı süre.
|
|
89
|
+
// 0 yazılırsa direktif hiç basılmaz.
|
|
90
|
+
staleWhileRevalidate: 60,
|
|
88
91
|
};
|
|
89
92
|
},
|
|
90
93
|
};
|
|
@@ -206,9 +209,11 @@ leadMs = min(max(produceMs * 2, 250ms), ttl / 2)
|
|
|
206
209
|
|
|
207
210
|
Böylece yavaş bir sayfa TTL dolduğu anda hâlâ soğuk render'a düşmez: taze
|
|
208
211
|
HTML çoğu zaman `expiresAt` gelmeden yazılmış olur. Trafik yoksa bir sweeper
|
|
209
|
-
aynı pencerede girdiyi soft-bayatlatır ve ısıtma kuyruğuna alır
|
|
210
|
-
|
|
211
|
-
|
|
212
|
+
aynı pencerede girdiyi soft-bayatlatır ve ısıtma kuyruğuna alır. Bir tur en
|
|
213
|
+
fazla dört girdi işaretler (süresi en yakın dolacak olan önce); kalanlar
|
|
214
|
+
sonraki saniyelere kalır. `startPrewarm` (`PREWARM=0` değilse) kuyruğu HTTP
|
|
215
|
+
ile boşaltır — klasik `prewarmPaths` olmasa da — ama bu boşaltma klasik turun
|
|
216
|
+
`rps: 0` ayarını kullanmaz: aynı anda tek istek, saniyede en fazla iki.
|
|
212
217
|
|
|
213
218
|
Stale penceresinde tazelemenin hatası isteği etkilemez: eski HTML pencere
|
|
214
219
|
boyunca geçerli kalır ve hata yalnızca loglanır
|
|
@@ -225,7 +230,9 @@ güncelleniyor.
|
|
|
225
230
|
Store LRU'dur: erişilen girdi sona taşınır, sınır (`cache().maxEntries`,
|
|
226
231
|
varsayılan 500) aşılınca en eski düşürülür. Config 500'ün üstünü isteyebilir;
|
|
227
232
|
**800'ü geçemez** — daha yükseği uyarıyla 800'e çekilir. Bunun yanında süreç
|
|
228
|
-
içi HTML string + sıkıştırılmış gövde **256 MB**'yi geçemez.
|
|
233
|
+
içi HTML string + sıkıştırılmış gövde **256 MB**'yi geçemez. Sıkıştırılmış
|
|
234
|
+
kopya tektir: brotli veya gzip, hangisi son istendiyse. Ham HTML durur.
|
|
235
|
+
Sayı tavanının
|
|
229
236
|
altında kalan şişman sayfa veya `vary.host` kopyası da bu bütçede LRU ile
|
|
230
237
|
düşer. Tek sayfa 256 MB'den büyükse saklanmaz; yanıt o istekte yine gider.
|
|
231
238
|
|
|
@@ -254,12 +261,33 @@ ile değiştirilebilir):
|
|
|
254
261
|
Önbelleklenebilir yanıtlarda ayrıca:
|
|
255
262
|
|
|
256
263
|
```
|
|
257
|
-
Cache-Control: public, max-age=0
|
|
264
|
+
Cache-Control: public, max-age=0
|
|
265
|
+
CDN-Cache-Control: max-age=<html ttl>, stale-while-revalidate=<staleWhileRevalidate>
|
|
258
266
|
```
|
|
259
267
|
|
|
260
|
-
`max-age=0` tarayıcıda saklamayı kapatır
|
|
261
|
-
|
|
262
|
-
|
|
268
|
+
`max-age=0` tarayıcıda saklamayı kapatır. Edge süresi `Cache-Control` içine
|
|
269
|
+
yazılmaz: `s-maxage`, Cloudflare'da `max-age=0` ile birlikte `EXPIRED` üretir.
|
|
270
|
+
Süre `CDN-Cache-Control` üzerindeki `max-age` olur ve mevcut HTML TTL'dir
|
|
271
|
+
(`cache().html` ya da route'un `revalidate` değeri). `s-maxage` hiç yazılmaz;
|
|
272
|
+
ona dönen bir anahtar da yoktur.
|
|
273
|
+
|
|
274
|
+
`stale-while-revalidate`, edge'in taze penceresi bittikten sonra eski HTML'i
|
|
275
|
+
sunacağı süredir. `cache().staleWhileRevalidate` ile gelir; varsayılan `60`.
|
|
276
|
+
`0` yazılırsa direktif hiç basılmaz:
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
CDN-Cache-Control: max-age=<html ttl>
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
`must-revalidate`, `proxy-revalidate` ve `no-cache` aynı yanıtta yoktur; bu
|
|
283
|
+
direktifler stale penceresini keser.
|
|
284
|
+
|
|
285
|
+
`X-JSkelet-Cache: STALE` süreç içi HTML önbelleğinin katmanıdır. Edge
|
|
286
|
+
başlığındaki stale penceresinden bağımsızdır.
|
|
287
|
+
|
|
288
|
+
Yalnızca `Cache-Control` / `s-maxage` okuyan bir ara katman (nginx
|
|
289
|
+
`proxy_cache`) bu HTML'i artık önbelleklemez. Cloudflare `CDN-Cache-Control`
|
|
290
|
+
okur.
|
|
263
291
|
|
|
264
292
|
## Sıkıştırılmış gövdenin saklanması
|
|
265
293
|
|
|
@@ -369,6 +397,9 @@ Ayrıntılar:
|
|
|
369
397
|
yazılır (`haber:tr:v2:${slug}`).
|
|
370
398
|
- TTL `0` verildiğinde önbellek devre dışı kalır ve `producer` her çağrıda
|
|
371
399
|
çalışır — bir ayarı geçici olarak kapatmak için yeterli.
|
|
400
|
+
- **Bayt tavanı 64 MB.** Sayı sınırı şişman JSON'u tutmaz; süreç içi gövdeler
|
|
401
|
+
bu tavanı geçemez ve config yükseltemez. Tek değer tavanı aşıyorsa saklanmaz,
|
|
402
|
+
çağıran sonucu yine alır. Tahliye en eski girdiden olur.
|
|
372
403
|
|
|
373
404
|
Yönetim yüzeyi:
|
|
374
405
|
|
|
@@ -517,7 +548,7 @@ baştan render etmek olur — içerik yine aynı eksik hâliyle döner, ziyaret
|
|
|
517
548
|
sadece render süresini öder.
|
|
518
549
|
|
|
519
550
|
Eksik veriyle üretilen çıktı **paylaşılan önbelleklere de sunulmaz**: `degraded`
|
|
520
|
-
bir yanıt `
|
|
551
|
+
bir yanıt `CDN-Cache-Control` değil `private, no-store` alır. Süreç içi
|
|
521
552
|
önbelleğe yazmama kararını CDN'de geri almak, aynı hatayı bir katman yukarıda
|
|
522
553
|
tekrarlamak olurdu. Teşhis başlığı (`X-JSkelet-Cache: MISS`) yine yazılır.
|
|
523
554
|
|
|
@@ -835,6 +866,19 @@ anahtarlar TTL ile ölür — elle temizlik ya da `FLUSHDB` gerekmez. Build
|
|
|
835
866
|
bilinçli olarak `buildId` **taşımaz**: deploy sırasında eski ve yeni sürüm yan
|
|
836
867
|
yana koşuyor ve bir purge ikisine de ulaşmalı.
|
|
837
868
|
|
|
869
|
+
1 KB ve üstü HTML ve veri girdileri düz JSON olarak durmaz: `JSK\x01` önekli
|
|
870
|
+
brotli gövde yazılır (kalite 5, metin modu — yanıt sıkıştırmasıyla aynı ayar).
|
|
871
|
+
L1 yine çözülmüş nesne tutar; sıkıştırma yalnızca L1 miss'ten sonraki
|
|
872
|
+
paylaşımda, yanıtı bekletmeden çalışır. Daha küçük kayıtlar düz JSON kalır,
|
|
873
|
+
eski düz JSON kayıtlar da okunur. zstd kullanılmaz: `node:zlib` içindeki zstd
|
|
874
|
+
22.15'ten itibaren var, motor ise `>=22`.
|
|
875
|
+
|
|
876
|
+
Redis kapalıyken (ya da bağlanamadığında) aynı gövde `.jskelet/cache/<buildId>/`
|
|
877
|
+
altına dosya olarak yazılır. Süreç yeniden açılınca L1 boştur ama diskteki
|
|
878
|
+
taze kopya render'ı atlatır. Bu tek makine içindir: birden fazla instance aynı
|
|
879
|
+
dizini paylaşmaz, küme için Redis durur. Yeni bir `buildId` eskisinin dizinini
|
|
880
|
+
bir sonraki yazışta siler. `clearHtmlCache()` ve invalidation dosyayı da düşürür.
|
|
881
|
+
|
|
838
882
|
### Bilmeniz gereken takaslar
|
|
839
883
|
|
|
840
884
|
- **Kişiye özel çıktı paylaşılmaz.** `storable: false` işaretlenen bir render
|