3 poin oleh GN⁺ 2023-09-11 | 1 komentar | Bagikan ke WhatsApp
  • Situs statis mudah di-hosting, cepat, dan minim perawatan, jadi untuk situs sederhana cukup dibuat dengan beberapa baris Makefile tanpa perlu mempelajari builder terpisah
  • Struktur intinya adalah mempertahankan penataan file di source, menambahkan header.html ke file HTML, dan menyalin apa adanya file lainnya ke build
  • make build memasangkan file input-output dengan find source -type f dan patsubst, lalu menerapkan aturan make yang berbeda untuk .html dan file lainnya
  • Penyorotan halaman saat ini, konversi Markdown, server lokal, rebuild saat ada perubahan, dan deployment GitHub Pages bisa ditambahkan sebagai target tambahan saat dibutuhkan
  • Karena dependensinya sedikit dan bagian yang perlu diubah jelas, untuk situs dengan kebutuhan kecil alur build buatan sendiri bisa lebih cepat daripada generator umum

Situs statis dasar yang dibuat hanya dengan Makefile

  • Generator situs statis menghasilkan keluaran yang mudah di-hosting, cepat, dan beban perawatannya sangat kecil
  • Untuk situs sederhana, menulis skrip sendiri bisa lebih cepat dan lebih memuaskan daripada mempelajari lalu menyesuaikan builder situs yang sudah ada
  • Untuk situs biasa tanpa timestamp pembaruan otomatis atau feed RSS, susunan yang lebih sederhana daripada skrip blog sudah cukup
  • Persyaratan dasar

    • Semua file input diletakkan di direktori source, dan struktur direktorinya dipertahankan sama pada output
    • header.html ditambahkan di depan semua file HTML
    • File non-HTML disalin ke direktori build tanpa perubahan
  • Aturan Makefile

    • Target build memiliki dependensi yang memetakan semua file di bawah source ke file output di bawah build
    • Target ini tidak memiliki pekerjaan sendiri, tetapi berperan sebagai titik masuk agar aturan yang sesuai diterapkan ke tiap file
    • Aturan build/%.html bergantung pada source/%.html, header.html, dan Makefile
    • mkdir -p $(dir $@) membuat direktori output, lalu cat header.html $< > $@ menggabungkan header dan HTML input menjadi output
    • Aturan build/% menyalin apa adanya file non-HTML dengan cp $< $@
    • Hanya dengan header.html dan aturan ini, menjalankan make build akan membuat direktori build yang bisa dibuka secara lokal atau diunggah ke server web

Contoh perluasan dan target pendukung

  • Menampilkan halaman saat ini

    • Jika halaman saat ini disorot di navigasi, pengunjung bisa langsung melihat posisinya di dalam situs
    • Pada contoh, tautan navigasi dicari lalu ditambahkan kelas current
    • sed -E 's|(href="$(subst source,,$<))|class="current" \\1|' header.html | cat - $< > $@
    • Cara substitusi yang sebenarnya perlu disesuaikan dengan struktur markup yang digunakan
  • Menghasilkan HTML dari Markdown

    • Jika tidak ingin menulis HTML langsung atau konten yang ada berbentuk Markdown, Anda bisa menyambungkan konverter Markdown-ke-HTML lewat pipe
    • Contohnya menggunakan smu
    • smu $< | cat header.html - > $@
    • Aturan dasar tetap mengasumsikan bahwa build/foo.html dibuat dari source/foo.html
    • Untuk file Markdown, Anda perlu tetap memakai sufiks .html atau mengubah aturan agar mencari file .md sebagai input
  • Pratinjau lokal

    • Beberapa situs sulit dipratinjau dengan benar jika file lokal dibuka langsung di browser; alasan yang umum adalah penggunaan tautan absolut alih-alih tautan relatif
    • Python sudah terpasang di banyak sistem dan menyertakan server web yang cocok untuk keperluan ini
    • Target serve: python -m http.server -d build
  • Rebuild otomatis saat ada perubahan

    • Saat mengerjakan situs, membangun ulang secara manual setiap kali terasa merepotkan
    • Dengan entr, make build bisa dijalankan otomatis saat source, header.html, atau Makefile berubah
    • Target watch: find source header.html Makefile | entr make build
    • Jika ingin menghindari dependensi, Anda juga bisa memakai inotifywait
  • Deployment GitHub Pages

    • Jika repositori Anda ada di GitHub, meng-host HTML hasilnya dengan GitHub Pages adalah pilihan yang alami
    • Menyesuaikan perintah deployment agar tidak perlu memikirkan detail git sedikit rumit, tetapi bisa ditangani dengan git worktree
    • Caranya didasarkan pada tulisan Sangsoo Nam
    • Tambahkan branch gh-pages sebagai worktree public_html
    • Salin build/* ke public_html
    • Jalankan git add --all, git commit -m "Deploy to github pages", dan git push origin gh-pages
    • Terakhir, hapus worktree dengan git worktree remove public_html
  • Contoh nyata

    • Halaman yang dibuat dengan pendekatan ini bisa dilihat di karlb/astridbartel.de
    • Seluruh generator situs statis bisa dimulai dari enam baris Makefile dan diubah cepat sesuai kebutuhan tanpa dependensi aneh atau beban perawatan

1 komentar

 
GN⁺ 2023-09-11
Pendapat di Hacker News
  • Dulu saya membuat situs web pribadi (https://pablo.rauzy.name/) dengan Makefile sederhana
    Setelah itu saya menambahkan fitur seperti berita dan feed RSS, daftar otomatis untuk makalah penelitian dan materi kuliah, serta daftar buku yang bisa difilter dengan tag. Sekarang pun masih Makefile, tetapi Makefile itu sendiri malah sedikit lebih sederhana; sebagai gantinya, ia memanggil skrip Bash yang memakai utilitas xml2 dan 2xml yang luar biasa untuk menangani HTML baris demi baris. Sebagian besar memanfaatkan utilitas inti seperti grep dan sed
    Saya juga menambahkan beberapa git hook yang otomatis memanggil make saat diperlukan, terutama di server jarak jauh tempat situs web di-hosting: ketika push ke repositori, versi publik akan dibangun ulang
    Sudah berjalan sangat baik selama bertahun-tahun, dan riwayat git-nya mundur sampai 2009. Melihat commit-commit awal, ada beccad7 (FIRST_VERSION) Initial commit, d1cc6d7 adding link to Google Reader shared items, 6ccfd0c fix typo, d337959 adding link to Identi.ca account, dan benar-benar sudah 15 tahun berlalu
  • Masalah dengan pendekatan ini adalah meskipun file dihapus dari source/, file itu tidak ikut terhapus dari build/
    Di proyek-proyek saya, membangun ulang seluruh situs masih cukup cepat, jadi saya memilih menghapus seluruh folder build sebelum rebuild
    https://github.com/jez/jez.github.io/blob/source/Makefile#L1...
    Dengan begitu, incremental build—salah satu alasan besar memakai build system—jadi banyak dilumpuhkan, tetapi kalau tahu halaman mana yang ingin dibuat ulang, tetap bisa langsung menjalankan make untuk file tersebut saja
    Saya ingin tahu apakah ada workaround yang umum untuk pola seperti ini di Makefile
    • Saya tidak tahu apakah ini pola yang umum, tetapi solusi saya adalah menjalankan perintah yang menghapus file “tak terduga” setiap kali
      Dengan fungsi shell dari GNU Make saya mencantumkan file, lalu memakai fungsi filter-out untuk menyaring output yang “diharapkan”. Ini hack yang jelek, tetapi dengan membuat perintah dijalankan sebagai bagian dari ekspansi variabel melalui fungsi shell, saya memastikan itu berjalan setiap kali
      Tautan Makefile: https://github.com/jaredkrinke/make-blog/blob/main/Makefile
    • Penghapusan file dan penggantian nama adalah masalah umum di banyak sistem version control/build
      Selain opsi nuklir seperti make clean, Anda bisa membuat target Make khusus untuk penghapusan dan penggantian nama. Misalnya, make rm sourcefile atau make mv sourcefile newsourcefile bisa dibuat agar sekaligus menangani penghapusan/penggantian nama pada sumber dan target yang dihasilkan
      Dalam praktiknya, bahkan untuk blog atau proyek online yang cukup besar, siklus make clean / make all biasanya cukup cepat, dan sering diperlukan saat memperbaiki template atau elemen desain situs. Kalau skalanya sudah sampai waktu rebuild jadi mengkhawatirkan, mungkin lebih tepat memakai CMS sungguhan yang mengelola source di database dan membuatnya secara dinamis saat klien mengakses
    • Bukankah cukup pakai make clean?
    • Sepertinya bisa seperti ini
      rm/%.html:
      @rm -f source/%.html build/%.html
      Jalankannya dengan $ make rm/page.html
    • Build system serbaguna Shake punya fitur prune persis untuk tujuan ini
      http://neilmitchell.blogspot.com/2015/04/cleaning-stale-file...
      Namun menurut saya solusi terbaik yang juga berlaku di make adalah membuat target make dist yang menghasilkan arsip akhir .tar.gz dari output. Jika aturannya ditulis dengan benar, file lama tidak akan masuk. Untuk proyek besar mungkin lambat, tetapi saat pengembangan toh tidak perlu dipakai, cukup saat rilis saja. Incremental build tetap bisa dilakukan, dan hanya .tar.gz terakhir yang dibuat dari awal
  • Saya langsung terinspirasi oleh pekerjaan Karl pada skrip shell blog.sh yang disebutkan dalam tulisan ini
    Saya mengambilnya dan memodifikasinya untuk membuat static site generator minimalis saya, barf. Itu tidak akan ada kalau Karl tidak memublikasikan karya hebatnya
    [0]: https://github.com/karlb/karl.berlin/blob/master/blog.sh
    [1]: https://barf.bt.ht
    • Sepertinya selera kita cocok. Punya saya saya sebut shite, dan saya membuat situs saya dengannya. Namanya mengisyaratkan kualitas perangkat lunaknya :)
      Hal yang paling saya sukai adalah sejauh ini saya tidak pernah perlu meng-upgrade apa pun, dan sepertinya ke depannya juga tidak akan perlu. Hal terbaik berikutnya adalah hot reload tanpa JavaScript
      [1] https://github.com/adityaathalye/shite
      [2] https://evalapply.org
  • Dengan sedikit mencampurkan m4, Anda bisa tetap mempertahankan pendekatan yang sangat kerangka saja seperti ini sambil mendapat sedikit lebih banyak fleksibilitas

Pernah mempertahankan situs web kecil yang dibuat dengan cara seperti itu sekitar 20 tahun lalu. Namun, selain situs web pribadi, saya tidak tahu apakah model ini masih cocok sekarang. Sebab pendekatan ini pada dasarnya memaksakan peran Web 1.0. Semua pengguna yang berkontribusi harus mahir HTML, atau seseorang harus mengambil alih pekerjaan serabutan sebagai “webmaster”
[1] https://en.wikipedia.org/wiki/M4_(computer_language)

  • Tidak ada yang namanya “sedikit m4
    Memulai proyek bersih dan berjanji kali ini tidak akan menyentuh m4. Lalu, untuk mengurangi kode berulang, akhirnya memasukkan satu pemanggilan m4 kecil
    Setahun kemudian, Anda membongkar lima lapis ekspansi makro untuk mencari tahu mengapa kata “cat” diam-diam menghilang dari situs web, dan akhirnya menemukan bahwa developer junior mencoba mengimplementasikan sendiri loop for tanpa menyalin dari manual, lalu merusak tanda kutipnya
    Setelah masalah saat itu terselesaikan, Anda memutuskan bahwa debugging DSL terlalu sulit, lalu mengambil file makro M4 yang selama ini selalu disalin ke tiap proyek. Setelah itu, Anda menghabiskan sehari penuh mengganti semua penggunaan define dengan makro pembuat makro yang menambahkan komentar ke output agar skrip pembuat stack trace bisa berjalan
    Di proyek berikutnya Anda akan menetapkan aturan mutlak. Dilarang m4! Tentu saja, mungkin ada pengecualian untuk satu tempat itu saja
  • Daripada mengandalkan substitusi teks umum seperti m4 atau perl, saya menyarankan memakai SGML, yang merupakan dasar sekaligus superset umum dari HTML dan XML
    SGML menyediakan makro teks dengan pemeriksaan tipe sederhana secara bawaan, yaitu ekspansi entitas, dan juga memungkinkan ekspansi makro berparameter yang memahami tipe. Di sini tipe berarti tipe konten umum dari elemen markup, yaitu elemen anak yang diizinkan beserta urutannya, sekaligus mempertimbangkan ekspansi atau escaping dalam konteks seperti atribut, CDATA, dan RCDATA
    Hal seperti menerapkan aturan pengguna yang, misalnya, mengizinkan markup tingkat inline tetapi melarang elemen script, sambil mengekspansi dan meng-escape komentar pengguna yang berpotensi berbahaya dengan benar, hanya bisa ditangani dengan baik oleh SGML. Itu juga memungkinkan ekspansi Markdown atau sintaks wiki menjadi HTML, mengambil konten HTML eksternal/sindikasi, membuat RSS dan outline untuk navigasi, dan sebagainya. Cocok untuk pekerjaan persiapan situs statis yang cukup kompleks dari command line
    [1]: https://sgmljs.net/docs/producing-html-tutorial/producing-ht...
    [2]: https://sgmljs.net/docs/sgmlproc-manual.html
  • Sebagai ganti m4 atau find-and-replace dengan sed, ada baiknya mencoba envsubst
    Itu adalah program yang mengganti referensi variabel gaya Bash, misalnya $TITLE, dengan nilai variabel lingkungan
    export CURRENT="..."
    cat page.html | envsubt
  • “Sedikit m4”? Tolong, jangan pernah
    m4 bahkan kurang bagus sebagai bahasa pemrograman esoterik
  • Pernah mencoba sekali, tidak akan lagi
    Fakta bahwa sesuatu pernah berjalan di sendmail saja tidak cukup untuk membenarkannya
  • Saya suka bahwa hampir semua blog developer yang saya temui di HN punya RSS feed
    Setiap kali membaca tulisan menarik di sini, saya berlangganan feed-nya. Entah itu situs Wordpress, Bear Blog, Micro.blog, blog Havenweb, atau feed dari situs buatan sendiri, saya menambahkannya ke modul Really Social Sites di Hey Homepage
    Pada akhirnya saya ingin memublikasikan daftar blog ini, seperti yang dilakukan Kagi dalam inisiatif Small Web. Namun, jika ingin menambahkan kualitas, kurasi adalah kuncinya, dan saat memikirkan kurasi, memulai semacam majalah online terasa sebagai langkah yang alami
    • Sebagai developer, saya sedang mencoba memahami apakah aneh jika saya tidak ingin punya blog sendiri
      Dari mana orang mendapatkan “rasa berhak” dalam arti yang baik, bahwa mereka boleh membagikan sesuatu kepada orang lain? Saya penasaran mengapa mereka berasumsi orang lain akan tertarik pada hal yang sedang mereka kerjakan. Kadang terasa seperti kompetisi. Semacam “kalau ingin mendapat like atau exposure di blog, saya harus membuat sesuatu sekeren mungkin”
      Kolaborasi tentu saja bagus, dan itu hanya mungkin jika semuanya terbuka. Namun, saya belum begitu paham batas antara “saya melakukan ini karena terlihat keren” dan “saya berusaha membagikannya kepada orang lain demi mendapatkan respons”
    • Ada juga https://prose.sh yang mirip dengan Bear Blog
  • Seorang teman pernah menjelaskan cara membuat makalah ilmiah dengan make
    Katanya, hanya dengan mengubah satu file pengujian, ia bisa membuat ulang seluruh makalah dengan satu perintah, termasuk menjalankan pengujian dan membuat grafik
  • Idenya memang rapi, tetapi jika Anda sudah melakukan push ke GitHub, cukup unggah source saja dan GitHub bisa menerbitkan Markdown sebagai halaman yang di-hosting
    https://pages.github.com/
    • Kalau begitu, Anda menjadi bergantung pada GitHub untuk lebih dari sekadar hosting sederhana. Lebih baik sejak awal membuat pembuatan situs bisa dijalankan secara lokal
  • Saya suka kodenya
    Punya saya agak over-engineered karena menginginkan hot reload tanpa JavaScript, dan itu menjadi yak shaving yang menyenangkan
    Ide dasarnya sama. Untuk template memakai heredoc, menggunakan compiler yang mengubah teks biasa menjadi HTML, dan dalam kasus saya itu pandoc. Saya memakai CSV perantara untuk membuat indeks, dan ada juga trik sed yang berguna untuk mengekstrak front matter. Klasik dan bagus
    [1] https://github.com/karlb/karl.berlin/blob/master/blog.sh
    [2] https://github.com/adityaathalye/shite
    [3] Cara saya melakukannya: https://github.com/adityaathalye/shite/blob/master/bin/templ...
    • Pendekatan GEMINI-nya cukup lucu. Sebagian besar pemformatan dilepas dengan regex

Namun, ada sedikit keterbatasan. Saya mengatur tulisan berdasarkan namespace dan memasukkan tanggal ke dalam URL, tetapi make tidak bisa menangani hal itu secara langsung dengan baik

  • Kalau melihat skrip semacam ini, kita jadi tahu persis mengapa kita memakai sesuatu seperti esbuild atau vite, alih-alih membuatnya sendiri
  • Keunggulan make adalah membuat rebuild inkremental jauh lebih cepat ketika ada perubahan kecil pada program besar yang dibangun dengan compiler lambat
    Pekerjaan yang jika di-rebuild seluruhnya memakan waktu 40 menit bisa selesai dalam sekitar 3 detik
    Jika sebuah situs statis dapat dibuat dari awal dalam waktu kurang dari 1 detik hanya dengan melakukan cat pada header umum dan beberapa ratus file HTML, tidak ada keuntungan memakai make alih-alih skrip. Yang ada hanya risiko melakukan build yang tidak lengkap karena bug dependensi
    • Jika dependensi file sebenarnya tidak penting, target build bisa ditandai sebagai .phony
      Meski begitu, kita tetap bisa memiliki pemisahan seperti make build dan make push
  • Wah, ini hampir persis sama dengan yang ingin saya lakukan untuk situs saya
    Di proyek kecil lain, saya memakai skrip shell yang sangat kecil sebagai bundler sementara. Caranya dengan menyisipkan CSS dan JS ke dalam HTML, dan tujuannya adalah agar file yang belum di-build juga bisa disajikan secara lokal