localStorage
- Origin (domain) başına ~5-10 MB
- Sayfayı kapatsan bile kalır
- Sadece string saklar
localStorage.setItem("theme", "dark");
const theme = localStorage.getItem("theme");
localStorage.removeItem("theme");
localStorage.clear();Obje saklamak
const user = { id: 1, name: "F" };
localStorage.setItem("user", JSON.stringify(user));
const stored = JSON.parse(localStorage.getItem("user") ?? "null");Storage event
Aynı origin'in başka sekmesinde değişiklik olduğunda tetiklenir:
window.addEventListener("storage", (e) => {
console.log(e.key, e.oldValue, e.newValue);
});Sekmeler arası senkronizasyon için.
sessionStorage
localStorage ile aynı API. Tek fark: sekme/pencere kapanınca silinir.
sessionStorage.setItem("temp", "x");Geçici state için (form draft, çok adımlı wizard).
Cookie
Eski. HTTP isteklerinde otomatik gönderilir, server'a ulaşır.
document.cookie = "theme=dark; max-age=86400; path=/; SameSite=Lax";
// Okumak — manuel parse
function getCookie(name) {
return document.cookie
.split("; ")
.find((row) => row.startsWith(name + "="))
?.split("=")[1];
}Önemli flagler
HttpOnly— JS erişemez, sadece HTTP başlığı (XSS koruma)Secure— sadece HTTPSSameSite=Strict|Lax|None— CSRF korumamax-ageveyaexpires— yaşam süresipath,domain— kapsam
JS ile HttpOnly cookie ayarlayamazsın → server kursun.
Hangisi ne zaman?
| İhtiyaç | Tercih |
|---|---|
| Auth token | HttpOnly cookie (server-side set) |
| Tema, dil tercihi | localStorage |
| Form draft (sekmeye özel) | sessionStorage |
| Server'a her istekte gitsin | cookie |
| Hassas veri | hiçbiri — server'da tut |
IndexedDB
5 MB sınırını aşan, yapılandırılmış veri için. API karmaşık —
idb-keyval gibi bir wrapper
kullan:
import { set, get } from "idb-keyval";
await set("user", { id: 1, name: "F" });
const u = await get("user");Offline uygulamalar, büyük cache, dosya saklama için.
Güvenlik notları
- Asla parola, kredi kartı veya hassas veriyi
localStorage'da tutma. XSS açığı olunca her şey çalınabilir. - Auth için HttpOnly cookie + CSRF token.
localStoragefarklı sekmeler arasında paylaşılır ama farklı origin'lere kapalı.
Gerçek uygulamada localStorage erişimini bir wrapper'a koy:
const storage = {
get(key, fallback = null) {
try { return JSON.parse(localStorage.getItem(key)) ?? fallback; }
catch { return fallback; }
},
set(key, value) { localStorage.setItem(key, JSON.stringify(value)); },
};Quota dolması, JSON parse hatası gibi durumları tek yerde halledersin.