3 puan yazan GN⁺ 2023-09-11 | 1 yorum | WhatsApp'ta paylaş
  • Statik siteler barındırması kolay, hızlı ve bakımı az olduğu için, basit bir siteyi ayrı bir oluşturucu öğrenmeden birkaç satırlık Makefile ile yapmak yeterli olabilir
  • Temel yapı, source içindeki dosya düzenini koruyup HTML dosyalarına header.html eklemek, diğer dosyaları ise build içine olduğu gibi kopyalamak üzerine kurulu
  • make build, find source -type f ve patsubst ile girdi·çıktı dosyalarını eşleştirir; .html ve diğer dosyalara farklı make kuralları uygular
  • Geçerli sayfayı vurgulama, Markdown dönüşümü, yerel sunucu, değişiklik algılayıp yeniden derleme ve GitHub Pages dağıtımı gerektiğinde ek hedefler olarak eklenebilir
  • Bağımlılıkları az ve değiştirilecek yerleri net olduğu için, gereksinimleri küçük sitelerde genel amaçlı oluşturuculardan ziyade kendi yaptığınız derleme akışı daha hızlı olabilir

Yalnızca Makefile ile temel bir statik site yapmak

  • Statik site oluşturucularının çıktısı barındırması kolaydır, hızlıdır ve bakım yükü çok küçüktür
  • Basit bir site için mevcut site oluşturucuları öğrenip onlara uyum sağlamaktansa doğrudan betik yazmak daha hızlı ve tatmin edici olabilir
  • Otomatik güncellenen zaman damgaları veya RSS akışı olmayan sıradan bir site için, blog betiklerinden daha basit bir yapı yeterlidir
  • Temel gereksinimler

    • Tüm girdi dosyalarını source dizinine koyun ve çıktıda da aynı dizin yapısını koruyun
    • Tüm HTML dosyalarının başına header.html ekleyin
    • HTML olmayan dosyaları değişiklik yapmadan build dizinine kopyalayın
  • Makefile kuralları

    • build hedefi, source altındaki tüm dosyaları build altındaki çıktı dosyalarına eşleyen bağımlılıklara sahiptir
    • Kendi başına iş yapmaz, ancak her dosyaya uygun kuralın uygulanması için giriş noktası görevi görür
    • build/%.html kuralı source/%.html, header.html ve Makefile dosyalarına bağımlıdır
    • mkdir -p $(dir $@) ile çıktı dizinini oluşturur, cat header.html $< > $@ ile başlık dosyasını ve girdi HTML’ini birleştirip çıktı üretir
    • build/% kuralı, HTML olmayan dosyaları cp $< $@ ile olduğu gibi kopyalar
    • Bu header.html ve kurallar olduğu sürece make build çalıştırıldığında, yerelde açılabilecek veya bir web sunucusuna yüklenebilecek bir build dizini oluşur

Genişletme örnekleri ve yardımcı hedefler

  • Geçerli sayfayı gösterme

    • Gezinmede geçerli sayfayı vurgulamak, ziyaretçinin site içindeki konumunu bir bakışta görmesini sağlar
    • Örnekte gezinme bağlantısı bulunup current sınıfı eklenir
    • sed -E 's|(href="$(subst source,,$<))|class="current" \1|' header.html | cat - $< > $@
    • Gerçek değiştirme yöntemi, kullandığınız işaretleme yapısına göre değişmelidir
  • Markdown’dan HTML üretme

    • HTML’i doğrudan yazmak istemiyorsanız veya mevcut içerik Markdown biçimindeyse bir Markdown-to-HTML dönüştürücüsünü pipe ile bağlayabilirsiniz
    • Örnekte smu kullanılır
    • smu $< | cat header.html - > $@
    • Varsayılan kural hâlâ build/foo.html dosyasının source/foo.html dosyasından üretildiğini varsayar
    • Markdown dosyalarında da .html sonekini korumalı veya girdi olarak .md dosyalarını bulacak şekilde kuralları değiştirmelisiniz
  • Yerel önizleme

    • Bazı sitelerde yerel dosyayı tarayıcıda doğrudan açınca doğru önizleme yapmak zordur; yaygın nedenlerden biri göreli bağlantılar yerine mutlak bağlantılar kullanılmasıdır
    • Python birçok sistemde zaten kurulu gelir ve bu kullanım için uygun bir web sunucusu içerir
    • serve hedefi: python -m http.server -d build
  • Değişiklikte otomatik yeniden derleme

    • Site üzerinde çalışırken her seferinde elle yeniden derlemek zahmetlidir
    • entr kullanırsanız source, header.html ve Makefile değiştiğinde otomatik olarak make build çalıştırabilirsiniz
    • watch hedefi: find source header.html Makefile | entr make build
    • Bağımlılıktan kaçınmak isterseniz inotifywait de kullanabilirsiniz
  • GitHub Pages dağıtımı

    • GitHub’da bir deponuz varsa sonuç HTML’ini GitHub Pages ile barındırmak doğal bir seçenektir
    • git ayrıntılarıyla uğraşmamak için dağıtım komutunu ayarlamak biraz zahmetli olabilir, ancak git worktree ile çözülebilir
    • Yöntem Sangsoo Nam’ın yazısına dayanır
    • gh-pages dalını public_html çalışma ağacı olarak ekleyin
    • build/* dosyalarını public_html içine kopyalayın
    • git add --all, git commit -m "Deploy to github pages", git push origin gh-pages komutlarını çalıştırın
    • Son olarak git worktree remove public_html ile çalışma ağacını kaldırın
  • Gerçek örnek

    • Bu yaklaşımla yapılmış bir sayfayı karlb/astridbartel.de üzerinde görebilirsiniz
    • Tam bir statik site oluşturucu Makefile’ın altı satırıyla başlayabilir; alışılmadık bağımlılıklar veya bakım yükü olmadan ihtiyaca göre hızla değiştirilebilir

1 yorum

 
GN⁺ 2023-09-11
Hacker News yorumları
  • Kişisel web sitesini (https://pablo.rauzy.name/) eskiden basit bir Makefile ile oluşturuyordu.
    Daha sonra haberler ve RSS akışı, araştırma makaleleri ve ders materyallerinin otomatik listeleri, etiketlere göre filtrelenebilen kitap listesi gibi özellikler ekledi. Hâlâ Makefile kullanıyor ama Makefile’ın kendisi aksine biraz daha basitleşti; bunun yerine HTML’i satır satır işlemek için harika xml2 ve 2xml yardımcı araçlarını kullanan Bash betiklerini çağırıyor. Ağırlıklı olarak grep ve sed gibi temel yardımcı araçlardan yararlanıyor.
    Buna, gerektiğinde otomatik olarak make çağıran birkaç git hook’u da ekledi; özellikle web sitesinin barındırıldığı uzak sunucuda, depoya push yapıldığında herkese açık sürüm yeniden derleniyor.
    Yıllardır çok iyi çalışıyor ve git geçmişi 2009’a kadar gidiyor. İlk commit’lere bakınca beccad7 (FIRST_VERSION) Initial commit, d1cc6d7 adding link to Google Reader shared items, 6ccfd0c fix typo, d337959 adding link to Identi.ca account görünüyor; gerçekten 15 yıl geçmiş.
  • Bu yöntemin sorunu, source/ içinden bir dosyayı silseniz bile build/ içinden silinmemesi.
    Kendi projelerimde tüm siteyi yeniden derlemek yeterince hızlı olduğundan, yeniden derlemeden önce build klasörünün tamamını silmeyi tercih ediyorum.
    https://github.com/jez/jez.github.io/blob/source/Makefile#L1...
    Bu, bir derleme sistemi kullanmanın büyük nedenlerinden biri olan artımlı derlemeyi büyük ölçüde etkisiz bırakıyor; yine de yeniden oluşturmak istediğiniz sayfayı biliyorsanız doğrudan yalnızca o dosya için make çalıştırabilirsiniz.
    Makefile’da bu tür bir desen için yaygın bir geçici çözüm varsa bilmek isterim.
    • Yaygın bir desen mi bilmiyorum ama benim çözümüm her seferinde “beklenmeyen” dosyaları silen bir komut çalıştırmaktı.
      GNU Make’in shell fonksiyonuyla dosyaları listeliyor, filter-out fonksiyonuyla “beklenen” çıktıları ayıklıyorum. Çirkin bir hack ama komutu shell fonksiyonu üzerinden değişken genişletmesinin bir parçası olarak çalıştırıp her seferinde çalışmasını garanti ediyor.
      Makefile bağlantısı: https://github.com/jaredkrinke/make-blog/blob/main/Makefile
    • Dosya silme ve ad değiştirme, pek çok sürüm kontrol/derleme sisteminde yaygın bir sorun.
      make clean gibi nükleer seçeneklerin yanı sıra, silme ve ad değiştirme için özel Make hedefleri (target) koyabilirsiniz. Örneğin make rm sourcefile veya make mv sourcefile newsourcefile komutlarının hem kaynak hem de üretilen hedefin silinmesini/adının değiştirilmesini birlikte işlemesini sağlamak gibi.
      Aslında oldukça büyük bloglarda veya çevrimiçi projelerde bile make clean / make all döngüsü genelde yeterince hızlıdır ve şablonları ya da site tasarım öğelerini düzeltirken sıkça gerekir. Yeniden derleme süresi dert olacak kadar büyük bir ölçekse, kaynakları veritabanında yöneten ve istemci eriştiğinde dinamik olarak oluşturan gerçek bir CMS kullanmak daha doğru olabilir.
    • make clean yeterli olmaz mı?
    • Şöyle bir şey olabilir gibi:
      rm/%.html:
      @rm -f source/%.html build/%.html
      Çalıştırmak için $ make rm/page.html denir.
    • Genel amaçlı derleme sistemi Shake’te tam da bu amaç için prune özelliği var.
      http://neilmitchell.blogspot.com/2015/04/cleaning-stale-file...
      Ama make ile de işe yarayan en iyi çözümün, çıktının nihai .tar.gz arşivini oluşturan bir make dist hedefi eklemek olduğunu düşünüyorum. Kurallar doğru yazılırsa içine eski dosyalar girmez. Büyük projelerde yavaş olabilir, ama geliştirme sırasında zaten kullanmanız gerekmez; yalnızca yayın sırasında kullanırsınız. Artımlı derleme hâlâ mümkün olur, sadece son .tar.gz baştan oluşturulur.
  • Bu yazıda bahsedilen Karl’ın blog.sh shell betiği çalışmasından doğrudan ilham aldım.
    Onu alıp elden geçirerek kendi minimal statik site üreticim olan barfı yaptım. Karl harika çalışmasını yayımlamamış olsaydı bu da var olmazdı.
    [0]: https://github.com/karlb/karl.berlin/blob/master/blog.sh
    [1]: https://barf.bt.ht
    • Zevki bana uyan biriymiş. Benimkine shite diyorum ve sitemi onunla oluşturuyorum. Adı, yazılım kalitesine gönderme yapıyor :)
      En sevdiğim yanı, şimdiye kadar hiçbir şeyi yükseltmem gerekmemiş olması ve bundan sonra da gerekecek gibi görünmemesi. Bir sonraki güzel yanı ise JavaScript olmadan hot reload yapabilmesi.
      [1] https://github.com/adityaathalye/shite
      [2] https://evalapply.org
  • Biraz m4 karıştırırsanız aynı iskelet yaklaşımı koruyup biraz daha esneklik elde edebilirsiniz.

Yaklaşık 20 yıl önce böyle bir yöntemle yapılmış küçük bir web sitesini bakımını üstlenmiştim. Ama kişisel web siteleri dışında bu modelin günümüzde ne kadar uyacağını bilmiyorum. Çünkü bu yöntem özünde Web 1.0 rolünü dayatıyor. Katkıda bulunan tüm kullanıcıların HTML’e hâkim olması gerekiyor ya da birinin “webmaster” angaryasını üstlenmesi gerekiyor
[1] https://en.wikipedia.org/wiki/M4_(computer_language)

  • “Biraz m4” diye bir şey yoktur
    Temiz bir projeye başlar ve bu kez m4ye dokunmayacağına yemin edersin. Sonra tekrar eden kodu azaltmak için küçük bir m4 çağrısı eklersin
    Bir yıl sonra web sitesinde “cat” kelimesinin neden sessizce kaybolduğunu bulmak için 5 kat makro genişletmesini deşersin ve sonunda junior geliştiricinin for döngüsünü kılavuzdan kopyalamayıp kendi yazmaya çalışırken tırnakları bozduğunu keşfedersin
    O anki sorunu çözdükten sonra DSL hata ayıklamasının çok zor olduğuna karar verip her projeye kopyalayıp durduğun M4 makro dosyasını getirirsin. Ardından çıktıya yorum ekleyip stack trace üreten betiğin çalışmasını sağlayan makro üreten makrolarla tüm define kullanımlarını değiştirmek için bir gün harcarsın
    Bir sonraki projede kesin bir kural koyacaksın. m4 yasak! Tabii belki o tek yer için bir istisna olabilir
  • m4 ya da perl gibi genel metin ikamesine bel bağlamak yerine, HTML ve XML’in temeli ve ortak üst kümesi olan SGML kullanmayı öneririm
    SGML, kolay tip denetimli metin makrolarını, yani entity genişletmeyi yerleşik olarak sunar; ayrıca tipi bilen parametreli makro genişletmesi de mümkündür. Buradaki tip, işaretleme öğesinin genel içerik tipi, yani izin verilen alt öğeler ve sıraları anlamına gelir; öznitelik, CDATA, RCDATA gibi bağlamlara genişletme ya da escape etme de hesaba katılır
    Potansiyel olarak kötü niyetli kullanıcı yorumlarını uygun şekilde genişletip escape ederken, örneğin satır içi düzeyde işaretlemeye izin verip script öğesini yasaklayan kullanıcı kurallarını uygulama işini ancak SGML düzgün biçimde yapabilir. Markdown ya da wiki sözdizimini HTML’e genişletmek, dış/sindikasyon HTML içeriklerini içeri almak, RSS ve gezinme için outline oluşturmak gibi işler de mümkündür. Komut satırında epey karmaşık statik site hazırlama işleri için uygundur
    [1]: https://sgmljs.net/docs/producing-html-tutorial/producing-ht...
    [2]: https://sgmljs.net/docs/sgmlproc-manual.html
  • m4 ya da sed ile bul-değiştir yerine envsubst denemen iyi olabilir
    Bash tarzı değişken başvurularını, örneğin $TITLEı ortam değişkeni değeriyle değiştiren bir programdır
    export CURRENT="..."
    cat page.html | envsubt
  • “Biraz m4” mü, lütfen kesinlikle hayır
    m4, obfuscated programming dili olarak bile pek iyi değil
  • Bir kez denedim, bir daha asla
    sendmail’de çalışmış olması tek başına herhangi bir şeyi meşrulaştırmaya yetmez
  • HN’de karşıma çıkan neredeyse tüm geliştirici bloglarında RSS feed olması hoşuma gidiyor
    Burada ilginç bir yazı okuduğum her seferinde feed’e abone oluyorum. Wordpress sitesi olsun, Bear Blog olsun, Micro.blog olsun, Havenweb blogu olsun, elde yapılmış bir sitenin feed’i olsun, Hey Homepage’in Really Social Sites modülüne ekliyorum
    Nihayetinde Kagi’nin Small Web girişiminde yaptığı gibi bu blog listesini herkese açmak istiyorum. Ancak kalite katmak için kürasyon kilit unsur ve kürasyonu düşününce bir tür çevrimiçi dergi başlatmak doğal görünüyor
    • Bir geliştirici olarak kendi bloguma sahip olmak istemememin tuhaf olup olmadığını anlamaya çalışıyorum
      İnsanlar başkalarıyla paylaşmaya hakları olduğu yönündeki, iyi anlamda “hak görme” duygusunu nereden alıyor? Başkalarının benim üzerinde çalıştığım şeylerle ilgileneceğini neden varsaydıklarını merak ediyorum. Bazen rekabet gibi geliyor. “Blogda beğeni ya da görünürlük almak için olabildiğince havalı bir şey yapmalısın” gibi
      İşbirliği elbette iyi ve bunun mümkün olması için her şeyin açık olması gerekiyor. Ama “havalı göründüğü için bunu yapıyorum” ile “tepki almak için bunu başkalarıyla paylaşmaya çalışıyorum” arasındaki sınırı pek bilmiyorum
    • Bear Blog’a benzeyen https://prose.sh de var
  • Bir arkadaşım make ile bilimsel makale üretme yöntemini anlatmıştı
    Tek bir test dosyasını değiştirsen bile tek bir komutla testleri çalıştırma ve grafik üretme dahil tüm makaleyi yeniden üretebildiğini söylemişti
  • Temiz bir fikir, ama zaten GitHub’a push ediyorsan yalnızca kaynağı yüklesen bile GitHub Markdown’ı barındırılan bir sayfa olarak yayımlayabiliyor
    https://pages.github.com/
    • O zaman basit hosting’in ötesinde GitHub’a bağımlı hale gelirsin. En baştan site üretimini yerelde çalıştırılabilir tutmak daha iyi
  • Kodu beğendim
    Benimki JavaScript’siz hot reload istediğim için biraz fazla tasarlandı ve keyifli bir yak shaving oldu
    Temel fikir aynı. Şablonlarda heredoc kullanıyorum, düz metni HTML’e çeviren bir derleyici kullanıyorum; benim durumumda bu pandoc. İndeks üretimi için ara CSV kullanıyorum ve front matter’ı çıkarmaya yarayan kullanışlı bir sed tekniği de var. Klasik ve güzel
    [1] https://github.com/karlb/karl.berlin/blob/master/blog.sh
    [2] https://github.com/adityaathalye/shite
    [3] Benim yöntemim: https://github.com/adityaathalye/shite/blob/master/bin/templ...
    • Onun GEMINI yaklaşımı epey komikti. Regex ile biçimlendirmenin çoğunu soyup atıyor

Ancak bazı sınırlamaları var. Ben yazıları namespace’lere göre düzenliyorum ve URL’ye tarih koyuyorum; make bunu doğrudan pek iyi işleyemiyor

  • Bu tür betiklere baktığınızda, neden kendimiz yapmak yerine esbuild ya da vite gibi şeyler kullandığımızı tam olarak anlıyorsunuz
  • make’in avantajı, yavaş bir derleyiciyle derlenen büyük programlarda küçük değişiklikler olduğunda artımlı yeniden derlemeyi çok daha hızlı hale getirmesi
    Tam yeniden derlemesi 40 dakika sürecek bir iş yaklaşık 3 saniyede bitebilir
    Statik bir site, ortak bir header ile birkaç yüz HTML dosyasını cat etmekten ibaretse ve baştan 1 saniyenin altında oluşturulabiliyorsa, betik yerine make kullanmanın bir avantajı yoktur. Sadece bağımlılık hataları yüzünden eksik bir build yapma riski doğar
    • Dosya bağımlılıkları gerçekten önemli değilse build hedeflerini .phony olarak işaretlemek yeterlidir
      Yine de make build ile make push gibi ayrımlara sahip olabilirsiniz
  • Vay, bu benim sitemde yapmayı düşündüğüm şeyle neredeyse birebir aynı
    Başka küçük projelerde geçici bir bundler olarak çok küçük bir shell betiği kullandım. CSS ve JS’yi HTML’nin içine gömüyordu; amaç, build edilmemiş dosyaların da yerelde sunulabilmesini sağlamaktı