Generator situs statis dengan "Make" (2022)
(karl.berlin)- 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, menambahkanheader.htmlke file HTML, dan menyalin apa adanya file lainnya kebuild make buildmemasangkan file input-output denganfind source -type fdanpatsubst, lalu menerapkan aturan make yang berbeda untuk.htmldan 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.htmlditambahkan di depan semua file HTML- File non-HTML disalin ke direktori
buildtanpa perubahan
- Semua file input diletakkan di direktori
-
Aturan Makefile
- Target
buildmemiliki dependensi yang memetakan semua file di bawahsourceke file output di bawahbuild - Target ini tidak memiliki pekerjaan sendiri, tetapi berperan sebagai titik masuk agar aturan yang sesuai diterapkan ke tiap file
- Aturan
build/%.htmlbergantung padasource/%.html,header.html, danMakefile mkdir -p $(dir $@)membuat direktori output, lalucat header.html $< > $@menggabungkan header dan HTML input menjadi output- Aturan
build/%menyalin apa adanya file non-HTML dengancp $< $@ - Hanya dengan
header.htmldan aturan ini, menjalankanmake buildakan membuat direktoribuildyang bisa dibuka secara lokal atau diunggah ke server web
- Target
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.htmldibuat darisource/foo.html - Untuk file Markdown, Anda perlu tetap memakai sufiks
.htmlatau mengubah aturan agar mencari file.mdsebagai 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 buildbisa dijalankan otomatis saatsource,header.html, atauMakefileberubah - 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-pagessebagai worktreepublic_html - Salin
build/*kepublic_html - Jalankan
git add --all,git commit -m "Deploy to github pages", dangit 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
Pendapat di Hacker News
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
grepdansedSaya juga menambahkan beberapa git hook yang otomatis memanggil
makesaat diperlukan, terutama di server jarak jauh tempat situs web di-hosting: ketika push ke repositori, versi publik akan dibangun ulangSudah 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 berlaluxml2dan2xmltampak seperti proyek yang agak terbengkalaihttps://github.com/cryptorick/xml2
https://manpages.debian.org/unstable/xml2/2xml.1.en.html
source/, file itu tidak ikut terhapus daribuild/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
makeuntuk file tersebut sajaSaya ingin tahu apakah ada workaround yang umum untuk pola seperti ini di Makefile
Dengan fungsi
shelldari GNU Make saya mencantumkan file, lalu memakai fungsifilter-outuntuk menyaring output yang “diharapkan”. Ini hack yang jelek, tetapi dengan membuat perintah dijalankan sebagai bagian dari ekspansi variabel melalui fungsishell, saya memastikan itu berjalan setiap kaliTautan Makefile: https://github.com/jaredkrinke/make-blog/blob/main/Makefile
Selain opsi nuklir seperti
make clean, Anda bisa membuat target Make khusus untuk penghapusan dan penggantian nama. Misalnya,make rm sourcefileataumake mv sourcefile newsourcefilebisa dibuat agar sekaligus menangani penghapusan/penggantian nama pada sumber dan target yang dihasilkanDalam praktiknya, bahkan untuk blog atau proyek online yang cukup besar, siklus
make clean/make allbiasanya 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 mengaksesmake clean?rm/%.html:@rm -f source/%.html build/%.htmlJalankannya dengan
$ make rm/page.htmlprunepersis untuk tujuan inihttp://neilmitchell.blogspot.com/2015/04/cleaning-stale-file...
Namun menurut saya solusi terbaik yang juga berlaku di
makeadalah membuat targetmake distyang menghasilkan arsip akhir.tar.gzdari 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.gzterakhir yang dibuat dari awalblog.shyang disebutkan dalam tulisan iniSaya 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
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
m4, Anda bisa tetap mempertahankan pendekatan yang sangat kerangka saja seperti ini sambil mendapat sedikit lebih banyak fleksibilitasPernah 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)
m4”Memulai proyek bersih dan berjanji kali ini tidak akan menyentuh
m4. Lalu, untuk mengurangi kode berulang, akhirnya memasukkan satu pemanggilanm4kecilSetahun 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
definedengan makro pembuat makro yang menambahkan komentar ke output agar skrip pembuat stack trace bisa berjalanDi proyek berikutnya Anda akan menetapkan aturan mutlak. Dilarang
m4! Tentu saja, mungkin ada pengecualian untuk satu tempat itu sajam4atauperl, saya menyarankan memakai SGML, yang merupakan dasar sekaligus superset umum dari HTML dan XMLSGML 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
m4atau find-and-replace dengansed, ada baiknya mencobaenvsubstItu adalah program yang mengganti referensi variabel gaya Bash, misalnya
$TITLE, dengan nilai variabel lingkunganexport CURRENT="..."cat page.html | envsubtm4”? Tolong, jangan pernahm4bahkan kurang bagus sebagai bahasa pemrograman esoterikFakta bahwa sesuatu pernah berjalan di sendmail saja tidak cukup untuk membenarkannya
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 Sitesdi Hey HomepagePada 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
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”
Katanya, hanya dengan mengubah satu file pengujian, ia bisa membuat ulang seluruh makalah dengan satu perintah, termasuk menjalankan pengujian dan membuat grafik
https://pages.github.com/
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 triksedyang 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...
Namun, ada sedikit keterbatasan. Saya mengatur tulisan berdasarkan namespace dan memasukkan tanggal ke dalam URL, tetapi
maketidak bisa menangani hal itu secara langsung dengan baikmakeadalah membuat rebuild inkremental jauh lebih cepat ketika ada perubahan kecil pada program besar yang dibangun dengan compiler lambatPekerjaan 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
catpada header umum dan beberapa ratus file HTML, tidak ada keuntungan memakaimakealih-alih skrip. Yang ada hanya risiko melakukan build yang tidak lengkap karena bug dependensi.phonyMeski begitu, kita tetap bisa memiliki pemisahan seperti
make builddanmake pushDi 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