1 puan yazan GN⁺ 4 시간 전 | 1 yorum | WhatsApp'ta paylaş
  • Go’nun html/template tabanlı sunucu tarafı render yapısını korurken HTMX ile dinamik etkileşimler ekler ve tek bir renderer üzerinden tam sayfa ile HTML parçalarını seçmeli olarak döndürür
  • İşaretlemeyi base.tmpl, sayfa şablonları ve yeniden kullanılabilir parçalara ayırır; Go 1.16’nın embed.FS yapısını ve paylaşılan şablon kümesini kullanarak dağıtım ve render yapısını sadeleştirir
  • HX-Request durumuna göre arama sonuçlarını tam sayfa ya da tablo satırları olarak döndürür; Vary: HX-Request ve historyRestoreAsHxRequest: false ile önbellek ve geri gitme geri yükleme hatalarını önler
  • HTMX isteklerini başka bir sayfaya yönlendirirken normal 3xx yerine HX-Redirect ve 2xx yanıtı kullanır; 204·422·4xx·5xx için responseHandling ile değiştirme kapsamını ve hata gösterimini kontrol eder
  • Yerel depolama önbelleğini ve öznitelik kalıtımını kapatıp istek zaman aşımını ayarlayan yapılandırmayı başlangıç noktası olarak alır; ölçek büyüdüğünde yönetim alanı gibi ayrı ekran düzenlerini desteklemek için ara layout şablonları eklenebilir

Go’nun sunucu tarafı render yapısını HTMX ile birleştirme nedeni

  • HTMX, çok az JavaScript ile dinamik etkileşimler eklerken Go html/template yapısının sağladığı sunucu tarafı HTML render tutarlılığını ve güvenliğini korumayı sağlar
  • Uygulamanın ele aldığı üç eksen vardır
    • Tam sayfa ve kısmi HTML yanıtlarını birlikte destekleyen şablon yapısı
    • HTMX ortamında yönlendirme ve hata işleme
    • HTMX varsayılanlarını değiştiren yapılandırma ve bunun nedenleri
  • Düğmeyi bir görselle değiştiren temel işlevden başlayıp, kullanıcı adı veya e-posta girilirken listeyi filtreleyen bir arama ekranına doğru genişler
  • Aynı şablon deseni yalnızca HTMX için değil, Unpoly ve Hotwire gibi HTML-over-the-wire araçları için de uygulanabilir
  • HTMX’in temel kullanımını bilmiyorsanız önce resmi dokümantasyona bakmak daha uygundur

Proje dizini ve statik dosya yapısı

  • Proje, rolüne göre aşağıdaki alanlara ayrılır
    • assets/html/base.tmpl: tüm sayfaların paylaştığı HTML iskeleti
    • assets/html/pages/: sayfaya özgü içerik
    • assets/html/partials/: birden fazla yerde yeniden kullanılan HTML parçaları
    • assets/static/css, assets/static/img, assets/static/js: statik varlıklar
    • cmd/web/: sunucu başlatma, handler ve HTML renderer kodu
  • Temel iskelet aşağıdaki komutlarla oluşturulur
go mod init example.com/htmx
mkdir -p assets/static/css assets/static/img assets/static/js assets/html/partials assets/html/pages cmd/web
touch assets/efs.go assets/html/base.tmpl assets/html/partials/images.tmpl assets/html/pages/home.tmpl cmd/web/main.go cmd/web/handlers.go cmd/web/html.go
  • HTMX, CDN veya NPM ile de kurulabilir; ancak genellikle bir kopyası indirilip uygulamanın statik dosyası olarak doğrudan sunulur
    • Yapılandırma daha basittir ve CDN kullanımının dezavantajlarından kaçınmayı sağlar
    • htmx.org@2.0.10 ve sınıfsız CSS framework’ü bamboo.css@1.4.0 kullanılır
wget -P assets/static/js https://cdn.jsdelivr.net/npm/htmx.org@2.0.10/dist/htmx.min.js
wget -P assets/static/css https://cdn.jsdelivr.net/npm/bamboo.css@1.4.0/dist/bamboo.min.css

Temel, sayfa ve parça şablonlarını ayırma

  • base.tmpl, <head>, ortak başlık, <main> gibi tüm belge iskeletini tanımlar ve page:title ile page:content bölümlerini yerleştirir
  • Bamboo CSS ve HTMX script’i temel şablonda yüklenir; HTMX script’ine defer niteliği verilir
    • Tarayıcı HTML’i parse ederken script’i paralel olarak getirir
    • HTML parse işlemi ve DOM oluşturma bittikten sonra script’i çalıştırır
  • Tüm şablonlara dosya adına bağlı kalmadan {{define}}...{{end}} ile açık ad verilir
    • Go kodu yalnızca tanımlı adlarla şablonlara tutarlı şekilde başvurabilir
    • page:title içindeki : keyfi bir ayraçtır; page_title, page-title, pageTitle, title gibi adlar da kullanılabilir
  • Ana sayfadaki düğmede iki davranış tanımlanır
    • hx-get="/gopher": tıklanınca GET /gopher isteği gönderir
    • hx-swap="outerHTML": yanıt HTML’i ile düğmenin kendisini değiştirir
  • partial:image:gopher, yeniden kullanılabilir bir görsel parçasıdır ve width="{{.}}" ile çağrı anında görsel genişliğini alır
  • Yalnızca belirli bir sayfada kullanılan HTML parçaları ortak partials dizininde değil, ilgili sayfa dosyasında tutulabilir
    • Birden fazla sayfada kullanılan parçalar ortak dizinde, sayfaya özel parçalar ise ilgili içeriğin yanında konumlandırılır

HTML ve statik varlıkları Go binary’sine gömme

  • Go 1.16 ile dosya embedding eklendikten sonra HTML ve statik varlıklar çalışma anında diskten okunmak yerine Go binary’sine dahil edilebilir
  • //go:embed "html" "static" yönergesiyle iki dizin embed.FS içine alınır ve fs.Sub() kullanılarak iki alt dosya sistemine ayrılır
    • HTMLFiles: kök olarak html kullanan şablon dosya sistemi
    • StaticFiles: kök olarak static kullanan statik dosya sistemi
  • Bu ayrımın iki avantajı vardır
    • HTML kodu ve statik dosya kodu birbirinin dosyalarına gereksiz erişim yapmaz
    • Dosya açarken html/ veya static/ önekini eklemek gerekmez
  • sub() içinde panic() kullanmak istemiyorsanız hata döndürüp iki değişkeni main() içinde de başlatabilirsiniz
  • Mevcut uygulamada fs.Sub() ancak dizin değeri geçerli bir yol değilse başarısız olabilir; fakat sabit string "html" ve "static" bu denetimi geçtiği için çalışma zamanı panic riski çok düşüktür

Paylaşılan şablon kümesi ve htmlRenderer

  • htmlRenderer, render akışını şu şekilde yönetir
    • Başlangıçta paylaşılan şablon kümesini bir kez parse eder
    • Her render işleminde paylaşılan kümeyi clone eder
    • İstek için gereken sayfa şablonlarını ek olarak parse eder
    • Belirtilen adlı şablonu çalıştırıp HTTP yanıtı olarak gönderir
  • newHTMLRenderer(), template.FuncMap kaydettikten sonra ortak şablonları parse eder
    • now, time.Now fonksiyonuna bağlanır
    • Diğer özel şablon fonksiyonları da aynı yere eklenebilir
  • render(), sharedTemplates.Clone() ile istek başına bir şablon kümesi oluşturur ve additionalTemplateFiles varsa ParseFS() ile genişletir
  • Şablon önce bytes.Buffer içine çalıştırılır, ardından durum kodu yazılır ve yanıt gövdesi olarak gönderilir
  • Sunucu başlatılırken "base.tmpl" ve "partials/*.tmpl" paylaşılan küme olarak parse edilir
    • Temel şablon ve tüm ortak parçalar renderer içinde her zaman kullanılabilir olur
    • Yalnızca sayfaya özgü şablonlar handler çağrısında eklenir
  • Statik dosyalar http.FileServerFS(assets.StaticFiles) ve /static/ yolu üzerinden sunulur; sunucu :5051 üzerinde çalışır

Tam sayfa ve HTML parçaları render etme

  • Ana sayfa handler’ı aşağıdaki çağrıyla tam belgeyi döndürür
app.html.render(w, 200, nil, "base", "pages/home.tmpl")
  • Bu çağrı, pages/home.tmpl dosyasını paylaşılan kümeye ekler ve base şablonunu 200 OK ile çalıştırır
  • /gopher handler’ı ek dosya parse etmeden, paylaşılan kümede zaten bulunan partial:image:gopher şablonunu çalıştırır
width := 100
app.html.render(w, http.StatusOK, width, "partial:image:gopher")
  • HTMX, /gopher adresinden alınan görseli hx-swap="outerHTML" ayarına göre butonla değiştirir
  • Bu yapı şu avantajları sağlar
    • Şablonlar ve statik varlıklar ikili dosyaya gömülür, böylece dağıtım kolaylaşır
    • Aynı render() ile hem tam HTML sayfası hem de belirli HTML parçaları döndürülebilir
    • Temel şablonlar ve parça şablonlar sayesinde işaretleme tekrarları azalır
    • Parça şablonlar temel şablonda, sayfa içeriğinde ve diğer parça şablonlarda yeniden kullanılabilir

Yazarken anında güncellenen kullanıcı araması

  • Arama özelliği iki yola ayrılır
    • GET /users: tüm kullanıcı bilgilerini içeren tam HTML sayfası
    • GET /users/search: adı veya e-postası arama terimiyle eşleşen kullanıcıların yalnızca tablo satırlarını döndüren HTML parçası
  • Arama giriş kutusu şu HTMX özelliklerini birleştirir
    • hx-get="/users/search" ile arama isteği gönderir
    • hx-trigger="input changed delay:500ms, keyup[key=='Enter']" ile giriş değiştikten 500ms sonra veya Enter'a basılınca istek yapar
    • Arama terimi GET /users/search?query=foo biçiminde sorgu dizesi olarak iletilir
    • hx-target="#search-results" ile yanıtı <tbody id="search-results"> içine yerleştirir
    • hx-push-url="true" ile her istekte adres çubuğunu günceller ve tarayıcı geçmişine bir kayıt ekler
  • users:rows, yalnızca kullanıcı satırlarını render eden ayrı bir şablondur
    • Her satırda ad ve e-posta gösterilir
    • IsGopher true ise partial:image:gopher 24 genişlikle render edilir
  • listUsers ve searchUsers her ikisi de pages/users.tmpl dosyasını paylaşılan kümeye ekler, ancak çalıştırdıkları şablon farklıdır
    • listUsers: base çalıştırılır ve tam sayfa döndürülür
    • searchUsers: users:rows çalıştırılır ve yalnızca eşleşen satırlar döndürülür
  • Arama terimi boşsa tüm kullanıcı listesi kullanılır, doluysa ad ve e-posta strings.Contains() ile kontrol edilir
  • Gerçek bir uygulamada şu iyileştirmeler düşünülebilir
    • Liste ve arama handler'larını birleştirmek
    • Hata işleme ve loglama yardımcılarını merkezileştirmek
    • Middleware ile Content Security Policy başlıkları ve panic kurtarma eklemek
    • Sunucu zaman aşımı sınırlarını uygun şekilde ayarlamak

HX-Request ile tam sayfa ve parça yanıtlarını ayırma

  • Kullanıcı /users/search?query=leo adresini tarayıcıda doğrudan açar ya da paylaşılan bir bağlantıyla ziyaret ederse, yalnızca tablo satırlarına karşılık gelen parça HTML'yi görebilir
  • HTMX istekleri her zaman HX-Request: true başlığını içerdiğinden, yanıt biçimi buna göre belirlenir
func isHTMXRequest(r *http.Request) bool {
    return r.Header.Get("HX-Request") == "true"
}
  • Arama handler'ının varsayılan yürütme şablonu base olarak bırakılır, yalnızca HTMX isteği olduğunda users:rows olarak değiştirilir
    • Doğrudan ziyaret edilirse arama sonuçlarını içeren tam sayfa alınır
    • HTMX isteğinde yalnızca <tbody> içine yerleştirilecek satır parçaları döndürülür

Vary başlığı ve geri gitme sırasında geri yükleme

  • Aynı URL, HX-Request değerine göre farklı yanıtlar döndürdüğü için önbelleğe de bu fark bildirilmelidir
  • Tüm render yanıtlarına Vary: HX-Request eklenir
    • Bunu yalnızca gereken yerlerde tek tek handler'larda ayarlamak teknik olarak daha az israf yaratır
    • Render katmanında topluca ayarlamak, unutma nedeniyle oluşabilecek hataları önler
  • hx-push-url veya hx-boost tarayıcı geçmişine kayıt eklediğinde HTMX, tamamlanmış sayfa HTML'sini tarayıcının yerel depolamasında önbelleğe alır
    • Varsayılan önbellek en fazla 10 sayfadır
    • Önbellekte olmayan bir noktaya kadar geri gidilirse HTMX ilgili URL'yi sunucudan yeniden ister
  • Varsayılan geri yükleme isteği HX-Request: true içerdiğinden, sunucu tam sayfa yerine parça HTML döndürebilir
  • Yanıt türü HX-Request ile seçiliyorsa historyRestoreAsHxRequest: false ayarlanmalıdır
    • Önbellek ıskalamalı geri yükleme isteklerinde HX-Request: true gönderilmez
    • Böylece sunucu bu isteğe tam HTML sayfası döndürür
  • HTMX yapılandırması base.tmpl içindeki htmx-config meta etiketine konur

HTMX isteklerini başka bir sayfaya yönlendirme

  • HTMX, başarı mesajı gibi HTML parçalarını anında değiştirebildiği için klasik Post/Redirect/Get akışına duyulan ihtiyaç çoğu durumda azalır
  • Giriş sonrası profile gitmek gibi tamamen farklı bir sayfaya yönlendirmek gerektiğinde yalnızca normal 3xx yanıtlarıyla bu yapılamaz
    • Tarayıcı, 3xx yanıtını HTMX'ten önce takip eder
    • HTMX ise yönlendirme sonrasındaki nihai yanıtı görür ve içeriğini mevcut hedefe yerleştirir
  • HTMX isteklerinde 2xx yanıtla birlikte HX-Redirect başlığı kullanılır
    • HX-Redirect: /foo/bar tarayıcıyı ilgili URL'ye götürür ve tam sayfayı yeniden yükler
    • Hedefe yapılan istekte HX-Request: true bulunmaz
  • JavaScript'in kapalı olduğu veya HTMX'in yüklenmediği ortamları da desteklemek isteniyorsa, HTMX olmayan isteklerde normal 3xx yanıtları korunmalıdır
func redirect(w http.ResponseWriter, r *http.Request, url string, code int) {
    if isHTMXRequest(r) {
        w.Header().Set("HX-Redirect", url)
        w.WriteHeader(http.StatusNoContent)
        return
    }

    http.Redirect(w, r, url, code)
}
  • Girişten sonra /profile sayfasına gitmek için şöyle çağrılabilir
redirect(w, r, "/profile", http.StatusSeeOther)

HX-Redirect ile HX-Location arasındaki fark

  • HX-Location, tam sayfayı yeniden yüklemeden yönlendirmeye benzer bir davranış sergiler
    • Hedef URL'nin HTML'sini alır
    • Yanıtı <body> ile değiştirir
    • Tarayıcı geçmişine yeni bir kayıt ekler
  • Hedef URL istenirken HX-Request: true gönderilir
  • Hedef yol HX-Request değerine göre parça HTML döndürüyorsa sorun çıkabilir
    • Handler, HX-Location ile gelen istekle normal HTMX isteğini ayırt edemez
    • İlkinde tam sayfa gerekirken ikincisinde parça yanıt gerekir
  • Geçmiş geri yüklemeden farklı olarak, HX-Location geçişlerinde HX-Request: true göndermeyi kapatan bir ayar yoktur
  • Çoğu durumda tam sayfa yeniden yüklemeyi kabul edip HX-Redirect kullanmak daha kolay ve güvenlidir
  • Hedef yol her zaman yalnızca tam HTML döndürecek şekilde yapılandırıldıysa HX-Location da kullanılabilir

204·422·4xx·5xx yanıtlarını işleme

  • HTMX varsayılan olarak 4xx veya 5xx yanıtlarını DOM'a yerleştirmez
    • Mevcut ekran olduğu gibi kalır
    • Hata, geliştirici araçları konsoluna kaydedilir
  • Sunucu, var olmayan bir şablon adı nedeniyle 500 Internal Server Error döndürse bile, varsayılan ayarlarda kullanıcı hatayı ekranda göremez
  • Hata mesajını kullanıcıya göstermek için 4xx ve 5xx yanıtları tüm <body> üzerinde değiştirilecek şekilde ayarlanır
  • İstisna 422 Unprocessable Content durumudur
    • Doğrulama hataları içeren formu geri döndürmek için kullanılır
    • Yanıtın mevcut HTMX hedefine normal şekilde yerleştirilmesi gerekir
  • responseHandling, durum koduna göre şöyle yapılandırılır
    • 204 No Content: DOM değiştirilmez
    • 422 Unprocessable Content: mevcut hedefte normal değişim yapılır
    • Diğer 4xx ve 5xx: yanıt <body> ile değiştirilir
    • Bunun dışındaki yanıtlar: mevcut hedefte normal değişim yapılır
"responseHandling":[
    {"code":"204", "swap": false},
    {"code":"422", "swap": true},
    {"code":"[45]..", "swap": true, "target": "body"},
    {"code":"...", "swap": true}
]
  • Belirli etkileşimlerde hataların <body> yerine başka bir hedefe yerleştirilmesi gerekiyorsa, varsayılan ayarı geçersiz kılmak için response target eklentisi kullanılabilir

Tarayıcı adres çubuğundaki mevcut URL’yi kontrol etme

  • HTMX, hx-boost, hx-push-url, hx-replace-url kullanılmadığı sürece AJAX isteği ve yanıt değiştirme sürecinde tarayıcı URL’sini değiştirmez
  • Bu nedenle Go işleyicisindeki r.URL ile kullanıcının adres çubuğunda gördüğü URL farklı olabilir
  • HTMX, her isteğin HX-Current-URL başlığında tarayıcının o anda gösterdiği URL’yi iletir
  • Yardımcı işlev bu başlığı url.URL olarak ayrıştırır; başlık yoksa r.URL döndürülür
func browserURL(r *http.Request) (*url.URL, error) {
    cu := r.Header.Get("HX-Current-URL")
    if cu != "" {
        return url.Parse(cu)
    }

    return r.URL, nil
}

HTMX varsayılanlarını değiştiren yapılandırma

  • historyCacheSize: 0 ile HTMX’in local storage sayfa önbelleği tamamen kapatılır
    • local storage önbelleği hata ve güvenlik sorunlarının kaynağı olabilir
    • Geri düğmesine basıldığında önbellek yerine sunucudan HTML yeniden alınır
    • Gelecekteki HTMX sürümlerinde de aynı nedenle local storage önbelleği varsayılan olarak devre dışı olacak
  • disableInheritance: true ile HTMX öznitelik kalıtımı devre dışı bırakılır
    • Öznitelikleri her zaman açıkça tanımlamak daha nettir
    • Hata veya istenmeyen davranış riskini azaltır
    • Gelecekteki HTMX sürümlerinde öznitelik kalıtımı da varsayılan olarak devre dışı olacak
  • includeIndicatorStyles: false ile HTMX’in gösterge stillerini enjekte etmesi engellenir
    • Tutarlılığı korumak için gösterge stilleri diğer CSS kurallarıyla birlikte doğrudan tanımlanır
  • HTMX istekleri varsayılan olarak zaman aşımına sahip değildir; sunucu yanıt verene kadar bekler
    • Go uygulamasının zaman aşımı ve deadline yönetimine göre timeout milisaniye cinsinden belirtilebilir
    • Başlangıç noktası olarak timeout: 5000 kullanılır
  • Varsayılan yapılandırmada historyRestoreAsHxRequest: false ve durum koduna göre responseHandling da yer alır
<meta
    name="htmx-config"
    content='{
        "includeIndicatorStyles": false,
        "historyCacheSize": 0,
        "historyRestoreAsHxRequest": false,
        "responseHandling":[
            {"code":"204", "swap": false},
            {"code":"422", "swap": true},
            {"code":"[45]..", "swap": true, "target": "body"},
            {"code":"...", "swap": true}
        ],
        "timeout": 5000
    }'
>

Büyük uygulamalar için sayfa bazlı düzenler

  • Temel şablon ve sayfa bazlı şablonlar yeterli değilse, iki katman arasına bir düzen şablonu eklenebilir
  • Yönetici sayfaları gibi, normal sayfalardan farklı başlık, gezinme menüsü ve gövde yapısı gerektiren alanlar için uygundur
  • base, page:content çağrısını doğrudan yapmak yerine layout çağırır
<body>
    {{template "layout" .}}
</body>
  • layouts/admin.tmpl, yönetici alanının ortak yapısını tanımlar ve içeride page:content çağırır
    • yönetici alanı başlığı
    • kullanıcılar ve siparişlere giden gezinme menüsü
    • sayfaya özgü içeriğin yer alacağı <main>
  • İşleyici, render() için kullanılacak düzeni ve sayfa şablonunu birlikte geçirir
app.html.render(
    w,
    200,
    nil,
    "base",
    "layouts/admin.tmpl",
    "pages/admin-orders.tmpl",
)
  • Paylaşılan temel şablon korunurken rota bazlı düzenler ve sayfa içeriği birleştirilebilir; böylece yönetici alanı gibi ayrı yapı gerektiren ekranlar da aynı render kalıbıyla genişletilebilir

1 yorum

 
GN⁺ 4 시간 전
Hacker News yorumları
  • Go + HTMX kombinasyonunu seviyor ve şablonlar, bileşenler ve kısmi HTML için tür güvenliğini artırmak amacıyla bunu a-h/templ ile birlikte kullanıyor Go·Unix·SQLite’tan oluşan tüm araç setine GUS stack adını verip paylaşmış: https://housecat.com/blog/the-gus-stack-go-unix-sqlite exe.dev’in GUTS stack’inden büyük ölçüde ilham almış ama TypeScript yerine HTMX kullanıyor: https://exe.dev/docs/guts Stack trace hataları için cockroachdb/errors, tür güvenli HTML için templ, OpenAPI şeması üretimi için fuego, SQL kod üretimi için sqlc, saf Go SQLite için modernc.org/sqlite, migration için goose, kalıcı iş akışları için dbos, Chrome/CDP testleri ve otomasyonu için rod kullanıyor Bu kombinasyon hem doğrudan kod yazarken ya da bir ajanın yardımıyla kod yazarken, hem de tek bir binary build edip deploy etme sürecinde verimli oluyor

    • HTMX konuşulurken Hyperscript’in hak ettiği ilgiyi görmemesi üzücü Sunucuya gidip gelmeden veya ayrı JavaScript fonksiyonları olmadan DOM’u manipüle edebildiği için Go + HTMX ile çok iyi uyuşuyor ve zaten üzerinde çalışılan HTML’in bir uzantısı gibi hissettiriyor Deklaratif programlamayı sevmeyenler olabilir ama birden fazla ödeme ağ geçidini yöneten Open Payment Host’ta karmaşık DOM manipülasyonlarını bile yalnızca Hyperscript ile gerçekleştirebilmiş https://hyperscript.org/, https://openpaymenthost.com/
    • HTMX ya da hypertext·Unix·Go·SQLite’ı bir araya getirip adını HUGS stack olarak da değiştirmek mümkün olabilir
    • Go·Templ·HTMX kombinasyonuna GoTH stack dendiğini de görmüş; sqlc eklenirse GoTHs ya da GHosT oluyor go generate ./... komutunu build aşamasının bir parçası olarak kabul edince çok şey kazanılıyor; ayrıca goverter ile sqlc modelleri, şablon nesneleri ve dönüş değerleri arasındaki dönüşümleri de üretiyor Tekrarlayan kodun yaklaşık %50’si otomatik üretiliyor ve tür güvenliği çok iyi oluyor
    • Son zamanlarda tür güvenli SQL için jet kullanmayı seviyor Kod üretimi için çalışan bir veritabanı gerekiyor ama bunu, kod yazmadan önce migration’ları uygulamaya zorlaması nedeniyle bir avantaj olarak da görüyor https://github.com/go-jet/jet
    • Kendi veritabanına bile ihtiyaç duymayabilecek gerçek zamanlı API dashboard’ları gibi küçük reaktif web uygulamalarında son zamanlarda sık sık PAHG template kullanıyor Pico.css·Alpine.js·HTMX·Go kombinasyonu; tabii istenirse SQLite da eklenebiliyor https://github.com/hiAndrewQuinn/pahg-template
  • HTMX pek çok kullanım için harika ama ekip arkadaşları aynı fikirde değilse bunu benimsetmek çok zor Bunun ciddi bir teknoloji olmadığı yönünde itirazlar sürüyor ve türlü bug’ların suçu önce HTMX’e atılıyor; sonradan bunun bir yanlış anlama olduğu ortaya çıksa bile güven çoktan zedelenmiş oluyor Çalıştığı en iyi ekipte bile böyle olmuş ve sonuçta hangi savaşın verileceğini seçmek gerektiği dersini çıkarmış Go’nun html/template paketinin arayüzünün de özellikle yapay göründüğünü düşünüyor. 《A Philosophy of Software Design》’ın önerdiği gibi karmaşıklığı içeri itmek gerekirken, her HTML render’ında şablon kopyalamayı dert etmek zorunda bırakan yapı gereksiz yere karmaşık

    • Ben de HTMX’i seviyorum ama ekip içinde benimsetirken aynı gerçeklikle karşılaştım Basit bir web uygulaması için önerdim ama yıllardır JSON döndürüp JS/jQuery ile render eden geliştirici, her adımda mevcut problemleri yeni yöntemle çözmekte zorlandı; başka bir geliştirici ise denemeye bile yanaşmadı ve ekipte sürekli Blazor konuşuldu Her yeni yaklaşımda zorlanacaklardı muhtemelen ama HTMX’in fiilen hiç şansı olmadı Küçük bir ekip olduğumuz için JavaScript’in %95’inden kaçınıp kodu ve HTML’i sunucuda üretmek kod tabanını daha düzenli ve test etmeyi daha kolay hale getirebilirdi. Kendi projelerimde HTMX kullanmaya devam ediyorum, iyi bir akış yakaladım ve web geliştirmeyi ciddi ölçüde sadeleştirdiğini hissediyorum
    • Danışman rolünde ekipleri aktif olarak yönlendiriyor ve HTMX öğrenmenin gerçek çalışma ortamı olan tarayıcıyı anlama konusunda derinlik kazandırdığını, buna karşılık React gibi araçların geliştiriciyi tarayıcıdan izole ettiğini anlattığını ama kendisinin de aynı şeyi yaşadığını söylüyor: https://www.reddit.com/r/htmx/s/DuXyGgsCWK html/template temel güvenlik sağlaması ve standartla birlikte gelmesi açısından güzel ama dinamik yapısı yüzünden kesin bir cevabı olmayan çok fazla alan bırakıyor; Templ ile de birkaç büyük ticari uygulama yazdıktan sonra geliştirici deneyimi açısından eksikler hissetmiş Bu yüzden gsx’i yapmış: https://github.com/gsxhq/gsx
    • Şablonları render ederken her seferinde kopyalamak gerekmez; bir kez derleyip sonra sadece çalıştırmak yeterlidir Orijinal yazıdaki sorun, ana şablonda sayfa başlığını tanımlamaya çalıştığı için kendi yarattığı bir sorun. Başlığı context ile geçirip base.tmpl dosyasını BASE_BEGIN ve BASE_END olarak ayırarak son şablonda kullanmak yeterli Sayfaya özgü başlıkları çalışma anında geçirmek gerekir ama orijinal yaklaşım da çoklu dil desteği başlatılınca zaten sonunda bozulacaktır
    • Bizim şirketteyse tam tersi bir durum var: Her türlü soruna rağmen React SPA’nin yerleşik bir teknoloji olduğu gerekçesiyle ölçeklenmediği gerçeğine kimseyi ikna etmek imkansız Her soruna tek tek bakıyorlar ama hepsinin aynı yapıdan kaynaklandığını gösteren büyük resmi birleştiremiyorlar
  • Yakın tarihli bir projede HTMX kullanmaktan çok keyif almış AngularJS ve React öncesi web’i bilen biri olarak, gerçekten sayfa üretip JavaScript miktarını minimumda tutabilmek özellikle hoşuna gidiyor Saf JavaScript ile de yapılabilir ama HTMX tekrarlayan event handling boilerplate’ini üstleniyor Modern frontend felsefesini sevmiyorsanız denemeye değer; resmi sitedeki ilk örnekler oldukça temel ama biraz daha öğrenince çok daha güçlü hale geliyor

    • Temkinli biçimde SvelteKit’i de önermek isterim Dışarıdan bakınca bir başka JavaScript frontend framework’ü gibi görünüyor ama bizzat kullanınca, HTMX benzeri yaklaşımın hedeflediği hypertext merkezli tasarımı çok iyi desteklediğini gördüm
  • Oldukça büyük bir projeyi HTMX + Go ile yapmayı denedim ama yine de yeterli gelmedi; ileride istediğim seviyeye ulaşıp ulaşmayacağından da emin değilim Basit CRUD uygulamaları ve yönetim panelleri için harika, ancak birbirine bağlı bileşenler, paylaşılan durum ve karmaşık etkileşimler arttıkça yönetmesi hızla zorlaşıyor React’tan hoşlanmadığım için HTMX’i seçmiştim ama sonunda backend’i Go’da tutup frontend’i SvelteKit SPA moduna geçirdim; iki tarafı da temizce ayırınca karmaşık UI’leri geliştirmek ve sürdürmek çok daha kolay oldu Svelte, JSX gibi bambaşka bir dilden ziyade HTML’in doğal bir uzantısı gibi hissettiriyor; durum yönetimi ve bileşen modeli basit, yeni $state sözdizimi de özellikle çok iyi

    • HTMX sitesi de bunun bu tür kullanım senaryolarına uygun olmadığını açıkça bir ödünleşim olarak belirtiyor, ancak bununla ilgili yazıları bulmak için biraz derine inmek gerekiyor
    • HTMX geliştiricilerinin frontend’deki kardeş projesi Hyperscript, frontend durumu gibi işlevleri ele alıyor. Bunu da deneyip denemediğinizi merak ediyorum: https://hyperscript.org/docs/reactivity/
    • Sanırım HTMX felsefesinin özü, en başta gerçekten paylaşılan durumla birbirine bağlı bileşenlere ihtiyaç olup olmadığını sorgulamakta yatıyor Sonuçta çoğu uygulama veritabanı üzerinde CRUD yapıyor
  • Bu aralar yan projelerimin neredeyse tamamını, LLM yardımı olsun ya da olmasın, Go + HTMX ile yazıyorum Opus ve GPT de bu kombinasyonu çok iyi kullanıyor; hızlıca geliştirip başlayabiliyorsunuz, tek bir binary olduğu için dağıtım ve barındırma da rahat Hızlı yinelemeli geliştirme için çok iyi bir stack

  • HTMX kullanacaksanız, backend tarafında da React’taki gibi ortak HTML parçalarını fonksiyonlara çıkarıp bileşenleştirmeyi kolaylaştıran bir HTML üretim yaklaşımını güçlü biçimde öneririm HTMX, duruma göre belirli HTML’nin hemen yanına etiket ekleyip çıkarmanız gibi backend’in ürettiği HTML’de esneklik gerektiriyor. Örneğin en üst seviyede `` etiketini bulursa sayfa başlığını güncelliyor Geleneksel string tabanlı template motorlarında bu tür işler zordur ama dile gömülü HTML kütüphaneleri ile basittir; ayrıca dilin tüm soyutlama olanaklarını kullanabildiğiniz için HTMX ile özellikle iyi uyum sağlar JavaScript backend’te https://github.com/WebReflection/uhtml-ssr gibi tagged template literal fonksiyonları, Go’da https://www.gomponents.com/, Scala’da ise ScalaTags kullanabilirsiniz

  • Go ile ilk tanışmam Alex Edwards’ın kitapları ve Learn Go with Tests sayesinde oldu; hâlâ tavsiye ediyorum Eski projelerimden bazılarını HTMX’e dönüştürmeyi denemek istiyorum

    • Go web geliştirmeyle azıcık bile ilgileniyorsanız Alex Edwards’ın Let's Go ve Let's Go Further kitaplarının ikisini de okumalısınız Bunlar şimdiye kadar okuduğum programlama dili giriş kitapları arasında en erişilebilir, en keyifli ve en pratik olanlar
  • Kendi kullanımım için Kotlin + HTMX tabanlı bir framework yaptım: https://github.com/reubenfirmin/zoned Amacım, tüm web uygulamasını uçtan uca tip güvenli hale getirmenin mümkün olup olmadığını görmekti; HTML yazmak için JSX’e benzer bir DSL sunan Kotlinx.html kullandım İlk %90’ını kendim yaptım, son %10 ve README için ise yayını tamamlamak amacıyla Claude’dan yardım aldım

  • Go’yu da Alex Edwards’ı da seviyorum ama HTMX ile elde ettiğim sonuçlar beni hep hayal kırıklığına uğrattı Kod tabanının karmaşıklığı uygulamanın kendisinden 2 kat daha hızlı büyüyormuş gibi geliyor ve tuhaf geçici çözümler olmadan çıkamadığınız sınır durumlarla hep karşılaşıyorsunuz Node paketlerinden neden hoşlanılmadığını anlıyorum ama HTMX buna verilmiş aşırı bir tepki gibi duruyor. JSON’la uğraşmayarak kazandığınız zamandan 3 kat fazlasını uygulamanın görünümünü ve hissini düzgün hale getirmeye harcıyorsunuz Mantine template ile 2 dakikada kurulum yapıp harika UI bileşenlerinden yararlanabiliyorsunuz; derlenmiş statik asset’leri dahil ederseniz bunu yine tek bir Go binary’si olarak sunabilirsiniz: https://github.com/mantinedev/vite-min-template

    • Rails ile hypermedia’yla ilk tanıştığımda kullanışlı ve kolay gelmişti; bu yüzden Go/HTMX sürtünmesi şaşırtıcıydı, ama birkaç denemeden sonra soyutlamaların önemli olduğunu öğrendim Bileşen üreticileri ve ters yönlü router’lar yoksa iş epey sancılı oluyor; Rails bunları kutudan çıktığı gibi sunduğu için bunları düşünmeniz gerekmiyordu En büyük artı, hesaplama ve verinin tek bir yerde olması. LLM’ler de kendi içinde tamamlanmış hypermedia uygulamalarını iyi kullanıyor ve test ediyor; JavaScript’i beklemediğiniz için yineleme döngüsü de kısa oluyor Ama hazır alıp kullanabileceğiniz bir bileşen kütüphanesi olmadığı için başlamanın zor olduğuna katılıyorum
    • HTMX kullanmak için tasarım felsefesinin tamamını değiştirmem gerekti Bu mutlaka kötü bir şey değil, hatta iyi bir değişim de olabilir; ama ciddi bir dönüşüm ve ortaya çıkan şey mobil uygulamayı taklit etmekten çok web’in kendine özgü biçimine daha yakın oluyor
    • Mantine ile yapabildiğiniz ama HTMX ile yapamadığınız somut UI örneklerinin neler olduğunu merak ediyorum
  • Go + Datastar daha basit olduğu için onu çok daha fazla tercih ediyorum

    • Go ve Datastar birbirine cuk oturuyor Template tarafına a-h/templ de eklemek istiyorum; Datastar bunu da destekliyor Datastar’ın bu kadar az bilinmesine şaşırıyorum
    • Ben de Datastar’ı tercih ediyorum ama HTMX4’ün yeni özellikleri aradaki farkı büyük ölçüde kapatıyor Ekosistemin iyi kalıplara doğru yakınsamasını görmek sevindirici