1 điểm bởi GN⁺ 2025-06-28 | 1 bình luận | Chia sẻ qua WhatsApp
  • Nền tảng web hiện đang thiếu một API mẫu khai báo mà các nhà phát triển thực sự cần
  • Trong hầu hết các framework web hiện đại, templating là công nghệ cốt lõi, nhưng API DOM tiêu chuẩn lại không có cách an toàn và hiệu quả để tạo/cập nhật mẫu
  • Vì điều này, người dùng, nhà phát triển, framework, thậm chí cả bản thân nền tảng đều gặp bất tiện và các vấn đề suy giảm hiệu năng
  • Đây là thời điểm thích hợp để đưa vào API mẫu, vì kinh nghiệm từ framework gần đây và các tính năng JavaScript đã tích lũy đủ để việc triển khai và chuẩn hóa trở nên thực tế hơn
  • Bằng cách tổng hợp nhiều mô hình như định danh mẫu, tính phản ứng dựa trên signal, bài viết đưa ra định hướng cho API mẫu thế hệ tiếp theo

Tóm tắt đề xuất

  • Bài viết này giải thích bối cảnh và sự cần thiết của việc bổ sung API mẫu khai báo vào nền tảng web
  • API DOM rất mạnh, nhưng trong DOM tiêu chuẩn lại thiếu một API mẫu để tạo và cập nhật nhiều node một cách an toàn, hiệu quả dựa trên dữ liệu
  • Các framework lớn như React, Vue, Angular đều xem templating là cốt lõi, đồng thời mang lại nhiều lợi ích như năng suất phát triển, bảo mật, hiệu năng, phân tích tĩnh và render phía máy chủ
  • Do thiếu API mẫu, người dùng, nhà phát triển, framework và cả nền tảng đều phải chịu sự phức tạp không cần thiết, rủi ro bảo mật, suy giảm hiệu năng và rào cản tiếp cận
  • Tác giả cho rằng đây là thời điểm phù hợp để đưa API này vào, đồng thời đề xuất chuẩn hóa theo hướng từng bước dựa trên kinh nghiệm từ các framework hiện có và các tính năng JavaScript hiện đại

Sự cần thiết của template và các vấn đề hiện tại

  • API DOM là nền tảng dẫn dắt các khả năng động của web
  • Tuy nhiên, DOM tiêu chuẩn không có một phương thức templating khai báo để định nghĩa cây DOM từ dữ liệu một cách an toàn và cập nhật nó hiệu quả
  • Các framework web hiện đại (React, Vue, Angular, Svelte...) đều cung cấp templating khai báo
  • Những lý do khiến templating khai báo phổ biến gồm:
    • Mang lại tính dễ dùngkhả năng đọc hiểu tốt hơn so với API mệnh lệnh
    • Tăng cường bảo mật XSS. Dữ liệu trong template được escape tự động
    • Hiệu năng render hiệu quả và nhanh
    • Tăng năng suất phát triển nhờ phân tích tĩnh, kiểm tra kiểu, IntelliSense...
    • Hỗ trợ render phía máy chủ

Những vấn đề của tình trạng hiện nay

  • Người dùng: tải ban đầu chậm hơn do phải tải thư viện và độ trễ render. Kích thước mã phía client tăng làm UX xấu đi
  • Nhà phát triển: cần thư viện riêng (npm, CDN...) để dùng template. Rào cản gia nhập cao, phụ thuộc vào giải pháp không tiêu chuẩn
  • Framework: phải tự triển khai engine template. Tồn tại đánh đổi nặng nề giữa hiệu năng, tính năng và kích thước mã
  • Nền tảng: bất lợi khi cạnh tranh với ứng dụng native. Flutter, SwiftUI... đều cung cấp hệ thống template tích hợp sẵn

Vì sao bây giờ là thời điểm thích hợp

  • Các nỗ lực trước đây liên quan đến template (E4X, E4H, html template literal...) từng thất bại, nhưng thời điểm đó còn yếu ở khía cạnh cập nhật DOM
  • Gần đây, trong framework và cộng đồng, best practice cho API template đã được tích lũy đầy đủ
  • Có thể đề xuất API dựa trên JavaScript. Trong JS tiêu chuẩn hiện nay đã có tagged template literal
  • Nhu cầu thao tác DOM thuận tiện vẫn đang tiếp tục tăng ở cả lập trình viên vanilla JS lẫn cộng đồng web component
  • Các đề xuất primitive mức thấp như DOM Parts cũng đang song hành, nhưng API khai báo mức cao có thể mang lại giá trị lớn hơn và chỉ ra hướng phát triển rõ ràng hơn

Phân tích các ví dụ về cú pháp template tốt

  • Các hệ thống template chủ đạo (React-JSX, Vue, Svelte, Angular...) về bản chất đều dựa trên cú pháp rất giống nhau: markup + binding
  • Với template dựa trên JS API, thông thường biểu thức template sẽ trả về phần mô tả DOM, còn một hàm render riêng sẽ phản ánh nó vào DOM thực tế
  • Những nỗ lực kiểu cũ như E4X trả về chính DOM, nên mô hình cập nhật không tốt

Khả năng của API template dựa trên JavaScript

  • Có thể thiết kế API template thông qua tagged template literal mà không cần bổ sung tính năng JavaScript mới
  • Đã có nhiều minh chứng thực tế như JSX-to-Lit

Thảo luận về tích hợp JSX

  • Việc chuẩn hóa JSX đòi hỏi định nghĩa ngữ nghĩa phức tạp và runtime semantics. Bản thân JSX chỉ là cú pháp
  • JSX không tiêu chuẩn hiện nay chỉ là chuyển đổi cú pháp thuần túy, nên nếu sau này có API template tiêu chuẩn, có thể nối sang compiler chuyển đổi JSX -> template literal
  • Nếu về sau thực sự chuẩn hóa JSX, cũng dễ chuyển sang cấu trúc chấp nhận kiểu dữ liệu phù hợp với API template

Quan hệ với API template dựa trên HTML

  • Nhiều nhà phát triển và cộng đồng đang yêu cầu một hệ thống template HTML
  • Tuy nhiên, hệ thống dựa trên HTML đòi hỏi thiết kế cú pháp/biểu thức mới cho binding, ngôn ngữ biểu thức, câu lệnh điều khiển..., nên là công việc lớn hơn rất nhiều
  • Lý do các framework gần đây (như Lit) chuyển từ template HTML sang JS API cũng chính là như vậy
  • Vì thế, API template dựa trên JS có khả năng sẽ được đưa vào trước, rồi sau đó mở rộng dần sang HTML API

Sự trưởng thành của kinh nghiệm triển khai tính phản ứng (reactivity)

  • Nhiều mô hình reactivity như VDOM diffing (React), định danh mẫu (Lit), signal (fine-grained signals, Solid/Svelte/Vue...) đều đã được kiểm chứng
  • Cách tiếp cận dựa trên VDOM thì chậm hơn, trong khi sự kết hợp giữa định danh mẫumô hình signal cho tốc độ, hiệu quả và khả năng giải thích tốt hơn
  • Cách dựa trên signal yêu cầu mọi dữ liệu đều phải được bọc thành signal, nhưng vẫn có thể trộn với dữ liệu thông thường

Lộ trình phát triển và hiệu quả kỳ vọng

  • API template JS khai báo được đề xuất sẽ mang lại lợi ích trực tiếp cho vanilla JS, web component và cả framework mới
  • Nó cũng có thể được dùng trong các framework hiện có như một compile target, runtime backend hoặc API hỗ trợ trực tiếp
  • Hỗ trợ cả cách tiếp cận "re-rendering" lẫn reactivity dựa trên signal
  • Đồng thời tạo nền tảng để sau này mở rộng sang template khai báo dựa trên HTML và custom element khai báo
    • Phạm vi API hẹp và rõ ràng, cũng dễ liên kết với các API hiện có (ví dụ: DOM Parts)
  • Tuy nhiên, dù API và cú pháp bề mặt có vẻ đơn giản, phần triển khai bên dưới như DOM Parts và scheduler vẫn có phạm vi rộng, nên cần sự hợp tác trong chuẩn hóa và kiểm thử

Kết luận

  • Tác giả đang thảo luận đề xuất này trong GitHub issue và kêu gọi cộng đồng, bao gồm các kỹ sư nền tảng, cùng tham gia

1 bình luận

 
GN⁺ 2025-06-28
Ý kiến Hacker News
  • Lý do tôi thấy buồn cười khi ai đó nói “chúng ta biết cú pháp template tốt là gì” là vì thực ra chưa từng có sự đồng thuận rõ ràng ngay cả về tiêu chí đó. Tôi nghĩ với template, trải nghiệm trực quan quan trọng hơn góc nhìn mang tính ký hiệu. Đó cũng là lý do các công cụ như Dreamweaver ngày xưa thành công đến vậy. Nhiều nhà thiết kế cũng bắt đầu học bằng các công cụ như Photoshop, theo đúng cùng một logic đó. Tôi thấy hơi tiếc vì nỗ lực lần này giống như đang cố làm lại XSLT. Bản chất của bài toán templating là ghép một cấu trúc được thiết kế chưa tốt thành một kết quả được thiết kế tốt. Xa hơn nữa, còn có vấn đề biểu diễn các thực thể có liên kết với nhau nhưng không nằm trong cùng một cây, như labelfor. Nếu tôi có thể dùng phép màu, tôi chỉ mong đừng cố ép mọi thứ phải khớp một cách kỳ quặc với bố cục tài liệu tiêu chuẩn. Chỉ cần dùng absolute positioning cho tốt cũng có thể giải quyết hiệu quả rất nhiều bài toán UI, nên tôi khá thắc mắc vì sao người ta cứ lặp đi lặp lại việc cố ép máy móc phải gánh toàn bộ các phép toán đó

    • Tôi đồng ý với ý rằng chuyện này giống như đang làm lại XSLT. Dù tôi không thích XML, XSLT thực sự rất mạnh. Đây vẫn là tính năng còn được hỗ trợ rộng rãi trong trình duyệt. XML bộc lộ nhiều nhược điểm trong cấu hình hay IPC, nhưng khi kết hợp một ngôn ngữ đánh dấu tốt với sức mạnh biến đổi của XSLT thì lại là thứ chưa từng được khai thác đúng mức. Việc XSLT không phổ biến là vì nó là một DSL thực sự mang tính khai báo và hàm. Nhiều người nói tích cực về DSL, nhưng trên thực tế phần lớn chỉ là lớp bọc mỏng cho ngữ nghĩa thủ tục của một ngôn ngữ phổ biến. Một DSL được thiết kế tốt có thể xử lý việc phức tạp theo cách đơn giản, và tôi nghĩ vấn đề là mọi người không chịu bỏ công học nó

    • Bạn nói cú pháp template đúng nghĩa lấy tính trực quan làm cốt lõi, nên tôi muốn biết vì sao bạn đi đến kết luận đó. Theo tôi nghe giống như bạn đang không hài lòng với chính HTML+CSS, tức là cách nó được tạo ra. Tôi cũng tò mò vì sao lại nhắc đến absolute positioning. Nó chắc chắn hữu ích ở đúng chỗ cần dùng, nhưng nếu dùng cho toàn bộ layout thì ngược lại sẽ rất khó bảo trì, và dễ hỏng theo kích thước màn hình hoặc lượng nội dung. Ngay cả bố cục báo in cũng thực tế chứa rất nhiều yếu tố tinh tế về chữ và typography nên không thể chỉ giải quyết bằng absolute positioning. Khi làm CSS chuyên sâu, tôi đã nhiều lần gặp trường hợp layout ban đầu dựng bằng absolute positioning nhưng sau đó chuyển sang flex hay flow thì giải quyết vấn đề nhanh hơn và dễ hơn. Có thể tìm thấy ý nghĩa nếu dùng tốt calc() và đơn vị viewport, nhưng trên thực tế nếu nội dung hay viewport không hoàn toàn cố định thì absolute positioning không phải lựa chọn phù hợp

    • Tôi từng thấy lập luận rằng người ta đi đường vòng quá phức tạp chỉ để đạt lại cùng hiệu ứng mà lẽ ra có thể làm dễ và nhanh bằng absolute positioning, nhưng trên web có yêu cầu là tài liệu phải hiển thị tốt trên mọi kích thước, hướng và hiệu năng thiết bị. Ứng dụng thông thường như ứng dụng Windows không có nỗi lo này, còn ứng dụng di động cũng chỉ cần nghĩ đến vài cỡ màn hình đã được chuẩn hóa. Chỉ riêng web mới có đặc tính phải xử lý tất cả những điều đó

    • Tôi không nghĩ việc phản ứng mỉa mai với cụm “cú pháp template tốt” là thái độ đặc biệt lịch sự đối với người đang cố thúc đẩy tiến bộ. Và tôi nghĩ hiện nay đã có một cú pháp template tốt rồi, đó là jsx. Tôi không phải fan của React, nhưng tôi cho rằng jsx đã tạo ra một cuộc cách mạng trong phát triển web, và hầu hết các hệ thống template JS hiện nay gần như đều hội tụ về “template như một biểu thức”, “kết hợp thông qua lồng nhau”, và việc dùng JavaScript để xử lý luồng điều khiển

    • React và Svelte chỉ giống nhau ở bề mặt, còn cách hoạt động thực sự thì khá khác nhau. Điểm cốt lõi của React là một hàm JavaScript gần như bình thường trả về markup dạng JSX được đánh giá lười. Khác biệt chính là không có cú pháp template riêng cho vòng lặp hay render có điều kiện; tất cả đều được xử lý bằng JavaScript thông thường

  • Tôi liên tục học được rằng API và ABI đều tuyệt đối không bao giờ là thứ cuối cùng. Nhu cầu của ứng dụng không cố định mà luôn thay đổi theo thời gian, nên không tồn tại API hoàn hảo dùng mãi mãi. Đề xuất lần này là ví dụ rất điển hình. Ban đầu vấn đề được thư viện ở userland như React giải quyết, rồi cuối cùng đến lúc nó hạ xuống thành tiêu chuẩn. Polyfill cũng đi theo mô thức như vậy. Kể cả khi các đề xuất này thành công thì cuối cùng chúng cũng sẽ trở thành công nghệ cũ, và mọi người sẽ tìm cách mới để lách qua chúng. DOM API, ECMA, trình duyệt cũ... đều có chung số phận đó. Điều này khiến tôi suy nghĩ liệu có thể xem entropy kỹ thuật, khả năng mở rộng và chính cả tính tương thích ngược như những ca sử dụng tiêu chuẩn hay không

    • Việc thêm tính năng mới vào web standard cuối cùng tạo ra gánh nặng mã nguồn bảo trì khổng lồ, và khi xây dựng trình duyệt tuân theo tiêu chuẩn thì lượng mã phải triển khai cứ tăng mãi. Các dự án như Servo mỗi khi cố đuổi kịp đều lại rơi vào tình trạng chỉ chạy theo phần mở rộng mới. Tôi muốn nền tảng web có được mọi khả năng của môi trường native, trong phạm vi các ràng buộc về quyền riêng tư và sandbox. Tôi cũng muốn trải nghiệm dành cho lập trình viên thật tốt. Nhưng để biến giấc mơ đó thành hiện thực thì phải cân nhắc cái giá là độ phức tạp tăng lên. Tôi nghi ngờ liệu templating native đang được bàn lần này có thực sự nâng DX lên rõ rệt hay không

    • Nếu vẫn giữ tương thích ngược và không thay đổi giao diện, vậy chẳng phải việc quản lý phiên bản chính là thứ đảm nhiệm vai trò đó sao?

    • Có lập luận rằng theo thời gian người ta cứ phải vòng qua hoặc vá lại, nhưng trong quá trình đó cũng có hiệu ứng tích cực là năng lực nền tảng được nâng lên một bậc. Cập nhật dần dần vẫn rất đáng giá, ngay cả khi nhu cầu người dùng liên tục phát hiện ra khoảng trống và ca sử dụng mới

    • Tôi không đồng ý với nhận định rằng “API và ABI không bao giờ ổn định vĩnh viễn”. Ví dụ getElementById đã ổn định hơn 25 năm. Nói rằng API bất biến là điều bất khả thi nghe giống một sự buông xuôi cá nhân hơn, trong khi ngoài kia có vô số phản ví dụ. Nhu cầu thì là vô tận, vậy cứ thêm API mới là được. Không có lý do phải phá vỡ API đang hoạt động tốt

    • Trên web, một khi API đã công khai thì sẽ luôn có người dùng phụ thuộc vào đúng hình dạng đó suốt đời. Vì vậy dư chấn từ các quyết định cách đây 20 năm nhiều khi vẫn còn kéo dài đến hôm nay. Có thể thấy điều đó trong các trường hợp như “smooshgate”

  • Có ý kiến nhắc đến làn sóng reactive programming và cho rằng tầng userland đã thử nghiệm quá đủ trong lĩnh vực này, nên giờ có thể gom những ưu điểm từ nhiều cách tiếp cận để tạo ra một hệ thống tiêu chuẩn thực sự. Nhưng ở những nơi như Ryan Carniato/Solid JS, người ta vẫn đang khám phá các khả năng mới với signals, nên tôi nghĩ việc thăm dò vẫn chưa kết thúc. Vẫn còn rất nhiều chỗ để phát triển thêm

  • Web thực sự cần templating native, reactivity và data binding. Lượng CPU và băng thông bị lãng phí khi hàng tỷ người dùng trên toàn thế giới phải tải xuống, parse và chạy các framework nặng như React là điều vượt xa sức tưởng tượng

    • So với mức lãng phí tài nguyên khổng lồ của LLM và các phép toán mật mã, kiểu lãng phí này lại thấy chẳng đáng là bao

    • Ở TC39 đang có proposal liên quan đến signals, và nhờ đó mọi thứ đang tiến thêm một bước

    • Thực tế thứ cần cho phát triển chỉ là data binding hai chiều và một bản sao của jsx là đủ

    • React không phải là một hệ thống template

  • Khi theo dõi cuộc thảo luận về việc đưa một hệ thống template cấp cao vào web standard, tôi lại nghĩ thứ nên có trước là các API cấp thấp tích hợp trong trình duyệt. Gần như không thể khiến mọi người đồng thuận về một hệ thống template tiêu chuẩn. Ngược lại, chỉ cần trình duyệt cung cấp API cấp thấp để áp dụng diff lên DOM là đủ. Ví dụ sẽ rất hay nếu native có phương thức như: element.applyDiff(DocumentFragment | string, { method: 'innerHTML' | 'outerHTML' }). Nếu áp dụng diff theo cách này thì có thể cập nhật không phá hủy, đồng thời giữ nguyên focus hiện tại của element, giá trị input, trạng thái audio/video, v.v. Có các thư viện JS như Idiomorph, nhưng lời giải native nhiều khả năng sẽ nhanh hơn rất nhiều

    • Trong bài có dẫn link đến DOM parts proposal. Đề xuất này rất hữu ích như một API cấp thấp. Nó có thể không quá hợp với các framework dựa trên VDOM, nhưng với những framework khác thì nó giúp đơn giản hóa cách triển khai và cũng mở rộng không gian tối ưu hóa. Nếu thêm cả proposal về signals nữa thì tính hữu dụng ngay cả khi không có framework cũng sẽ cao
  • Tác giả bài viết lần này được giới thiệu là một người có kinh nghiệm ở đẳng cấp hàng đầu trong lĩnh vực liên quan. Ông từng đóng góp lớn cho Lit, Polymer, web components của Google và nhiều đặc tả DOM cốt lõi

    • Nhưng cũng có chỉ trích rằng rất nhiều đặc tả ông thúc đẩy lại tạo thêm nhiều vấn đề hơn. Để có một giải pháp nông và chưa được mài giũa hoàn toàn, người ta phải cần đến hơn 20 đặc tả web, và những việc vốn đã làm được ở userland lại bị tiêu chuẩn hóa theo cách quá phức tạp. Hơn nữa, cũng có nhắc đến việc từ 15 năm trước Safari đã chủ trương nhu cầu về cách tiếp cận mang tính khai báo nhưng đã bị phớt lờ
  • Thay vì cách làm kiểu JSX, tôi muốn một hướng cú pháp giống như cách Kotlin khái quát hóa DSL bằng receiver và builder. Cách này không chỉ hữu ích cho template HTML đơn giản mà còn có thể phát huy mạnh trong nhiều tầng component, cấu hình và nhiều bối cảnh khác nhau. Ý nghĩa thực sự của templating và data binding cuối cùng chỉ là một tập hàm tiêu chuẩn tận dụng các tính năng cú pháp như vậy, và điều này khá giống Jetpack Compose

    • Chỉ cần vài tính năng thực sự thiết yếu: vòng lặp, điều kiện cho thuộc tính, điều kiện cho node, v.v. Thực ra chỉ với những cấu trúc đó thôi cũng đã có thể dùng xuyên ngôn ngữ
  • Tôi không phải lúc nào cũng chắc templating mang tính khai báo tốt hơn jQuery. Tôi đã dùng React gần 10 năm, nhưng SPA của tôi càng phức tạp thì tôi lại càng nhớ cảm giác điều khiển DOM theo kiểu mệnh lệnh. Sự trừu tượng hóa DOM bị rò rỉ, và cuối cùng các mẫu đơn giản như “lần ghi cuối cùng thắng” lại còn rõ ràng hơn. Template khai báo được nói là để giải quyết chuyện này, nhưng ngay khi bạn bắt đầu chia sẻ trạng thái mutable giữa các component thì giới hạn của nó lộ ra quá nhanh

    • Cảm giác này cũng phần nào đến từ việc phía lập trình viên React xem chuyện gọi trực tiếp DOM API như một điều cấm kỵ. Dùng ref tích cực hoặc tìm rồi thao tác trực tiếp component qua id cũng không sao cả. Thực tế các thư viện form nhanh và ít rerender thường hoạt động theo kiểu này

    • Tôi không thích React lắm, nhưng tôi cũng không thấy có rào cản nào khi muốn thoát khỏi DOM khai báo để dùng innerHTML, ref, v.v. Điều khiển theo kiểu mệnh lệnh là khả thi, nhưng xét thực dụng thì không có nhiều việc mà phía khai báo thật sự không làm được. Cả attachShadow() hay showModal() cũng có thể được bọc theo kiểu khai báo khá dễ chỉ với thêm khoảng 10 dòng mã

  • Nếu proposal Records và Tuples có tiến triển, JSX có lẽ đã có thể dùng các cấu trúc đó để mang ngữ nghĩa mới, nhưng thực tế proposal này không chỉ dừng lại mà đã bị rút hẳn (xem issue). Thay vào đó nó được thay thế bằng composites proposal

  • Tôi nghĩ nên dừng các cuộc bàn luận về việc tiêu chuẩn hóa các tính năng cấp cao kiểu này. Thay vào đó, nên mở rộng các đặc tính cấp thấp và tập trung vào hướng có giá trị hơn cho việc triển khai thư viện phía trên. Nếu một đề xuất tiêu chuẩn không có ưu thế rõ ràng so với thư viện thì nó không có nhiều ý nghĩa. Theo tôi chỉ nên bắt đầu thảo luận tiêu chuẩn hóa sau khi thứ đó đã được kiểm chứng rộng rãi ít nhất 5–10 năm ở dạng thư viện