Kiến trúc danh mục JBake - Tầm nhìn và các trường hợp sử dụng
Đăng ngày 15 January 2026
Tầm nhìn Kiến trúc
Nguyên tắc chủ đạo
Kiến trúc dựa trên nguyên lý tách biệt các mối quan tâm (separation of concerns):
-
Nội dung: các tệp AsciiDoc được cấu trúc với siêu dữ liệu phong phú
-
Giới thiệu: các template Thymeleaf có thể tái sử dụng
-
Dữ liệu: mô hình được JBake trích xuất tự động từ các thuộc tính AsciiDoc
-
Phong cách: Bootstrap 5 để đảm bảo tính nhất quán về mặt hình ảnh
Lựa chọn chiến lược: AsciiDoc cho portfolio
Tại sao lại là AsciiDoc?
| Tiêu chí | Lợi thế |
|---|---|
Tính nhất quán |
Cùng định dạng với các bài viết blog |
Siêu dữ liệu |
Các thuộc tính có cấu trúc và có thể mở rộng ( |
Khả năng bảo trì |
Chỉnh sửa văn bản đơn giản, có thể quản lý phiên bản bằng Git |
Tính linh hoạt |
Có thể chứa nội dung phong phú (bảng, mã, hình ảnh) |
Tạo mẫu |
JBake tự động trích xuất các thuộc tính cho Thymeleaf |
Mô hình dữ liệu
Mỗi dự án portfolio là một tài liệu AsciiDoc với:
-
Siêu dữ liệu tiêu đề: thông tin có cấu trúc (khách hàng, thời lượng, công nghệ, v.v.)
-
Nội dung tài liệu : mô tả chi tiết, thách thức, giải pháp, kết quả
-
Thuộc tính tùy chỉnh: có tiền tố`project-*`cho việc trích xuất tự động
@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false
class ProjetAsciiDoc {
+titre: String
+jbake-type: "dự án"
+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 : phân tích
JBakeEngine --> ThymeleafTemplate : cung cấp dữ liệu
ThymeleafTemplate --> PortfolioPage : tạo ra
@enduml
Các trường hợp sử dụng chi tiết
UC1 : Thêm một mục vào danh mục hồ sơ (portfolio)
Lưu lượng định mức
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "Biên tập\nVăn bản" as editor participant "Tệp\nAsciiDoc" as file participant "JBake\nCông cụ" as jbake participant "Trang web\ntĩnh" as site dev -> editor : Tạo file mới activate editor editor -> file : portfolio/nouveau-projet.adoc activate file dev -> editor : Viết tiêu đề với metadata\n(titre, type=project, status=published,\nattributs project-*) dev -> editor : Viết nội dung câu chuyện\n(bối cảnh, thách thức, giải pháp) dev -> editor : Thêm hình ảnh vào assets/img/portfolio/ editor -> file : Lưu deactivate editor dev -> jbake : Thực hiện build (jbake -b) activate jbake jbake -> file : Đọc và phân tích jbake -> jbake : Trích xuất siêu dữ liệu jbake -> jbake : Chuyển đổi AsciiDoc → HTML jbake -> jbake : Áp dụng mẫu project.html jbake -> jbake : Thêm vào danh sách portfolio.html jbake -> site : Tạo các trang tĩnh deactivate jbake dev -> site : Kiểm tra kết quả activate site site --> dev : Hiển thị dự án deactivate site @enduml
Mẫu tệp cần tạo
Nhà phát triển tạo`content/portfolio/nom-projet.adoc`với một cấu trúc tiêu chuẩn hóa:
-
Tiêu đề với tất cả các thuộc tính bắt buộc
-
Các phần chuẩn hóa (Bối cảnh, Thách thức, Giải pháp, Kết quả)
-
Đặt tên hình ảnh nhất quán
Các điểm xác thực
-
Các thuộc tính bắt buộc hiện có (
jbake-type,jbake-status,project-thumbnail) -
Các hình ảnh được tham chiếu tồn tại trong`assets/img/portfolio/`
-
Quá trình build JBake thành công mà không có lỗi
-
Dự án xuất hiện trên trang portfolio
-
Trang chi tiết của dự án hiển thị chính xác
UC2 : Xóa một phần tử khỏi portfolio
Luồng định mức
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "Hệ thống\nTập tin" as fs participant "JBake\nĐộng cơ" as jbake participant "Trang web\ntĩnh" as site database "Bộ nhớ cache\nJBake" as cache dev -> fs : Xóa portfolio/projet-ancien.adoc activate fs fs --> dev : Tệp đã bị xóa deactivate fs dev -> fs : **(Tuỳ chọn) Xóa hình ảnh liên quan\nassets/img/portfolio/projet-ancien-*** activate fs fs --> dev : Hình ảnh đã bị xóa deactivate fs dev -> cache : Xóa cache JBake activate cache cache --> dev : Bộ nhớ đệm đã được xóa deactivate cache dev -> jbake : Xây dựng lại hoàn toàn (jbake -b) activate jbake jbake -> jbake : Máy quét nội dung/portfolio/ jbake -> jbake : Dự án không tồn tại → không được tạo jbake -> jbake : Tái tạo portfolio.html\n(không có dự án đã bị xóa) jbake -> site : Triển khai bản dựng mới deactivate jbake dev -> site : Kiểm tra activate site site --> dev : Dự án không có trong danh sách deactivate site @enduml
Chiến lược thay thế: lưu trữ
Thay vì xóa vĩnh viễn, có khả năng tạo một thư mục`content/portfolio/archive/`Vui lòng cung cấp nội dung cần dịch.
-
Di chuyển tệp thay vì xóa nó
-
Cho phép khôi phục dễ dàng
-
Giữ lịch sử Git rõ ràng hơn
Dọn dẹp tài nguyên
-
Kiểm tra các hình ảnh mồ côi trong`assets/img/portfolio/`
-
Xóa các hình ảnh không được tham chiếu bởi các dự án khác
-
Xóa bộ nhớ đệm JBake để tránh các tham chiếu ma
UC3 : Chuyển sang chưa xuất bản (draft)
Flux định mức
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "Tệp\nAsciiDoc" as file participant "JBake\nĐộng cơ" as jbake participant "Trang\ntĩnh" as site dev -> file : Mở portfolio/projet.adoc activate file dev -> file : Chỉnh sửa thuộc tính\n:jbake-status:đã xuất bản\n↓\n:jbake-status:nháp file --> dev : Đã được sao lưu deactivate file dev -> jbake : Xây dựng lại (jbake -b) activate jbake jbake -> file : Phân tích tệp tin jbake -> jbake : Phát hiện status=draft jbake -> jbake : Bỏ qua published_projects jbake -> jbake : Đừng tạo trang công khai note right Dự án vẫn tồn tại nhưng chưa được công bố end note jbake -> site : Tạo site (không có dự án này) deactivate jbake dev -> site : Kiểm tra portfolio activate site site --> dev : Dự án không có trong danh sách công cộng deactivate site @enduml
Các trạng thái có thể có
@startuml skinparam backgroundColor #FEFEFE [*] --> Draft : Création initiale Draft --> Published : Xác thực và công bố Published --> Draft : Rút tạm thời Draft --> Archived : Dự án đã bị bỏ rơi Published --> Archived : Dự án lỗi thời Archived --> [*] : Xóa vĩnh viễn Published --> Published : Cập nhật note right of Draft :jbake-status: nháp Không hiển thị công khai Hữu ích cho các dự án đang diễn ra end note note right of Published :jbake-status: published Hiển thị trên danh mục Được lập chỉ mục bằng JBake end note note right of Archived Đã di chuyển vào archive/ hoặc jbake-status: đã lưu trữ Chưa xuất bản nhưng vẫn được giữ end note @enduml
Các trường hợp sử dụng điển hình
-
Dự án đang trong quá trình soạn thảo: tạo bản nháp, xuất bản khi sẵn sàng
-
Dự án tạm thời bảo mật: chuyển sang bản nháp trong thời gian chờ khách hàng đồng ý
-
Cập nhật lớn: chuyển thành bản nháp, chỉnh sửa, xuất bản lại
-
A/B testing: nhân bản thành bản nháp, thử nghiệm, xuất bản phiên bản tốt nhất
Kiến trúc Templating
Chiến lược template có thể tái sử dụng
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
package "Templates Thymeleaf" {
component [index.html] as index
component [portfolio.html] as portfolio
component [project.html] as project
package "Partials" {
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 "dữ liệu JBake" {
database "published_projects" as data
database "content (dự án)" as content
}
index --> header
index --> footer
portfolio --> header
portfolio --> footer
portfolio --> card
data --> portfolio : Sự lặp lại
project --> header
project --> footer
project --> badge
project --> gallery
content --> project : dự án cá nhân
note right of card
Mảnh có thể tái sử dụng
để hiển thị một thẻ
dự án với :
- ảnh thu nhỏ
- tiêu đề
- thẻ
- những điểm nổi bật
end note
@enduml
Mẫu trích xuất dữ liệu
JBake tự động chuyển đổi các thuộc tính AsciiDoc thành các property có thể truy cập được trong Thymeleaf:
@startuml
skinparam backgroundColor #FEFEFE
rectangle "Tài liệu AsciiDoc" {
(":project-client: Acme Corp") as attr1
(":project-duration: 6 tháng") as attr2
(":project-tags: java, react") as attr3
}
rectangle "Mẫu JBake" {
(content['project-client']) as prop1
(content['project-duration']) as prop2
(content.tags) as prop3
}
rectangle "Mẫu Thymeleaf" {
(th:text="${project['project-client']}") as tmpl1
(th:text="${project['project-duration']}") as tmpl2
(th:each="tag : ${project.tags}") as tmpl3
}
attr1 --> prop1 : parsing
attr2 --> prop2 : parsing
attr3 --> prop3 : parsing
prop1 --> tmpl1 : binding
prop2 --> tmpl2 : binding
prop3 --> tmpl3 : binding
@enduml
Quy ước đặt tên
-
Thuộc tính dự án : tiền tố`project-*` (ex:
project-client,project-tech-stack) -
Tệp tin : kebab-case (ví dụ:`ecommerce-platform.adoc`)
-
Hình ảnh : tiền tố tên-dự-án (ví dụ:`ecommerce-platform-thumb.jpg`)
-
Templates : tên chức năng (ví dụ:`project-card.html`,
tech-badge.html)
Quy trình xuất bản
Luồng phát triển
@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false
class ProjetAsciiDoc {
+titre: String
+jbake-type: "dự án"
+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 : phân tích
JBakeEngine --> ThymeleafTemplate : cung cấp dữ liệu
ThymeleafTemplate --> PortfolioPage : tạo ra
@enduml
Môi trường
| Môi trường | Cách sử dụng | Trạng thái đã chấp nhận |
|---|---|---|
Địa phương |
Phát triển và xem trước |
bản nháp, đã xuất bản |
Staging |
Xác thực tiền sản xuất |
chỉ được xuất bản |
Sản xuất |
Trang công khai |
chỉ được xuất bản |
Khả năng mở rộng
Thêm các thuộc tính mới
Để làm phong phú mô hình dữ liệu, chỉ cần thêm các thuộc tính mới có tiền tố`project-*`Vui lòng cung cấp văn bản cần dịch.
-
project-awards: Giải thưởng và công nhận -
project-testimonial: Trích dẫn của khách hàng -
project-team-size: Quy mô đội ngũ -
project-budget-range: Khoảng ngân sách
Các thuộc tính này sẽ tự động khả dụng trong các template mà không cần thay đổi công cụ JBake.
Phân loại nâng cao
@startuml
skinparam backgroundColor #FEFEFE
object Projet {
project-category = "web"
project-subcategory = "thương mại điện tử"
project-industry = "bán lẻ"
project-complexity = "cao"
}
object Taxonomie {
categories : [web, mobile, data, devops]
subcategories : Map<category, List>
industries : [retail, finance, healthcare, ...]
complexities : [low, medium, high]
}
Projet --> Taxonomie : phân loại theo
note right of Taxonomie
Cho phép lọc đa tiêu chí
trong mẫu portfolio.html
thông qua JavaScript hoặc phía máy chủ
end note
@enduml
Thực hành Tốt nhất
Tổ chức tệp tin
-
Một tệp = một dự án: tránh trộn lẫn nhiều dự án
-
Hình ảnh trong thư mục riêng:`assets/img/portfolio/nom-projet/`
-
Hệ thống đặt tên nhất quán: tạo điều kiện thuận lợi cho việc tìm kiếm và bảo trì
-
Versioning Git : theo dõi đầy đủ các thay đổi
Quản lý nội dung
-
Trạng thái bản nháp mặc định: chỉ xuất bản khi đã sẵn sàng
-
Xem lại trước khi xuất bản: phê duyệt chất lượng và bảo mật
-
Siêu dữ liệu đầy đủ: điền tất cả các trường liên quan
-
Nội dung tường thuật phong phú: không giới hạn ở siêu dữ liệu
Hiệu năng
-
Tối ưu hóa hình ảnh: nén trước khi commit
-
Phân trang nếu cần thiết: nếu >20 dự án
-
Lazy loading : hình ảnh trong thư viện được tải theo yêu cầu
-
Bộ nhớ đệm trình duyệt : các header phù hợp cho assets
Kết luận
Kiến trúc này cho phép:
-
Đơn giản trong sử dụng: thêm một dự án = tạo một tệp văn bản
-
Tính linh hoạt: có thể mở rộng thông qua các thuộc tính mới
-
Khả năng bảo trì: tách biệt nội dung/trình bày
-
Khả năng truy xuất nguồn gốc: versioning Git đầy đủ
-
Tự động hóa: khả năng build và triển khai liên tục
Việc lựa chọn AsciiDoc đảm bảo tính nhất quán với phần còn lại của trang web, đồng thời cung cấp các siêu dữ liệu phong phú cần thiết cho một portfolio chuyên nghiệp.