- URL yapısı, basit bir adres olmanın ötesinde uygulama durumunu saklama ve geri yükleme aracı olarak çalışır
- PrismJS indirme sayfası gibi, tek bir URL ile tema, dil ve eklenti ayarlarının tamamen yeniden üretilebildiği bir örnek sunulur
- Yol, sorgu parametreleri, fragment gibi her bileşen; hiyerarşik gezinme, filtreleme ve istemci tarafı navigasyon gibi farklı durumları ifade eder
- Arama filtreleri, sayfalama, görünüm modu, tarih aralığı gibi durumlar URL'ye eklemek için uygundur; hassas bilgiler veya geçici UI durumu ise uygun değildir
- İyi tasarlanmış URL'ler paylaşılabilirliği, öngörülebilirliği ve önbellekleme verimliliğini artırır; web uygulamalarının güvenilirliğini ve kullanıcı deneyimini güçlendirir
URL'nin potansiyeli
- URL, yalnızca basit bir kaynak adresi değil, aynı zamanda bir kullanıcı arayüzü (UI) ve bir durum kapsayıcısı olarak işlev görür
- Paylaşım, yer imleri, tarayıcı geçmişi ve derin bağlantılar gibi senaryolarda durumu otomatik olarak korur
- 1991'den beri web'in temel durum yönetimi mekanizması olarak çalışır
- URL'nin her bileşeni farklı türde durumları ifade eder
- Yol (Path): hiyerarşik kaynak gezintisi (
/users/123/posts)
- Sorgu (Query): filtreler, seçenekler ve ayarlar (
?theme=dark&lang=en)
- Fragment: belge içi konum veya SPA yönlendirmesi (
#features, #/dashboard)
- Text Fragments özelliği, sayfa içindeki belirli bir metne doğrudan bağlantı verilmesini sağlar
Sorgu parametresi kalıpları
- Birden fazla değeri tek anahtarda tutmak için ayırıcı (delimiter) kullanımı (
?tags=frontend,react,hooks)
- İç içe veriyi JSON veya Base64 ile serileştirme (
?config=eyJyaWNrIjoicm9sbCJ9==)
- Boolean flag değerlerini anahtarın varlığıyla ifade etme (
?mobile)
- Dizi gösterimi (bracket notation),
tags[]=frontend&tags[]=react biçiminde çoklu değerleri ifade eder
- Node'daki
qs veya Express middleware'leri tarafından otomatik olarak tanınır, ancak standartlaştırılmış değildir
- Esas olan tutarlılığı korumaktır
URL üzerinden durum ifade etme örnekleri
- PrismJS: tema, dil ve eklenti ayarlarının tamamını URL hash'i içinde saklar
- GitHub:
#L108-L136 ile belirli kod satırı aralığını vurgular
- Google Maps: koordinatları, yakınlaştırma seviyesini ve harita türünü URL'ye dahil eder
- Figma: canvas konumu, zoom ve seçili öğeler gibi çalışma bağlamını URL ile paylaşır
- E-ticaret siteleri: filtreleri, sıralamayı ve fiyat aralığını URL'ye ekleyerek arama durumunu geri yükler
Frontend mühendisliği kalıpları
- URL'ye eklenmesi uygun durumlar
- Arama terimi, filtreler, sayfa ve sıralama, görünüm modu, tarih aralığı, aktif sekme, UI yapılandırması, özellik bayrakları
- URL için uygun olmayan durumlar
- Parola, token gibi hassas bilgiler; geçici UI durumu; kaydedilmemiş giriş; büyük hacimli veri; yüksek frekanslı durumlar
- Karar ölçütü: Başka bir kullanıcı aynı URL'ye tıkladığında aynı durumu görmeli mi?
JavaScript uygulaması
URLSearchParams API'si ile sorgu parametreleri okunup yazılabilir
pushState yeni bir geçmiş girdisi ekler, replaceState mevcut girdiyi günceller
popstate olayı ile tarayıcıda geri gidildiğinde UI geri yüklenebilir
React uygulaması
- React Router'ın
useSearchParams hook'u ile URL durumu kısa ve net biçimde yönetilebilir
- Parametreler okunup güncellendiğinde URL ve UI otomatik olarak senkronize edilir
URL durum yönetimi için iyi uygulamalar
- Varsayılan değerleri URL'ye eklemeyin (
?theme=dark kalsın, varsayılan değerler kodda ele alınsın)
- Yazı yazarken URL'nin aşırı güncellenmesini önlemek için debounce kullanın (
lodash.debounce yararlanılabilir)
- pushState vs replaceState
pushState: filtre değişikliği, sayfa geçişi gibi geri alınabilir durumlar
replaceState: arama girdisi gibi ince ayarlı değişiklikler
URL'yi bir sözleşme (Contract) olarak görmek
- İyi tasarlanmış URL'ler, uygulama ile kullanıcı arasındaki açık sözleşme işlevini görür
- Açık/gizli, istemci/sunucu, paylaşılan/oturum durumu arasındaki sınırları netleştirir
- Okunabilir URL'ler niyeti açıklar ve hem insanlar hem makineler tarafından anlaşılabilir
example.com/products/laptop?color=silver&sort=price biçimi anlam aktarmada avantajlıdır
- Önbellekleme verimliliğini artırır
- Aynı URL aynı kaynak olarak kabul edilir ve cache hit oranı yükselir
- Sorgu parametreleri ile önbellek varyasyonları kontrol edilebilir
- Sürüm yönetimi ve deneyler
?v=2, ?beta=true, ?experiment=new-ui ile API sürümleri ve A/B testleri ayrıştırılabilir
Kaçınılması gereken anti-pattern'ler
- SPA içinde durumu yalnızca bellekte tutmak, böylece sayfa yenilendiğinde durumun kaybolması
- Hassas bilgileri URL'ye koymak (
?password=secret123)
- Belirsiz parametre adları kullanmak (
?foo=true&bar=2 yerine ?mobile=true&page=2)
- Karmaşık JSON'u Base64 ile kodlayıp aşırı uzun URL'ler üretmek
- URL uzunluk sınırını aşmak (tarayıcı, sunucu ve CDN kısıtları vardır)
- Geri düğmesini etkisizleştirmek (
replaceState aşırı kullanıldığında ortaya çıkar)
Sonuç
- İyi bir URL, yalnızca içeriği işaret etmenin ötesinde, kullanıcı ile uygulama arasındaki diyaloğu ifade eder
- URL, niyet, bağlam ve paylaşılabilirlik taşıyan en eski ve en zarif durum yönetimi araçlarından biridir
- Redux, MobX, Zustand, Recoil gibi karmaşık durum yönetimi araçları olsa da,
URL gibi temel bir özelliği unutmamak gerçek web'in gücüdür
- Sayfa yenilendiğinde durum kaybeden uygulamalar, web'in özündeki temel niteliği kaçırıyor
2 yorum
Hacker News görüşleri
Kod incelemesi sırasında mümkün olduğunca fazla durumu (state) URL'de tutmaya çalışıyorum
Yeniledikten sonra tamamen farklı bir konuma gitmek ya da paylaşılan URL'nin alakasız bir ekran göstermesi kullanıcı açısından aşağılayıcıdır
Bu yaklaşım geliştirme hızını düşürüyor, ama ekip içinde UX farkındalığını artırıyor ve görünümde ne kadar durum taşıdığımızı daha net görmemizi sağlıyor
URL'nin bir tür kamusal API haline gelerek kısıt oluşturacağı endişesi de var, ancak çoğu URL yalnızca kısa vadede kullanıldığı için bunun büyük bir sorun olmadığını düşünüyorum
Gerekirse yükleme sırasında eski URL'yi yeni URL'ye migrate eden kodla çözülebilir
Yol (path) yerine query parametreleri kullanmanın biraz daha iyi olduğunu düşünüyorum
Kullanıcı açısından “geri” kelimesi tarayıcı düğmesiyle bağlantılı olduğu için kafa karıştırıcı
Yenilemenin durumu sıfırlaması daha az sinir bozucu. Çünkü “yenile = baştan başla” şeklinde bir algı var
Her şeyi JS ile yapınca bu tür varsayılan özellikler hafifçe bozuluyor
Ama şimdiye kadar 30'dan fazla UX tasarımcısıyla çalıştım, yine de URL'lerle ilgili hiç rehberlik almadım
Özellikle mobilde sayfayı ilk durumuna döndürmek zor olduğu için yenileme en hızlı çözüm haline geliyor
Sonsuz kaydırma ya da karmaşık filtre arayüzlerinde URL'de ne kadar çok durum varsa sıfırlamak da o kadar zahmetli oluyor
Zaten UX'ten memnun olunmayan bir durumda bir de URL'yi toparlamak gerekiyorsa bu kullanıcı için çifte stres demek
Dijital okuryazarlığı yüksek kişilerde bile URL ve DNS anlayışının zayıf olduğunu düşünüyorum
Kimlik avı riskini azaltmak, URL parametrelerinin (
?t=_,utm_) ne anlama geldiğini anlamak ve paylaşmadan önce kişisel bilgileri temizleyebilmek gerekiyorHTTPS kilidinin ‘güven’ anlamına gelmediğini de bilmek lazım
URL'yi durum kapsayıcısı olarak kullanınca iç yapı açığa çıkıyor ve sürümleme ihtiyacı doğuyor
Tarayıcılar arası uyumlulukta ya da kimlik doğrulama akışlarında da sorun çıkabiliyor
Yine de komut satırı argümanlarında olduğu gibi mümkün olduğunca fazla durumu URL'de görünür kılmaya çalışıyorum
Ama bu bilinçli bir trade-off; cehalet ya da deneyim eksikliği değil
Eski bir kütüphane olsa da hâlâ faydalı olan Rison'ı öneriyorum
JSON'u URL'de temiz biçimde saklayabiliyor ve Elastic'in Kibana'sında da kullanılıyor
Örnek: http://example.com/service?query=q:'*',start:10,count:10
Sistem geliştikçe durum yapısı da değişir, bu yüzden durumu URL'ye koymak evrimi kısıtlar
Çünkü URL temelde kalıcı bir string'dir
Bunun yerine URL'yi bir tür protokol gibi görüp, durumu encode/decode etmenin daha uygun olduğunu düşünüyorum
Basit bir sayfadaysa tüm durumu URL'ye koymak da mümkün
Ama feed gibi yerlerde “yenileyince en güncel duruma mı dönmeli?” gibi kullanıcı beklentilerine göre değişir
URL uzunluğu sınırı tarayıcı, sunucu, CDN ve arama motoru ayarlarına göre değişiyor ama genelde 2000 karakterin altında oluyor
Bu sınır içinde ne kadar durum taşınabileceğini ya da başka bir yaklaşım gerekip gerekmediğini düşünüyorum
- . _ ~özel karakterleri) kullanılabildiği için bilgi yoğunluğu oldukça yüksekdraw.io tüm durumu URL'de saklayıp paylaşabiliyor
Diyagram verisi Base64 ile encode ediliyor ve tek bir bağlantıyla tamamen geri yüklenebiliyor
Yine de bunun ‘state container’ tanımına gerçekten uyup uymadığından emin değilim
Ben self-hosted uygulamalarda hash routing (#/dashboard) kullanıyorum
Sunucu tarafı URL yeniden yazımı (.htaccess vb.) gerektirmediği için kusursuz olmasa da dağıtım ortamı kısıtlarını azaltabiliyor
Güncel Microsoft Teams'te tüm ekranlar tek bir URL ile işlendiği için yer imi eklenemiyor
Belirli bir takımı ya da kanalı doğrudan açamamak çok rahatsız edici
HATEOAS ismi kötü olduğu için ilgi görmüyor ama sonuçta web'in temel kavramlarından biri
Ama hem sunucuyu hem istemciyi kontrol ettiğiniz ortamlarda yalnızca ek karmaşıklık yaratır
Özellikle istemci hâlâ endpoint yapısını bilmek zorundaysa URL'yi sadece opak hale getirir
Sekme uyutma özelliğini sık kullanıyorum; ama URL’yi sabitleyip tek parça halinde çalışan web uygulamalarında uykuya girince bilgiler kayboluyor.
Ama öte yandan böyle web sayfalarının hepsi birden ağır olduğu için uyutmayı kapatmak da olmuyor.