บล็อกฟีเจอร์ขั้นต่ำ (Minimum viable blog)
(ostwilkens.se)- ตั้งเป้าทำบล็อกส่วนตัวเป็นหน้าเว็บแบบสแตติกบน โดเมนที่มีอยู่แล้ว โดยมุ่งสู่การทำให้ใช้งานได้ขั้นต่ำที่รองรับทั้งการเพิ่มคอนเทนต์และ SEO พื้นฐาน
- การทำจริงเรียบง่ายต่อเนื่องด้วย
template.htmlขนาดเล็ก,markdown2,render.pyที่ขอให้ O1 ช่วยสร้าง, และการ เขียนบทความด้วย Markdown - เทมเพลตใช้เพียง HTML/CSS พื้นฐาน เช่น
system-ui, ความกว้างสูงสุด70ch,color-scheme: light dark,viewport,UTF-8 render.pyจะแปลง./posts/{post}/eng.mdเป็น HTML ปรับพาธรูปภาพ แล้วสร้าง./blog/{post}.htmlและindex.html- แสดงให้เห็นว่าสามารถสร้างบล็อกที่ดูแลได้ด้วยเพียง การเรนเดอร์แบบสแตติก และการโฮสต์ โดยไม่ต้องใช้ Jekyll, Ghost หรือ WordPress
ข้อกำหนดของบล็อกขั้นต่ำและโครงสร้างที่ใช้จริง
- จุดตั้งต้นมีข้อกำหนดอยู่ 4 ข้อ
- ใช้ โดเมน ที่เป็นเจ้าของอยู่แล้ว
- เป็นไปตามมาตรฐานเว็บสมัยใหม่และมี SEO ที่ใช้ได้
- เพิ่มคอนเทนต์ใหม่ได้ง่ายมาก
- ทุกหน้าต้อง บิลด์แบบสแตติก
- ขั้นตอนการทำจริงนั้นเรียบง่าย
- เขียน
template.htmlขนาดเล็ก - รัน
pip install markdown2 - ขอให้ O1 สร้างสคริปต์
render.py - เขียนบทความ จากนั้นเรนเดอร์และโฮสต์
- เขียน
- ไม่ได้ใช้เอนจินบล็อกสำเร็จรูปอย่าง Jekyll, Ghost หรือ WordPress
เทมเพลตและสคริปต์เรนเดอร์
template.htmlมีเพียงโครงสร้างเอกสาร HTML พื้นฐานและ CSS ขั้นต่ำ- กำหนดชุดสีสว่าง/มืดด้วย
color-scheme: light dark - สไตล์เนื้อหาตั้งค่าเป็น
system-ui,sans-serif, ความกว้างสูงสุด70ch, ความสูงบรรทัด1.5, ขนาดตัวอักษร1.25em - ใช้ลิงก์กลับหน้าแรกที่มี
id="head-link"และตัวแทนตำแหน่ง{{ content }}
- กำหนดชุดสีสว่าง/มืดด้วย
render.pyใช้markdown2แปลงบทความ Markdown เป็น HTML- ไดเรกทอรีอินพุตคือ
./postsและเอาต์พุตคือ./blog - แต่ละบทความอ่านจาก
./posts/{post_directory}/eng.md - ใช้หัวข้อ
#แรกเป็นชื่อบทความ - แปลง Markdown ด้วยออปชัน
fenced-code-blocks,header-ids - เปลี่ยนพาธรูปภาพจาก
<img src="ให้ยึดตาม/posts/{post_code}/ - แทนที่
{{ content }}ในเทมเพลตด้วย HTML ที่แปลงแล้ว และเปลี่ยนสตริงชื่อเรื่องเป็นชื่อบทความ
- ไดเรกทอรีอินพุตคือ
- หน้าอินเด็กซ์ก็ถูกสร้างจากสคริปต์เดียวกัน
- แปลง
greetings.mdเป็น HTML ก่อน - อ่านชื่อบทความแต่ละรายการแล้วเพิ่มลิสต์ลิงก์ไปยัง
/blog/{post_code}.html - บันทึกผลลัพธ์สุดท้ายเป็น
index.html
- แปลง
- บทความถูกเขียนด้วยมือเมื่อ 2025-03-31
5 ความคิดเห็น
ตอนนี้ผมก็จัดการบล็อกของตัวเองแบบเดียวกับด้านบนเลยครับ ผมสร้างและใช้งาน SSG ที่ตอบโจทย์ความต้องการส่วนตัวของตัวเอง โดยเพิ่มฟังก์ชันคัสตอมทีละอย่างเพื่อให้ใช้ความสามารถอย่างรูปภาพ thumbnail, หมวดหมู่ และแท็กได้ด้วย รูปภาพที่แนบมาก็ถูกแปลงเป็น webp โดยอัตโนมัติแล้วอ้างอิงใช้งาน ทำให้ความเร็วในการเรนเดอร์น่าพอใจมากครับ
โอ้ ฟีเจอร์แบบคัสตอมพวกนั้นคุณค่อย ๆ เขียนโค้ดเพิ่มเองโดยตรงใช่ไหมครับ? ผมเองก็คิดจะทำแบบ DIY อยู่เสมอเหมือนกัน แต่ก็มักลังเลเพราะฟังก์ชันการขยายความสามารถและปลั๊กอินที่เฟรมเวิร์กบล็อกแบบ SSG ที่เคยใช้งานอยู่มีมาให้นี่แหละครับ
ถ้าตัดความโลภออกไปได้ แค่ตัดความอยากได้อยากมีออกไป ที่เหลือก็ไม่ได้ยากอะไรมาก จริง ๆ แล้วถ้าขอให้ AI เขียนโค้ดให้
ssgก็เขียนให้ได้หมด และถ้าขอให้เพิ่มฟีเจอร์ ก็เพิ่มให้ได้หมดเหมือนกัน 555ถ้าเลือกแค่ฟอนต์ที่สวย ๆ มันก็ดูน่าอ่านขึ้นมาเลยครับ
ความคิดเห็นบน Hacker News
นึกถึงแผนภูมิในบทความบล็อกนี้: https://molodtsov.me/2023/02/how-to-start-your-blog-in-2023/
พอตกลงไปในหล่มของ static site generator (SSG) ก็ใช้เวลาส่วนใหญ่ไปกับการเขียนถึงและง่วนกับ ตัว SSG เอง แทนที่จะเขียนสิ่งที่เดิมทีอยากเขียนหรือทำสิ่งที่ตั้งใจจะทำ
สุดท้ายก็ทิ้ง SSG แล้วติดตั้ง WordPress จากนั้นก็เลิกกังวล ซึ่งรู้สึกเหมือนได้ปลดแอกมาก
ถ้าเป้าหมายคือการง่วนปรับแต่งและเขียนถึงกระบวนการนั้นก็ไม่เป็นไร และสำหรับคนที่การง่วนปรับแต่งไม่ขัดขวางการเขียนก็ไม่เป็นไรเช่นกัน แต่สำหรับผมไม่ใช่แบบนั้น
สิ่งสุดท้ายที่ต้องการในจังหวะที่กำลังจะเขียน คือข้ออ้างให้ผัดวันประกันพรุ่ง
WordPress และปลั๊กอินทั้งหมดอาจถูกเจาะได้หากไม่อัปเดตให้เป็นเวอร์ชันล่าสุด และ BDFL ก็เป็นคนที่สามารถปิดกั้นการส่งมอบอัปเดตความปลอดภัยหรือการเข้าถึงเพื่อรับอัปเดตได้ด้วยเหตุผลส่วนตัวเล็กน้อย
เว็บไซต์แบบสแตติกไม่มีช่องโหว่ด้านความปลอดภัยให้ต้องแพตช์ ดังนั้นแม้โปรเจกต์ SSG จะล่มสลายไปเพราะปัญหาของผู้ดูแลก็ไม่ได้เป็นเรื่องใหญ่นัก แต่ใน WordPress เรื่องนี้สำคัญมาก
ต้องมีวิธีให้ผู้เยี่ยมชมทิ้งคอมเมนต์ได้ จึงเพิ่ม Disqus เข้าไป และสุดท้ายก็กลายเป็นของปนเปที่มีหลายบริการกับ JavaScript จำนวนมากปะปนกัน
หลายปีก่อน ผมอยากกลับมาถือครองข้อมูลของตัวเองโดยตรงและไม่พึ่งพาบริการภายนอก จึง export คอมเมนต์จาก Disqus แล้วลองปรับแต่ง Serendipity ก่อนจะลงตัวกับ WordPress
มันนำเข้าคอมเมนต์และหน้า Markdown ได้ และยังมีปลั๊กอินที่เผยแพร่ทุกอย่างไปยัง Fediverse ให้ด้วย
พอทำให้ทำงานบน SQLite และเปิด auto-update ไว้ ก็แทบไม่ต้องบำรุงรักษาเลย
ต้องบำรุงรักษามากเกินไปเพื่อฟีเจอร์ที่มีโอกาสสูงว่าจะไม่ได้ใช้ หากไม่อัปเดตให้เป็นเวอร์ชันล่าสุด ก็อาจกลายเป็นส่วนหนึ่งของบอตเน็ตได้
สำหรับบล็อกส่วนใหญ่ static site generator ก็เพียงพอแล้ว และต่อให้ต้องบำรุงรักษา ผมก็ทำเมื่อถึงเวลาที่ผมต้องการได้
สิ่งที่ต้องการจริง ๆ คือคำสั่งเดียวสำหรับเผยแพร่ และวิธีลากรูปภาพลงในบทความได้ง่าย ๆ ซึ่งอย่างแรกทำได้ดี ส่วนอย่างหลังทำได้ผ่านฟีเจอร์เผยแพร่ของ Jupyter Notebook
สิ่งที่ไม่ต้องการเลยคือวิธีที่ทำให้ “การส่ง HTML ไปยังไคลเอนต์” มีภาระอย่างฐานข้อมูลเข้ามาเกี่ยวข้อง
ดี แต่รู้สึกว่าถ้าจะเรียกว่าบล็อก ต้องมีฟีเจอร์เล็ก ๆ เพิ่มอีกสองอย่าง
อย่างแรก ต้องเรียงบทความตามวันที่ ให้บทความล่าสุดมาก่อน และแสดงวันที่ไว้ที่ใดที่หนึ่ง หากต้องการคงโครงสร้างขั้นต่ำไว้ ก็ใช้เมทาดาทาของไฟล์บทความ เช่น เวลาในการสร้างไฟล์ก็ได้
อย่างที่สอง แน่นอนว่าต้องมี RSS feed น่าจะสร้างฟีดง่าย ๆ ที่มีแค่ลิงก์กับชื่อเรื่องได้ไม่ยาก โดยใช้สคริปต์เดิมกับเทมเพลต RSS ขั้นต่ำ
การถูก “ติดตาม” ไม่ได้ดีเสมอไป และอาจสร้างแรงกดดันให้ต้องเอาใจผู้อ่าน ซึ่งเป็นปัจจัยเดียวกับที่ทำให้โซเชียลมีเดียแย่
ข้อ 1 ผมเอนเอียงไปทางการสร้างไฟล์ที่มีเมทาดาทาในรูปแบบอย่าง TOML โดยอัตโนมัติ
ข้อ 2 RSS จะเพิ่มแน่นอน แต่ขึ้นอยู่กับข้อ 1 :-)
ผมชอบเว็บไซต์อิสระมาโดยตลอด และเว็บไซต์ของผมเองก็เริ่มต้นคล้าย ๆ กันเมื่อราว 25 ปีก่อน
ตอนนั้นเทคโนโลยีที่เหมาะสมซึ่งผมรู้จักมีแค่ Classic ASP เลยทำแบบเรียบง่ายที่สุดด้วย ASP ล้วน ๆ
ตอนนี้กลายเป็นไซต์ที่สร้างแบบ static ด้วย Common Lisp และคิดว่าการตั้งค่านี้น่าจะอยู่ยาว: https://github.com/susam/susam.net/blob/main/site.lisp
การเริ่มจากชุดหน้าเว็บเรียบง่ายเป็นวิธีที่ดีในการสร้างเว็บไซต์แบบ minimum viable แต่เมื่อเวลาผ่านไปก็เริ่มต้องการฟีเจอร์อย่าง RSS feed, รายการบล็อกเรียงตามวันที่, ดัชนีตามแท็ก, การรองรับคอนเทนต์ที่ไม่ใช่บล็อก เช่น เครื่องมือ·เกม·เดโม และคอมเมนต์แบบไม่พึ่งพา third-party
ทุกครั้งที่ความต้องการเพิ่มขึ้น ซอร์สก็โตตาม จากโค้ดไม่กี่ร้อยบรรทัด ตอนนี้กลายเป็น Common Lisp ราว 1300 บรรทัดแล้ว
ถึงอย่างนั้นก็ยังอยากรักษาให้อยู่ในระดับที่สามารถเก็บภาพรวมของโค้ดทั้งหมดไว้ในหัวได้ และถ้ามีบั๊กก็ไล่เหตุผลและแก้ได้ภายใน 10 นาที
ช่วงนี้มีแรงยั่วยวนให้อยากเพิ่ม blogroll ที่แสดงรายการบทความจากบล็อกเกอร์ที่ชอบ อาจใช้แทน feed reader ได้ด้วย แต่จะระวังไม่ให้มันโตไปเป็นของที่อ่านอีเมลได้ด้วย
ซอร์สโค้ดอยู่ที่นี่: https://github.com/brilee/modern-descartes-v2/blob/master/ma...
มี RSS feed, รายการบล็อกเรียงตามวันที่, ระบบแท็ก และ local development server ที่ watch ไฟล์แล้ว recompile ให้
เวอร์ชันปัจจุบันคงไว้เป็น สคริปต์ Python ไม่ถึง 1000 บรรทัด: https://github.com/llimllib/obsidian_notes/blob/c93b9b5c46fe...
ผมทำหน้าที่แตกแขนงออกมาอย่างชุดบทความ, ดัชนี, slideshow และยังทำรูปแบบแท็กสำหรับคนกับวิดีโอเกมด้วย
รูปลักษณ์และความรู้สึกของ widget ทั่วไปอย่างแกลเลอรี thumbnail หรือกล่องคำอ้างอิงก็สามารถควบคุมได้ทั้งหมด
อาจใช้เป็นแหล่งอ้างอิงระดับสูงได้
ต่อไปอาจอยาก embed shader กับเว็บเกมด้วย หวังว่าความซับซ้อนจะไม่บานปลายเกินไป
อยากให้เบราว์เซอร์รองรับ text/markdown และ text/gemini แบบ native
ถ้าเบราว์เซอร์ render PDF ได้ การใส่ formatter ง่าย ๆ สำหรับคอนเทนต์ Markdown/Gemini กับ stylesheet ที่ผู้ใช้กำหนดเองได้ก็น่าจะไม่ได้ยากขนาดนั้น
ตอนนี้ยังเขียนบล็อกแบบ text/plain ได้ แต่ไม่ใช่ hypertext จริง ๆ และเสียเปรียบด้าน SEO บางทีอาจใช้ link header ทำเวทมนตร์บางอย่างได้ก็ได้
การรองรับรูปแบบอื่นจะช่วยลดกำแพงในการเผยแพร่อย่างสะอาด และคืนการควบคุมให้ผู้ใช้
ก่อนอื่นเบราว์เซอร์ต่าง ๆ ต้องตกลงกันให้ได้ว่าจะใช้ Markdown variant และ extension แบบไหน เพราะ Markdown แทบจะเหมือน CSV ของโลกฟอร์แมตข้อความ คือทุกคนใช้กันคนละแบบ
ถ้าทำให้ minimal เกินไปก็จะมีคนบ่นว่าไร้ประโยชน์ แต่ถ้าเลือก extension ก็จะมีคนบ่นว่าบวมเกินไป
ต่อให้พยายามคุยอย่างรอบคอบถึงข้อดีข้อเสียทั้งระยะสั้นและระยะยาว ก็อาจถูกปิดด้วยคำพูดว่า “อย่าให้ความสมบูรณ์แบบเป็นศัตรูของสิ่งที่ดี”
ต่อให้ตกลงชุดฟีเจอร์บางอย่างกันได้ ก็ยังน่าสงสัยว่ามันคุ้มค่าจริงหรือไม่
การอ่าน PDF โดยตรงในเบราว์เซอร์เป็นเรื่องที่พบได้บ่อยพอสมควร แต่ประโยชน์ของการอ่าน Markdown โดยตรงน่าจะไปถึงแค่นักพัฒนาซอฟต์แวร์บางส่วนทั่วโลกกับคนแปลก ๆ อีกสักห้าคนเท่านั้น
ดังนั้นถ้าชั่วชีวิตนี้ไม่ได้เห็น browser-native Markdown rendering ก็คงไม่แปลกใจ
ยังมีไลบรารีสำหรับ XSLT ที่ใช้ได้เมื่อต้องการเวอร์ชันใหม่กว่าการรองรับ native ของเบราว์เซอร์ และก็มีไลบรารีสำหรับฟอร์แมตต่าง ๆ อย่าง jpegxl ด้วย
ถ้าเป็น
html_content = html_content.replace('Minimum viable blog', title)แปลว่าทุกครั้งที่มีสตริงMinimum viable blogในบทความ มันจะถูกเปลี่ยนเป็นชื่อบทความปัจจุบันใช่ไหม? นี่เป็นบั๊กไม่ใช่เหรอ?โค้ดในบทความเป็น draft แรกที่ O1 สร้างขึ้นมา และสตริงนี้ถูกแทนที่ด้วย
{{ title }}แล้วผมทดลองกับ บล็อกแบบมินิมัล มาราว 15 ปี และมีเคล็ดลับที่ได้เรียนรู้อยู่บ้าง
แค่
const title = lines.match(/# (.+)/)[1]ก็พอแล้ว จึงหลีกเลี่ยง frontmatter ได้บล็อกของผมไม่เคยมีบทความเยอะจนต้องใช้ pagination, แท็ก, category หรือการจัดเรียง
JSX ถ้าใช้แฮ็กชวนสงสัยแบบ https://immaculata.dev/guides/enabling-jsx.html ก็ใช้เป็น string builder ฝั่ง server ล้วน ๆ ได้ค่อนข้างดี
ตอนนี้ GitHub Pages ก็ใช้ขั้นตอน build ใด ๆ แทน Jekyll ได้ง่ายขึ้นด้วยของอย่าง https://immaculata.dev/guides/using-gh-pages.html
highlight.js แทบจะเป็นราชาแห่ง code syntax highlighting ที่ง่ายมาก แค่เพิ่มสามบรรทัดใน HTML ก็พอ ส่วน shiki นั้นสวยแต่ช้า
ใช้เฟรมเวิร์กบล็อกแบบสแตติกมาตรฐานอย่าง Hugo/Zola + Cloudflare Pages ก็ง่าย
บล็อกของผมก็เป็นชุดขั้นต่ำที่เล็กกว่า 100KB และตรงตามเกณฑ์ทั้งหมดที่ผู้เขียนต้นฉบับไล่ไว้
ใช้ธีม Hugo Blog Awesome, ทำตามแนวทาง 512kb, ตรวจสอบขนาดหน้าแล้ว และตัดรูปภาพกับ JS ที่ไม่จำเป็นออก จริง ๆ แล้วก็ไม่ได้มีเยอะตั้งแต่แรก
อ้างอิง: https://512kb.club, https://radar.cloudflare.com/scan
เคยทำ “MVB” อยู่พักหนึ่ง ของผมเรียบง่ายกว่านี้อีก
แค่วางหน้า HTML หน้าเดียว เขียนบทความเป็นไฟล์
.txtแล้วอัปเดตหน้าแรกด้วยมือแม้จะค่อนข้างเยิ่นเย้อ แต่ผมว่าก็ยังง่ายกว่าการรับมือกับ เว็บสมัยใหม่
หลังจากนั้นย้ายไปทำแบบประณีตขึ้น ตอนนี้ใช้ Astro กับเว็บไซต์ส่วนตัวและบล็อก ซึ่งยอดเยี่ยมจริง ๆ
Astro อ้างบนหน้าแลนดิ้งว่าเป็นแพลตฟอร์มที่ดีที่สุดสำหรับ “ไซต์ที่เน้นคอนเทนต์” และหลังจากใช้มา 6 เดือนก็เห็นด้วย
มันให้แนวปฏิบัติที่ชัดเจนและทำตามง่ายสำหรับแทบทุกอย่างที่จำเป็นในการทำบล็อก และตัดส่วนที่ไม่จำเป็นออก
ลองทดลองใช้ Bun JS กับวิธีเขียน HTML ในสตริง JavaScript กับบางไซต์
Bun มีแฟล็ก
—hotที่สร้าง HTML แบบสแตติกใหม่เมื่อมีการเปลี่ยนแปลงIntelliJ IDE ตรวจจับคอมเมนต์
// language=htmlเหนือสตริง แล้วจัดฟอร์แมต HTML ข้างในและทำ syntax highlighting ให้ด้วยถ้าใช้ฟังก์ชัน JavaScript ล้วนแทนภาษาเทมเพลต ก็เขียนลอจิกที่ต้องการเองได้โดยไม่ต้องไปค้นหาว่าในภาษาเทมเพลตต้องทำอย่างไร
เบื่อเว็บไซต์ที่ใหญ่เทอะทะจนโหลดนาน เลยใช้แนวทางคล้ายกันมากกับบล็อกของผม: https://blog.borrego.dev
ซอร์ส: https://github.com/agubelu/blog