สถาปัตยกรรมพอร์ตโฟลิโอ JBake - วิสัยทัศน์และกรณีการใช้งาน
เผยแพร่เมื่อ 15 January 2026
วิสัยทัศน์ด้านสถาปัตยกรรม
หลักการนำทาง
สถาปัตยกรรมมีพื้นฐานอยู่บนหลักการของ การแยกความกังวล
-
เนื้อหา : ไฟล์ AsciiDoc ที่มีโครงสร้างพร้อมด้วยเมตาดาต้าที่อุดมสมบูรณ์
-
การนำเสนอ : เทมเพลต Thymeleaf ที่สามารถใช้ซ้ำได้
-
ข้อมูล : แบบจำลองที่ดึงออกโดยอัตโนมัติจาก JBake จากแอตทริบิวต์ของ AsciiDoc
-
Style : Bootstrap 5 เพื่อความสอดคล้องทางภาพ
ตัวเลือกเชิงกลยุทธ์: AsciiDoc สำหรับพอร์ตโฟลิโอ
| เกณฑ์ | ข้อได้เปรียบ |
|---|---|
ความสอดคล้อง |
รูปแบบเดียวกับบทความบล็อก |
ข้อมูลเมตา |
แอตทริบิวต์เชิงโครงสร้างและขยายได้`project-*`) |
ความสามารถในการบำรุงรักษา |
การแก้ไขข้อความแบบง่าย ๆ รองรับการควบคุมเวอร์ชันด้วย Git |
ความยืดหยุ่น |
อาจมีเนื้อหาที่อุดมสมบูรณ์ (ตาราง, โค้ด, รูปภาพ) |
การกำหนดเทมเพลต |
JBake ดึงแอตทริบิวต์โดยอัตโนมัติสำหรับ Thymeleaf |
โมเดลข้อมูล
แต่ละโครงการพอร์ตโฟลิโอเป็นเอกสาร AsciiDoc ที่มี :
-
ข้อมูลเมตาดาต้าในส่วนหัว : ข้อมูลที่จัดโครงสร้าง (ลูกค้า, ระยะเวลา, เทคโนโลยี ฯลฯ)
-
Corps du document : คำบรรยายเชิงเรื่องราว, ความท้าทาย, วิธีแก้ปัญหา, ผลลัพธ์
-
แอตทริบิวต์ที่กำหนดเอง : ต่อคำนำหน้า`project-*`เพื่อการสกัดอัตโนมัติ
@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false
class ProjetAsciiDoc {
+titre: String
+jbake-type: "โครงการ"
+jbake-status: published|draft
+jbake-date: Date
+jbake-tags: List<String>
--
+project-category: String
+project-client: String
+project-duration: String
+project-role: String
+project-thumbnail: String
+project-gallery: List<String>
+project-tech-stack: String
+project-highlights: List<String>
+project-demo-url: String
+project-github-url: String
--
+body: HTML (converti)
}
class JBakeEngine {
+parse(asciidoc)
+extractMetadata()
+convertToHTML()
}
class ThymeleafTemplate {
+portfolio.html
+project.html
+partials/project-card.html
}
class PortfolioPage {
+published_projects: List
+filtres: categories
}
ProjetAsciiDoc --> JBakeEngine : พาร์ส
JBakeEngine --> ThymeleafTemplate : ให้ข้อมูล
ThymeleafTemplate --> PortfolioPage : สร้าง
@enduml
การใช้งานโดยละเอียด
UC1 : เพิ่มไอเท็มลงในพอร์ตโฟลิโอ
ฟลักซ์โนมินัล
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "บรรณาธิการ\nTexte" as editor participant "ไฟล์\nAsciiDoc" as file participant "JBake\nEngine" as jbake participant "เว็บไซต์\nStatique" as site dev -> editor : สร้างไฟล์ใหม่ activate editor editor -> file : portfolio/nouveau-projet.adoc activate file dev -> editor : สร้างส่วนหัวพร้อมเมตาดาต้า\n(titre, type=project, status=published,\nattributs project-*) dev -> editor : เขียนเนื้อเรื่อง\n(contexte, défis, solutions) dev -> editor : เพิ่มรูปภาพใน assets/img/portfolio/ editor -> file : บันทึก deactivate editor dev -> jbake : เริ่มการบิลด์ (jbake -b) activate jbake jbake -> file : อ่านและวิเคราะห์ jbake -> jbake : ดึงข้อมูลเมตา jbake -> jbake : แปลง AsciiDoc → HTML jbake -> jbake : ใช้ template project.html jbake -> jbake : เพิ่มลงในรายการ portfolio.html jbake -> site : สร้างหน้าเว็บแบบคงที่ deactivate jbake dev -> site : ตรวจสอบผลลัพธ์ activate site site --> dev : แสดงโครงการ deactivate site @enduml
เทมเพลตไฟล์ที่จะสร้าง
ผู้พัฒนาสร้าง`content/portfolio/nom-projet.adoc`ด้วยโครงสร้างมาตรฐาน:
-
ส่วนหัวที่มีแอตทริบิวต์ที่จำเป็นทั้งหมด
-
ส่วนมาตรฐาน (บริบท, ความท้าทาย, วิธีแก้, ผลลัพธ์)
-
ชื่อเรียกภาพที่สอดคล้อง
จุดตรวจสอบความถูกต้อง
-
คุณสมบัติที่จำเป็นมีอยู่`jbake-type`,
jbake-status,project-thumbnail) -
ภาพที่อ้างถึงมีอยู่ใน`assets/img/portfolio/`
-
บิลด์ JBake สำเร็จโดยไม่มีข้อผิดพลาด
-
โครงการปรากฏบนหน้า portfolio
-
หน้าเฉพาะของโครงการแสดงผลอย่างถูกต้อง
UC2 : ลบรายการออกจากพอร์ตโฟลิโอ
ฟลักซ์มาตรฐาน
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "ระบบ\nFichiers" as fs participant "JBake\nEngine" as jbake participant "ไซต์\nStatique" as site database "แคช\nJBake" as cache dev -> fs : ลบ portfolio/projet-ancien.adoc activate fs fs --> dev : ไฟล์ถูกลบ deactivate fs dev -> fs : (Optionnel) ลบภาพที่เกี่ยวข้อง\nassets/img/portfolio/projet-ancien-* activate fs fs --> dev : รูปภาพถูกลบ deactivate fs dev -> cache : Nettoyer cache JBake activate cache cache --> dev : วิดีโอที่อยู่ในแคช deactivate cache dev -> jbake : การสร้างใหม่เต็มรูปแบบ (jbake -b) activate jbake jbake -> jbake : สแกน เนื้อหา/portfolio/ jbake -> jbake : ไม่มีโครงการ → ไม่ได้สร้าง jbake -> jbake : สร้างใหม่ portfolio.html\n(sans le projet supprimé) jbake -> site : ปรับใช้บิลด์ใหม่ deactivate jbake dev -> site : ตรวจสอบ activate site site --> dev : ไม่มีโครงการอยู่ในรายการ deactivate site @enduml
กลยุทธ์ทางเลือก: การจัดเก็บถาวร
แทนที่จะลบอย่างถาวร มีความเป็นไปได้ในการสร้างโฟลเดอร์`content/portfolio/archive/`:
-
ย้ายไฟล์แทนที่จะลบมัน
-
ทำให้สามารถกู้คืนได้อย่างง่ายดาย
-
รักษาประวัติ Git ให้ชัดเจนขึ้น
ทำความสะอาดทรัพยากร
-
ตรวจสอบภาพที่กำพร้าใน`assets/img/portfolio/`
-
ลบภาพที่ไม่ได้ถูกอ้างอิงโดยโครงการอื่น
-
ทำความสะอาดแคช JBake เพื่อหลีกเลี่ยงการอ้างอิงผี
UC3 : ตั้งเป็นร่าง (draft)
ฟลักซ์โนมินัล
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "ไฟล์\nAsciiDoc" as file participant "JBake\nEngine" as jbake participant "เว็บไซต์\nStatique" as site dev -> file : เปิดพอร์ตโฟลิโอ/projet.adoc activate file dev -> file : แก้ไขคุณสมบัติ\n:jbake-status: เผยแพร่\n↓\n:jbake-status: ร่าง file --> dev : บันทึกแล้ว deactivate file dev -> jbake : สร้างใหม่ (jbake -b) activate jbake jbake -> file : วิเคราะห์ไฟล์ jbake -> jbake : ตรวจสอบ status=draft jbake -> jbake : ยกเว้นจาก published_projects jbake -> jbake : อย่าสร้างหน้าสาธารณะ note right โครงการยังคงมีอยู่ แต่ไม่ได้รับการเผยแพร่ end note jbake -> site : สร้างเว็บไซต์ (โดยไม่มีโครงการนี้) deactivate jbake dev -> site : ตรวจสอบพอร์ตโฟลิโอ activate site site --> dev : ไม่พบโครงการในรายการสาธารณะ deactivate site @enduml
สถานะที่เป็นไปได้
@startuml skinparam backgroundColor #FEFEFE [*] --> Draft : Création initiale Draft --> Published : การตรวจสอบและการเผยแพร่ Published --> Draft : การถอนชั่วคราว Draft --> Archived : โครงการที่ถูกยกเลิก Published --> Archived : โครงการล้าสมัย Archived --> [*] : ลบอย่างถาวร Published --> Published : การอัปเดต note right of Draft :jbake-status: ร่าง ไม่ปรากฏต่อสาธารณะ มีประโยชน์สำหรับโครงการที่กำลังดำเนินอยู่ end note note right of Published :jbake-status: เผยแพร่ ปรากฏในพอร์ตโฟลิโอ จัดทำดัชนีโดย JBake end note note right of Archived ย้ายเข้าไปที่ archive/ หรือ jbake-status: archived ไม่ได้เผยแพร่ แต่ยังคงเก็บไว้ end note @enduml
กรณีการใช้งานทั่วไป
-
โครงการที่กำลังอยู่ในขั้นตอนการร่าง : สร้างเป็นฉบับร่าง, เผยแพร่เมื่อพร้อม
-
โครงการที่เป็นความลับชั่วคราว : ตั้งเป็นร่างจนกว่าจะได้ข้อตกลงจากลูกค้า
-
การอัปเดตหลัก : เปลี่ยนเป็นร่าง, แก้ไข, เผยแพร่ซ้ำ
-
A/B testing : ทำซ้ำเป็นร่าง, ทดสอบ, เผยแพร่เวอร์ชันที่ดีที่สุด
สถาปัตยกรรมของเทมเพลต
กลยุทธ์เทมเพลตที่สามารถใช้ซ้ำได้
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
package "เทมเพลท Thymeleaf" {
component [index.html] as index
component [portfolio.html] as portfolio
component [project.html] as project
package "ส่วนย่อย" {
component [header.html] as header
component [footer.html] as footer
component [project-card.html] as card
component [tech-badge.html] as badge
component [gallery.html] as gallery
}
}
package "ข้อมูล JBake" {
database "published_projects" as data
database "เนื้อหา (โครงการ)" as content
}
index --> header
index --> footer
portfolio --> header
portfolio --> footer
portfolio --> card
data --> portfolio : การทำซ้ำ
project --> header
project --> footer
project --> badge
project --> gallery
content --> project : โครงการส่วนบุคคล
note right of card
ส่วนที่สามารถนำกลับมาใช้ใหม่
เพื่อแสดงบัตร
ของโครงการ :
- ภาพขนาดย่อ
- ชื่อเรื่อง
- แท็ก
- ไฮไลท์
end note
@enduml
รูปแบบการสกัดข้อมูล
JBake จะทำการแปลงอัตโนมัติของคุณลักษณะ AsciiDoc เป็นคุณสมบัติที่สามารถเข้าถึงได้ใน Thymeleaf :
@startuml
skinparam backgroundColor #FEFEFE
rectangle "เอกสาร AsciiDoc" {
(":project-client: Acme Corp") as attr1
(":project-duration: 6 เดือน") as attr2
(":project-tags: java, react") as attr3
}
rectangle "แบบจำลอง JBake" {
(content['project-client']) as prop1
(content['project-duration']) as prop2
(content.tags) as prop3
}
rectangle "เทมเพลต Thymeleaf" {
(th:text="${project['project-client']}") as tmpl1
(th:text="${project['project-duration']}") as tmpl2
(th:each="แท็ก : ${project.tags}") as tmpl3
}
attr1 --> prop1 : การวิเคราะห์
attr2 --> prop2 : การวิเคราะห์
attr3 --> prop3 : การแยกวิเคราะห์
prop1 --> tmpl1 : การผูกมัด
prop2 --> tmpl2 : การผูกพัน
prop3 --> tmpl3 : การผูกมัด
@enduml
หลักเกณฑ์การตั้งชื่อ
-
คุณลักษณะโครงการ : คำนำหน้า`project-*` (ex:
project-client,project-tech-stack) -
ไฟล์ : kebab-case (ตัวอย่าง:`ecommerce-platform.adoc`)
-
Images : คำนำหน้าชื่อโครงการ (เช่น:`ecommerce-platform-thumb.jpg`)
-
Templates : ชื่อฟังก์ชั่น (ex:`project-card.html`,
tech-badge.html)
เวิร์กโฟลว์การเผยแพร่
กระบวนการพัฒนา
@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false
class ProjetAsciiDoc {
+titre: String
+jbake-type: "โครงการ"
+jbake-status: published|draft
+jbake-date: Date
+jbake-tags: List<String>
__
+project-category: String
+project-client: String
+project-duration: String
+project-role: String
+project-thumbnail: String
+project-gallery: List<String>
+project-tech-stack: String
+project-highlights: List<String>
+project-demo-url: String
+project-github-url: String
__
+body: HTML (converti)
}
class JBakeEngine {
+parse(asciidoc)
+extractMetadata()
+convertToHTML()
}
class ThymeleafTemplate {
+portfolio.html
+project.html
+partials/project-card.html
}
class PortfolioPage {
+published_projects: List
+filtres: categories
}
ProjetAsciiDoc --> JBakeEngine : แยกวิเคราะห์
JBakeEngine --> ThymeleafTemplate : ให้ข้อมูล
ThymeleafTemplate --> PortfolioPage : สร้าง
@enduml
สภาพแวดล้อม
| สภาพแวดล้อม | การใช้งาน | สถานะที่ยอมรับ |
|---|---|---|
ท้องถิ่น |
การพัฒนาและการแสดงตัวอย่าง |
ฉบับร่าง, เผยแพร่ |
การเตรียมความพร้อม |
การตรวจสอบก่อนการผลิต |
เผยแพร่เฉพาะ |
การผลิต |
เว็บไซต์สาธารณะ |
เผยแพร่เท่านั้น |
ความสามารถในการขยาย
การเพิ่มคุณสมบัติใหม่
เพื่อเสริมสร้างโมเดลข้อมูล ให้เพียงเพิ่มคุณสมบัติใหม่ที่มีการกำหนดชื่อขึ้นต้น`project-*`(No output provided)
-
`project-awards`รางวัลและการยอมรับ
-
`project-testimonial`ใบเสนอราคาลูกค้า
-
`project-team-size`ขนาดทีม
-
`project-budget-range`ช่วงงบประมาณ
คุณลักษณะเหล่านี้พร้อมใช้งานโดยอัตโนมัติในเทมเพลตโดยไม่ต้องแก้ไขเอนจิน JBake.
การจัดหมวดหมู่ขั้นสูง
@startuml
skinparam backgroundColor #FEFEFE
object Projet {
project-category = "เว็บ"
project-subcategory = "อีคอมเมิร์ซ"
project-industry = "ค้าปลีก"
project-complexity = "สูง"
}
object Taxonomie {
categories : [web, mobile, data, devops]
subcategories : Map<category, List>
industries : [retail, finance, healthcare, ...]
complexities : [low, medium, high]
}
Projet --> Taxonomie : จัดประเภทตาม
note right of Taxonomie
อนุญาตการกรองหลายเกณฑ์
ในเทมเพลต portfolio.html
ผ่าน JavaScript หรือฝั่งเซิร์ฟเวอร์
end note
@enduml
แนวทางการปฏิบัติที่ดี
การจัดระเบียบไฟล์
-
หนึ่งไฟล์ = หนึ่งโครงการ : หลีกเลี่ยงการผสมหลายโครงการ
-
รูปภาพในโฟลเดอร์เฉพาะ`assets/img/portfolio/nom-projet/`
-
การตั้งชื่ออย่างสม่ำเสมอ
-
Versioning Git : การติดตามการแก้ไขแบบครบถ้วน
การจัดการเนื้อหา
-
satus draft par défaut : publier seulement quand prêt becomes:
สถานะดราฟต์โดยค่าเริ่มต้น : เผยแพร่เฉพาะเมื่อพร้อม
-
Review ก่อนการเผยแพร่ : การตรวจสอบคุณภาพและความลับ
-
ข้อมูลเมตาครบถ้วน : กรอกฟิลด์ทั้งหมดที่เกี่ยวข้อง
-
เนื้อเรื่องที่อุดมสมบูรณ์ : อย่าจำกัดตัวเองอยู่ที่เมตาดาต้า
ประสิทธิภาพ
-
การบีบอัดภาพ : การบีบอัดก่อน commit
-
การแบ่งหน้าเมื่อจำเป็น : ถ้า >20 โครงการ
-
การโหลดเมื่อต้องการ : รูปภาพของแกลเลอรี่ที่โหลดเมื่อต้องการ
-
Cache เบราว์เซอร์ : headers ที่เหมาะสมสำหรับทรัพย์สิน
สรุป
สถาปัตยกรรมนี้ทำให้ :