2 điểm bởi GN⁺ 2025-05-05 | 1 bình luận | Chia sẻ qua WhatsApp
  • Chỉ với HTML thì không có tính năng include để đưa cùng một phần tử vào nhiều trang*
  • CSS có thể gọi CSS, JavaScript có thể gọi JS, nhưng HTML lại không thể nhập HTML, điều này khiến nhiều người thắc mắc
  • Để giải quyết vấn đề này, người ta sử dụng nhiều JavaScript, ngôn ngữ mẫu và trình tạo trang tĩnh khác nhau
  • Hiệu năng, bảo mật, độ trễ khi render, include vòng lặp cùng nhiều vấn đề phức tạp khác là rào cản cho việc đưa tính năng này vào
  • Nhiều lập trình viên muốn HTML có một tính năng include thuần khai báo, nhưng điều đó vẫn chưa được đưa vào tiêu chuẩn web

Thắc mắc về việc HTML không có tính năng Include

Vấn đề được đặt ra

  • Trong nhiều trang như index.html, about.html, contact.html, việc lặp đi lặp lại phần header dùng chung là khá bất tiện
  • Lập trình viên muốn tái sử dụng header đã định nghĩa một lần mà không bị trùng lặp

Những cách thay thế đã tồn tại

  • Dùng fetch API của JavaScript để tải HTML bên ngoài rồi chèn vào DOM
  • Server Side Include (SSI), include của PHP, trình tạo trang tĩnh và các ngôn ngữ mẫu đều là những cách giải quyết hiện có
  • Các phần tử HTML như <iframe><object> cũng có thể dùng, nhưng không phù hợp vì khả năng truy cập, hiệu năng và vấn đề cô lập style
  • Rốt cuộc, bản thân HTML không có cú pháp include đơn giản

Vì sao HTML không có tính năng này?

  • CSS và JS lần lượt có cú pháp @import hoặc import, nhưng HTML thì không
  • Tiêu chuẩn web nói chung thường tiếp nhận các tính năng được lập trình viên dùng nhiều, nhưng HTML include thì lại chưa
  • Những lý do được nêu ra gồm:
    • Có thể cản trở cách hoạt động của preload scanner
    • Dịch chuyển layout/nhấp nháy giao diện khi tải bất đồng bộ
    • Độ phức tạp khi xử lý include lồng nhau hoặc include vòng lặp
    • Sự phản đối liên quan đến việc tăng lưu lượng web hosting
    • Các vấn đề bảo mật (CORS, CSP, v.v.)xung đột về thời điểm của các sự kiện tải tài liệu
    • Hoặc đơn giản là mức ưu tiên thấp và chưa có đề xuất đủ rõ ràng

Thảo luận liên quan

  • Đang có thảo luận sôi nổi trong issue WHATWG trên GitHub #2791
  • Trước đây Chrome từng có HTML Imports, nhưng sau đó bị loại bỏ do các trình duyệt khác không hỗ trợ
  • Các cách tiếp cận thay thế như HTMX, Web Components, XSLT, SSI cũng được chia sẻ

Tóm tắt phản ứng của cộng đồng

  • Việc HTML phát triển theo hướng markup tĩnh và loại trừ các chức năng mang tính logic vẫn là một triết lý khá mạnh
  • Nhiều người muốn tính năng này, nhưng phần lớn là lập trình viên cá nhân khó lên tiếng trong quá trình tiêu chuẩn hóa
  • Cũng có phân tích cho rằng nếu không giải quyết được các bài toán hiệu năng, bảo mật, xử lý render, ngăn vòng lặp thì rất khó đưa vào
  • Có người cho rằng tính năng include bị thiếu đơn giản vì quan niệm rằng HTML chỉ nên đảm nhiệm “kết quả”

Kết luận

  • Cho đến nay, HTML vẫn chưa có tính năng include thuần túy, và người dùng phải thay thế bằng nhiều công cụ hay ngôn ngữ bên ngoài
  • Tuy vậy, nhiều lập trình viên vẫn kỳ vọng vào một cấu trúc tái sử dụng đơn giản dựa trên HTML

1 bình luận

 
GN⁺ 2025-05-05
Ý kiến Hacker News
  • Về mặt lịch sử, HTML là một ứng dụng của SGML, và SGML có hỗ trợ tính năng include. Bạn có thể định nghĩa một “entity” mới và tạo một entity “system”, rồi tham chiếu đến nó sau này để thay thế
    • Đã có nhiều nỗ lực nhằm đơn giản hóa HTML vì độ phức tạp của SGML, và trong quá trình đó các tính năng như vậy đã bị loại bỏ
  • Vào cuối những năm 90, đã có những nỗ lực để giải quyết vấn đề này. Với vai trò quản trị viên web của trang Analog Science Fiction, tôi đã tạo ra nhiều trang tĩnh có cùng header và sidebar. Vì vậy tôi đã phát hiện ra tính năng server-side include của Apache. Đó là cách để duy trì nguyên tắc DRY trước cả khi tôi biết đến nguyên tắc này
    • Vấn đề này liên tục được giải quyết lặp đi lặp lại bằng nhiều cách. Với những người nói rằng iframe là đủ, thì iframe không tự co giãn theo nội dung. Các giải pháp server-side thì cần có máy chủ. Tại sao lại không có một cách đơn giản ở phía client? Tôi nghĩ đó là một câu hỏi hợp lý
  • Đã từng có một đề xuất tính năng tên là HTML Imports. Nó được tạo ra như một phần của Web Components
    • HTML Imports là cách để nhúng và tái sử dụng một tài liệu HTML trong tài liệu HTML khác
    • Google đã triển khai đặc tả được đề xuất này trong Blink, nhưng các công ty khác phản đối vì nhiều lý do khác nhau. Mozilla lo ngại về độ phức tạp khi triển khai, các vấn đề bảo mật và sự chồng chéo với module ES6. Do không có sự ủng hộ từ các nhà cung cấp, đề xuất này đã chính thức bị dừng
  • Netscape 4 có một tính năng gọi là inflow layers
    • Tên của tính năng này là transclusion. Nó là một phần của Project Xanadu và ban đầu được xem là một tính năng quan trọng của hypertext
    • MediaWiki sử dụng transclusion rất rộng rãi. Đôi khi wiki mang lại cảm giác như hình thức hypertext đích thực
  • Một frameset đúng nghĩa (không phải iframe) từ lâu đã được thiết kế để thực hiện kiểu chức năng này. Ít nhất thì nó tự mở rộng khá tốt và người dùng có thể thay đổi kích thước
    • Có rất nhiều chỉ trích nhắm vào frame, nhưng nó đã được triển khai thành công cho những thứ hữu ích như tài liệu API của Java
    • Tôi nghĩ frameset không được duy trì vì nó không mang lại đủ sự linh hoạt cho giới thiết kế. Trên thiết bị di động ngày nay, frameset có lẽ cũng không hoạt động tốt
  • Tính năng “Includes” được xem là phía server, được xử lý bên ngoài trình duyệt web. HTML là phía client và chỉ là một cú pháp đánh dấu đơn giản chứ không phải ngôn ngữ lập trình
    • Đây là một vấn đề đã được giải quyết. Vấn đề “Includes” là cách mà mọi sinh viên thiết kế web học PHP. Trong hầu hết các CMS, “Includes” trở thành “template partial”, và đó là một trong những thứ đầu tiên được giải thích trong tài liệu
    • Không cần phải dùng “Includes” chỉ với riêng HTML. HTML là một định dạng trình bày và không làm được gì thú vị nếu thiếu CSS và JS
  • Tính năng include trong HTML có nhiều vấn đề khác nhau
    • Nếu main.html nhúng child/include1.html, và child/include1.html có liên kết src="include2.html", thì khi người dùng bấm vào liên kết đó họ nên đi tới đâu? Nếu đi tới include2.html, thì trang đó sẽ thiếu tất cả những phần khác. Nếu đi tới main.html, thì làm sao chỉ định rằng lần này dùng include2.html chứ không phải include1.html?
    • Theo chiều ngược lại, article1.html, article2.html, article3.html v.v. có thể mỗi trang đều nhúng header.html, footer.html, navi.html. Nhưng nếu muốn thêm comments.html vào mọi bài viết thì bạn vẫn phải sửa tất cả các bài, và cuối cùng lại quay về việc tạo bài dựa trên template, khiến trình duyệt không cần hỗ trợ include nữa
    • Nếu phần header cần biết tiêu đề, hoặc footer muốn có liên kết trước/sau, thì sẽ cần một cách để truyền thông tin này giữa các phần include; rốt cuộc bạn lại phải tạo trang hoàn chỉnh, và include không phải là lời giải
    • Include trong HTML về thực tế sẽ không hữu ích cho phần lớn các trường hợp sử dụng
  • WHATWG có một issue công khai về vấn đề này
    • Tính năng include phía client cho HTML
  • HTML từng có khả năng include, nhưng đã mất đi sự phổ biến
    • Thuật ngữ “include” thực ra là một tính năng của XML và cũng là thứ bài viết đang muốn nói tới. HTML đã có một cách tiếp cận thay thế từ trước cả XML. Cách đó là frame. Frame cung cấp nhiều tính năng hơn XML include, và vì thế HTML đã không nhận thêm tính năng đó. Frame dần mất phổ biến do bị lạm dụng, các vấn đề bảo mật, khả năng truy cập và nhiều vấn đề khác