10 điểm bởi GN⁺ 2025-10-11 | 2 bình luận | Chia sẻ qua WhatsApp
  • Khi dùng HTMX, có thể giảm khoảng 70% lượng mã, nhưng lại gặp vấn đề đồng bộ giữa các UI cùng với sự gia tăng độ phức tạp của quản lý trạng thái frontend
  • Sau khi áp dụng Datastar, việc phát triển ứng dụng đa người dùng thời gian thực trở nên dễ bảo trì hơn với cấu trúc mã gọn gàng mà không cần WebSockets
  • Trong khi HTMX phân tán logic hành vi xoay quanh các thuộc tính HTML, Datastar nâng cao tính nhất quán và khả năng bảo trì của logic thông qua mô hình cập nhật do máy chủ điều khiển
  • API của Datastar có ít thuộc tính hơn, mang lại cảm giác tăng độ dễ đọc và năng suất cho mã nguồn
  • Datastar tích cực tận dụng các công nghệ web native như Server-Sent Events(SSE), Web Components, CSS View Transitions để hỗ trợ cộng tác thời gian thực và cấu trúc thành phần có thể tái sử dụng

Giới thiệu và động lực

Những vấn đề dẫn tới việc chuyển đổi

  • Trong lúc chuẩn bị cho bài trình bày tại FlaskCon 2025, tác giả đã cố đồng bộ UI bằng cách kết hợp HTMX với AlpineJS nhưng gặp phải vấn đề đồng bộ giao diện
    • Hai thư viện này là các công cụ tách biệt do những nhà phát triển khác nhau tạo ra nên không thể giao tiếp trực tiếp với nhau, buộc lập trình viên phải tự đảm nhận phần tích hợp
    • Trong quá trình khởi tạo component ở nhiều thời điểm khác nhau và điều phối sự kiện, lượng mã cần viết và thời gian debug nhiều hơn dự kiến
  • Tác giả chú ý tới việc Datastar tích hợp chức năng của cả hai thư viện mà vẫn có kích thước dưới 11KB, nên đã thử dùng
    • Điều này có lợi cho hiệu năng tải trang đối với người dùng thiết bị di động

Thiết kế API tốt hơn của Datastar

  • API của Datastar mang lại cảm giác nhẹ hơn rất nhiều so với HTMX, và số lượng thuộc tính (attribute) cần thêm để đạt được kết quả mong muốn cũng ít hơn
  • HTMX cần nhiều thuộc tính trong hầu hết các tương tác
    • Định nghĩa URL, chỉ định phần tử đích và cách xử lý phản hồi đều được cấu hình bằng các thuộc tính riêng
    • Thông thường phải dùng 2~3 thuộc tính mỗi lần, đôi khi còn phải lần theo chuỗi kế thừa để hiểu cách thuộc tính hoạt động
    <a hx-target="#rebuild-bundle-status-button"  
       hx-select="#rebuild-bundle-status-button"  
       hx-swap="outerHTML"  
       hx-trigger="click"  
       hx-get="/rebuild/status-button"></a>  
    
  • Datastar thường chỉ cần một thuộc tính duy nhất để triển khai cùng chức năng
    <a data-on-click="@get('/rebuild/status-button')"></a>  
    
    • Ngay cả khi xem lại mã sau vài tháng, vẫn có thể dễ dàng hiểu cách nó hoạt động

Khác biệt trong nguyên lý hoạt động

  • Trong khi HTMX là thư viện frontend với mục tiêu mở rộng đặc tả HTML, thì Datastar là thư viện do máy chủ điều khiển, hướng tới xây dựng các ứng dụng cập nhật thời gian thực hiệu năng cao dựa trên web native
  • HTMX định nghĩa hành vi bằng cách thêm thuộc tính vào phần tử kích hoạt yêu cầu, và ngay cả khi cập nhật một phần tử ở rất xa trên trang, logic vẫn bị phân tán qua nhiều lớp
  • Datastar để máy chủ quyết định cần thay đổi điều gì, từ đó tập trung toàn bộ logic cập nhật vào một chỗ
  • Ví dụ với HTMX

    <div>  
      <div id="alert"></div>  
        <button hx-get="/info"   
                hx-select="#info-details"   
                hx-swap="outerHTML"  
                hx-select-oob="#alert">  
            Get Info!  
        </button>  
    </div>  
    
    • Khi nhấn nút, một yêu cầu GET được gửi tới /info, thay thế nút bằng phần tử có ID info-details trong phản hồi, đồng thời thay thế phần tử có cùng ID alert trên trang bằng phần tử alert trong phản hồi
    • Nút phải biết quá nhiều thông tin, và vì cần biết trước những gì máy chủ sẽ trả về nên nguyên tắc "locality of behavior" của HTMX bị suy yếu
  • Cách tiếp cận được cải thiện của Datastar

    <div>  
        <div id="alert"></div>  
        <button id="info-details"  
        data-on-click="@get('/info')">  
            Get Info!  
        </button>  
    </div>  
    
    • Máy chủ trả về một chuỗi HTML chứa hai phần tử gốc có cùng ID tương ứng
      <p id="info-details">These are the details you are looking for…</p>  
      <div id="alert">Alert! This is a test.</div>  
      
    • Đây là một lựa chọn đơn giản và có hiệu năng tốt

Tư duy ở cấp độ component

  • Cách tiếp cận tốt hơn là xem HTML như component
  • Xác định bản chất của component đó
    • Cách người dùng lấy thêm thông tin về một mục cụ thể
    • Khi người dùng bấm nút, thông tin sẽ hiện ra, hoặc nếu không có thông tin thì lỗi sẽ được render; dù theo cách nào thì component cũng chuyển sang trạng thái tĩnh
  • Tách component theo từng trạng thái

    • Trạng thái placeholder:
      <!-- info-component-placeholder.html -->  
      <div id="info-component">  
          <button data-on-click="@get('/product/{{product.id}}/info')">  
              Get Info!  
          </button>  
      </div>  
      
    • Trạng thái hiển thị thông tin:
      <!-- info-component-get.html -->  
      <div id="info-component">  
          {% if alert %}<div id="alert">{{ alert }}</div>{% endif %}  
          <p>{{product.additional_information}}</p>  
      </div>  
      
    • Khi máy chủ render HTML, Datastar sẽ tự động cập nhật trang
    • Tư duy ở cấp độ component giúp ngăn việc rơi vào trạng thái sai hoặc làm mất trạng thái của người dùng

Cập nhật đồng thời nhiều component

  • Một điểm gây ấn tượng trong bài trình bày của David Guillot là khi ứng dụng cập nhật số lượng mục yêu thích, nó đồng thời cập nhật cả component đã thay đổi lẫn phần tử đếm nằm rất xa trên trang
    • Với HTMX, điều này đòi hỏi kích hoạt sự kiện JavaScript, rồi từ đó lại kích hoạt component ở xa gửi một yêu cầu GET
  • Datastar có thể cập nhật đồng thời nhiều component ngay cả trong một hàm đồng bộ
  • Ví dụ giỏ hàng

    • Component thêm vào giỏ hàng:
      <form id="purchase-item"  
            data-on-submit="@post('/add-item', {contentType: 'form'})">"  
      >  
        <input type=hidden name="cart-id" value="{{cart.id}}">  
        <input type=hidden name="item-id" value="{{item.id}}">  
        <fieldset>  
          <button data-on-click="$quantity -= 1">-</button>  
          <label>Quantity  
            <input name=quantity type=number data-bind-quantity value=1>  
          </label>  
          <button data-on-click="$quantity += 1">+</button>  
        </fieldset>  
        <button type=submit>Add to cart</button>  
        {% if msg %}  
          <p class=message>{{msg}}</p>  
        {% endif %}  
      </form>  
      
    • Component hiển thị số lượng trong giỏ:
      <div id="cart-count">  
          <svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">  
              <use href="#shoppingCart">  
          </svg>  
          {{count}}  
      </div>  
      
    • Trong Django, có thể cập nhật cả hai component trong cùng một yêu cầu:
      from datastar_py.consts import ElementPatchMode  
      from datastar_py.django import (  
          DatastarResponse,  
          ServerSentEventGenerator as SSE,  
      )  
      
      def add_item(request):  
          # important state update omitted  
          return DatastarResponse([  
              SSE.patch_elements(  
                  render_to_string('purchase-item.html', context=dict(cart=cart, item=item, msg='Item added!'))  
              ),  
              SSE.patch_elements(  
                  render_to_string('cart-count.html', context=dict(count=item_count))  
              ),  
          ])  
      

Triết lý web native

  • Thông qua cộng đồng Datastar trên Discord, tác giả hiểu rằng Datastar không chỉ là một script trợ giúp đơn giản mà là một triết lý xây dựng ứng dụng dựa trên các primitive cốt lõi của web
  • Trong khi HTMX cố mở rộng đặc tả HTML, Datastar quan tâm hơn tới việc thúc đẩy áp dụng các tính năng web native
    • CSS view transitions
    • Server-Sent Events
    • Web Components, v.v.
  • Tác giả đã đạt được kết quả lớn khi refactor các component AlpineJS phức tạp thành Web Components đơn giản để tái sử dụng ở nhiều nơi
  • Đây là một mẫu rất tốt để đạt được tính cục bộ hành vi cao và khả năng tái sử dụng thông qua tạo phần tử HTML tùy biến, ngay cả khi không dùng các công cụ như React

Cập nhật thời gian thực cho ứng dụng đa người dùng

  • Những ứng dụng có cộng tác như tính năng hạng nhất sẽ khác biệt so với các ứng dụng khác, và Datastar giải quyết đúng bài toán này
  • Phần lớn lập trình viên HTMX hoặc polling để lấy thông tin từ máy chủ, hoặc viết mã WebSocket tùy biến làm tăng độ phức tạp
  • Datastar dùng Server-Sent Events(SSE), một công nghệ web đơn giản, để máy chủ "đẩy" cập nhật tới các client đang kết nối
    • Khi người dùng thêm bình luận hoặc trạng thái thay đổi, máy chủ cập nhật trình duyệt ngay lập tức với lượng mã bổ sung tối thiểu
    • Có thể xây dựng dashboard thời gian thực, bảng quản trị và công cụ cộng tác mà không cần JavaScript tùy biến
  • Nếu kết nối client bị gián đoạn, trình duyệt sẽ tự động thử kết nối lại, không cần thêm mã
    • Máy chủ cũng có thể được thông báo về "sự kiện nhận được gần nhất"

Tránh độ phức tạp quá mức

  • Cộng đồng Datastar trên Discord giúp tác giả hiểu rõ tầm nhìn của Datastar đối với việc xây dựng ứng dụng web
    • Cập nhật UI theo kiểu push
    • Giảm độ phức tạp
    • Xử lý các tình huống cục bộ phức tạp bằng các công cụ như Web Components
  • Cộng đồng cũng giúp người dùng mới nhận ra khi họ đang tiếp cận vấn đề theo cách quá phức tạp

Những mẹo chính

  • Đừng ngại render lại toàn bộ component rồi gửi đi
    • Cách này dễ hơn và không ảnh hưởng lớn tới hiệu năng
    • Có thể đạt tỷ lệ nén tốt hơn, và trình duyệt phân tích chuỗi HTML rất nhanh
  • Máy chủ là nguồn chân lý của trạng thái và mạnh hơn trình duyệt
    • Hãy để máy chủ xử lý phần lớn trạng thái; có thể bạn sẽ không cần nhiều reactive signal như tưởng tượng
  • Web Components rất phù hợp để đóng gói logic vào các phần tử tùy biến có tính cục bộ hành vi cao
    • Hiệu ứng trường sao trong phần header của website Datastar là một ví dụ điển hình
    • Phần tử <ds-starfield> đóng gói toàn bộ mã cho hoạt ảnh trường sao và lộ ra ba thuộc tính để thay đổi trạng thái bên trong
    • Datastar điều khiển các thuộc tính đó khi input dạng range thay đổi hoặc khi chuột di chuyển trên phần tử

Khả năng vượt qua giới hạn

  • Điều thú vị nhất là tiềm năng mà Datastar mở ra
  • Cộng đồng thường xuyên tạo ra các dự án vượt xa những giới hạn mà các nhà phát triển dùng công cụ khác thường gặp phải

Các trường hợp đáng chú ý

  • Bản demo giám sát cơ sở dữ liệu trong trang ví dụ
    • Tận dụng Hypermedia để cải thiện đáng kể tốc độ và mức dùng bộ nhớ so với bản demo từng được trình bày tại hội nghị JavaScript
  • 1 tỷ checkbox của Anders Murphy
    • Khi thử nghiệm 1 triệu checkbox vượt quá năng lực máy chủ, anh đã dùng Datastar để triển khai 1 tỷ checkbox trên một máy chủ giá rẻ
  • Một ứng dụng web hiển thị dữ liệu từ toàn bộ các trạm radar tại Mỹ
    • Khi tín hiệu của radar thay đổi, điểm tương ứng trên UI thay đổi trong vòng dưới 100 mili giây
    • Hơn 800.000 điểm được cập nhật mỗi giây, và người dùng có thể tua ngược tới tối đa 1 giờ trước đó với độ trễ dưới 700 mili giây
    • Việc điều này khả thi trong một ứng dụng Hypermedia cho thấy những gì Datastar có thể mang lại

Trải nghiệm sử dụng hiện tại

  • Tác giả vẫn đang ở giai đoạn khám phá Datastar, và có thể nhanh chóng, dễ dàng triển khai xử lý AJAX cập nhật UI cho các chức năng tiêu chuẩn mà HTMX thường đảm nhiệm
  • Đồng thời đang học và thử nghiệm nhiều mẫu khác nhau để đạt được nhiều hơn với Datastar
  • Trong nhiều thập kỷ, tác giả luôn quan tâm tới cách mang lại trải nghiệm người dùng tốt hơn bằng cập nhật thời gian thực, và đánh giá cao việc Datastar cho phép cập nhật theo kiểu push ngay cả trong mã đồng bộ
  • Khi mới bắt đầu dùng HTMX, tác giả từng cảm thấy rất phấn khích; nhưng sau khi chuyển sang Datastar, không thấy mình mất đi điều gì, mà ngược lại cảm giác như nhận được nhiều hơn rất nhiều
  • Nếu bạn từng thấy vui khi dùng HTMX, bạn có lẽ sẽ cảm nhận lại bước nhảy tương tự với Datastar — như thể khám phá lại điều mà web vốn nên làm

2 bình luận

 
GN⁺ 2025-10-11
Ý kiến trên Hacker News
  • Tôi cảm thấy biết ơn vì Chris đã dám bước ra khỏi vùng an toàn của mình để thử thách bản thân và chia sẻ trải nghiệm đó với chúng ta. Tôi có thể hơi thiên vị vì đã làm web app bằng htmx suốt 4 năm nay, nhưng tôi nghĩ điều này cho thấy khác biệt kiến trúc chính giữa Datastar và htmx: htmx là hướng HTML, còn Datastar là hướng máy chủ. Đúng là API phía client đơn giản hơn, nhưng đó là vì logic phía server trở nên phức tạp hơn. Ví dụ, nếu phần tử HTML không có thông tin về việc phải chèn fragment được trả về từ server vào đâu, thì thông tin đó phải được ghi nhận ở phía server, nên độ phức tạp nhất định phải tồn tại ở một bên nào đó. Việc chọn kiến trúc có vẻ là vấn đề sở thích. Trong ví dụ, lập luận về “less attributes” (ít thuộc tính hơn) cũng chưa hẳn công bằng 100%, vì có cả những thuộc tính trong htmx vốn là tùy chọn cũng được đưa vào ví dụ; chẳng hạn bỏ hx-trigger="click" đi là đã giảm được 20% số thuộc tính. Và nếu viết HTML có tính truy cập tốt hơn, như dùng <button> thay vì <span>, thì sẽ thuyết phục hơn. Cuối cùng, điểm mạnh của Datastar có vẻ là nó đi kèm sẵn các tính năng kiểu Alpine hay Stimulus, và điều đó thực sự rất ấn tượng
    • Tôi nghĩ với Datastar thì độ phức tạp giảm đi rất nhiều, vì để cập nhật theo thời gian thực các phần khác trên trang, bạn không cần tự triển khai riêng cơ chế eventing mà có thể tải toàn bộ xuống một lần rồi cập nhật luôn. Tất nhiên, tùy tình huống thì cách tiếp cận dựa trên sự kiện hoặc tải sau có thể tốt hơn
    • Tôi thấy nhận xét “giống như có sẵn các tính năng của Alpine hay Stimulus trong HTMX” nên đang cân nhắc làm dự án cá nhân bằng HTMX. Không biết có tài liệu nào giải thích rằng thực sự cần thêm thư viện như AlpineJS hay Stimulus hay không
    • Có tranh luận rằng nếu phần tử HTML không có thông tin về vị trí chèn fragment thì server phải biết điều đó, nhưng tôi cũng tự hỏi liệu trong trường hợp này frontend có nhẹ và nhanh hơn không. Nhất là khi có rất nhiều phần tử thì lại càng như vậy đúng không?
    • Cấu trúc này khá giống framework Seaside của Pharo. Khi công ty chúng tôi làm ứng dụng B2B bằng Pharo, trạng thái UI được quản lý ở backend nên có rất nhiều qua lại giữa frontend và backend. Với B2B nơi thời gian thực hay độ trễ không quá quan trọng thì ổn, nhưng với ứng dụng B2C cần khả năng mở rộng cao thì không phù hợp
  • Với tư cách là người đã trực tiếp dùng cả Datastar lẫn HTMX, tôi vẫn chưa rõ khi viết app bằng Datastar thì sẽ khác biệt lớn ở điểm nào. Tôi đang dùng FastAPI, HTMX, Alpine.js và SSE cùng nhau để hiển thị log theo thời gian thực, cập nhật trạng thái deploy, v.v. Khi xem các ví dụ của Datastar, tôi không thấy rõ điểm nào đơn giản hơn cấu trúc này. (Xem mã: devpush SSE partial). Trước đây tôi cũng từng thử Web Components khi phát triển Basecoat, nhưng vì đủ loại lý do như vấn đề style và quản lý trạng thái nên cuối cùng lại quay về HTML/CSS/JS truyền thống. devpu.sh, basecoatui.com
    • Ngay cả trong HTMX, khi cân nhắc khả năng mở rộng chức năng như Datastar thì nhiều lúc cứ cập nhật nguyên cả danh sách lại đơn giản hơn. Thay vì cố cập nhật trạng thái từng deployment riêng lẻ, cập nhật cả danh sách sẽ đơn giản hơn nhiều và code cũng gọn hơn vì không phải lo các edge case như phân trang
  • Nếu ai cho rằng Datastar không đủ cho thời gian thực/cộng tác/multiplayer, tôi muốn giới thiệu 3 demo đã lên trang chính HN, chạy được cả không cần tính năng PRO và thậm chí trên VPS 5 đô. Chúng cho thấy Datastar là công nghệ được làm tốt đến mức nào: Checkboxes, Cells, Game of Life Example. Ví dụ checkbox và cell có render view rất linh hoạt nên có thể zoom out khá nhiều, và còn có cả backpressure cho virtual scroll
    • Nếu tôi hiểu đúng cấu trúc code, thì thực ra có vẻ họ không dùng cách patch (diff/patch) được datastar khuyến nghị mà render lại toàn bộ trang mỗi lần. Thành thật mà nói, mô hình tư duy này lại trông đơn giản hơn nhiều so với những ví dụ theo dõi cực kỳ chi tiết trạng thái client ở phía server, nên ngược lại làm tôi thấy hứng thú. Tôi tò mò không biết có thể xây cả những app phức tạp thông thường theo cách này không. Nếu có tài liệu nào đáng tham khảo về việc phải làm sao để theo dõi trạng thái của đủ loại widget và render lại ngay lập tức khi người dùng chuyển giữa các trang khác nhau, mong được chia sẻ
    • Ở ví dụ checkbox/cell có nói là có thể “zoom out”, nhưng tôi tò mò cụ thể làm thế nào. Và sẽ còn hay hơn nếu có tùy chọn kiểu data-replace-url để URL của view hiện tại tự động cập nhật theo tọa độ tương ứng (x=123&y=456, v.v.)
    • Nhìn đoạn nhắc đến tính năng PRO tôi mới biết đây là mô hình open-core (một phần mã nguồn mở, phần còn lại trả phí, giấy phép 299 đô). Tôi xin bỏ qua
  • Gần đây tôi có đọc bài này (htmx, datastar, greedy developer), và nghe nói những tính năng cốt lõi hay của Datastar đã bị chuyển sang bản trả phí (Pro). Dù là mã nguồn mở hay trả phí, tôi vẫn muốn hỗ trợ tài chính cho framework, nhưng tiền lệ kiểu này khá đáng lo
    • Tôi cũng đã theo dõi Datastar suốt mấy tháng để chờ bản phát hành 1.0.0, nhưng giờ thì hứng thú đã tắt hẳn. Tôi từng nhiều lần gặp kiểu “mã nguồn mở nhưng thực ra không hẳn vậy”, nên càng khó tin tưởng hơn
    • Thực ra trước đây tôi từng viết là mình không thích Datastar lắm, nhưng lần này lại muốn bênh Datastar một chút. Tác giả framework đã phát hành miễn phí mã của mình theo giấy phép MIT, nên cả những tính năng từng được phát hành miễn phí trong quá khứ vẫn có thể dùng theo MIT. Với tư cách là người chỉ dùng mà không đóng góp, việc tiếp tục phụ thuộc vào phiên bản cũ là lựa chọn của chính bạn. Từ bây giờ chuyển sang mô hình trả phí là quyền của chủ sản phẩm, và nếu cần thì cứ fork thôi
    • Tôi đã trả một lần 299 đô để mua giấy phép PRO, nhưng thực ra vẫn chưa từng dùng tính năng PRO nào. Tôi từng định làm một bản clone Google Sheets, nhưng ngay cả không có PRO cũng vẫn đủ để triển khai. (xem demo cells)
    • Tôi từng có cảm giác phía Datastar không chỉ đơn thuần quảng bá việc Datastar tốt thế nào trong Discord của HTMX, mà đôi lúc còn hơi mang tính công kích. Trên reddit tôi cũng từng thấy họ để lại bình luận kiểu “nếu đã có đủ chức năng cần thiết thì cứ dùng beta forever đi, mã nguồn mở không nợ ai điều gì”
    • Khi dùng Datastar, tôi lập tức nhớ đến trường hợp Meteor.js ngày xưa. (Thảo luận HN về Meteor.js)
  • Tôi không thật sự hiểu các ví dụ code trong bài post này. Ví dụ đoạn htmx dưới đây <span hx-target="#rebuild-bundle-status-button" hx-select="#rebuild-bundle-status-button" hx-swap="outerHTML" hx-trigger="click" hx-get="/rebuild/status-button"></span> có vẻ được đổi thành đoạn datastar này: <span data-on-click="@get('/rebuild/status-button')"></span> Và các ví dụ khác còn gây rối hơn nữa. Rốt cuộc tôi không hiểu vì sao người ta lại chuyển từ htmx sang Datastar
    • Về cơ bản, HTMX có nghĩa là “khi click vào span này thì lấy HTML từ /rebuild/status-button, trích xuất phần tử #rebuild-bundle-status-button từ HTML trả về, rồi thay thế phần tử hiện tại”. Còn Datastar thì là “khi click vào span thì làm đúng theo lệnh từ /rebuild/status-button”. Nếu server trả về nhiều phần tử có gắn ID, Datastar sẽ tự nhận diện tất cả và thay thế chúng tương ứng. Tức là không cần dùng target, select, swap, chỉ cần có ID là sẽ hoạt động theo ý định
    • Cấu trúc của Datastar là dồn logic về backend. Nó giống HTML truyền thống ngày xưa ở chỗ request rồi nhận HTML và browser render ngay, nhưng Datastar sau khi tải trang một lần thì mỗi khi có tương tác sẽ gửi request lên backend và chỉ nhận phần thay đổi để áp dụng. Đây là cấu trúc ngược với SPA (single-page app) nơi frontend không có logic và backend quản lý toàn bộ trạng thái. Về bản chất, đây vẫn là câu chuyện lặp lại về việc phân bổ logic giữa backend và frontend, nhưng Datastar cho phép dồn logic về server (backend) mà vẫn giữ được giao diện động
    • Nhưng tôi vẫn thắc mắc tại sao lại dùng thẻ span để click. Có vẻ button hoặc thẻ link sẽ phù hợp hơn chứ nhỉ
  • Trớ trêu là bài này nói về hypermedia nhưng lại không có link đến trang chính thức của Datastar. Đây là trang chính thức: https://data-star.dev/
  • Một trong những ưu điểm lớn của HTMX là client không cần biết cấu trúc dữ liệu mà server trả về, nhưng nếu client phải biết cả ID hay ý nghĩa của từng phần tử riêng lẻ thì lời hứa đó có vẻ bị phá vỡ. Dù vậy, trong thực tế cũng có rất nhiều dự án dùng OOB (Out of Band), nên việc tách biệt cấu trúc hoàn hảo có lẽ cũng hơi xa rời thực tế. Sẽ thật tốt nếu có cách nào đó lấy được ưu điểm của cả hai thế giới
    • Thực tế thì client không cần biết gì cả. Client có thể thực thi action rồi server trả về toàn bộ view của trang. Client render toàn bộ ngay lập tức. Nó khá giống mô hình immediate mode trong video game
  • Kiểu Datastar patch HTML từ server như thế này có vẻ không tốt về separation of concerns, và ứng dụng càng lớn thì việc liên tục đẩy các phần HTML từ server càng có vẻ rất khó quản lý
    • Nhưng nếu để JS đi khắp nơi chèn HTML dưới dạng fragment thì cũng đâu có gì tốt hơn
    • Cách thiết kế endpoint chuyên để rải các mảnh HTML từ server xuống nghe cứ có gì đó không ổn
  • Datastar cho cảm giác hoàn thiện hơn htmx. Tôi đã làm thành công vài dự án với htmx, nhưng vẫn luôn thấy tiếc vì phải bổ sung JS glue code (đặc biệt là AlpineJS v.v.) cho phần xử lý sự kiện. Nếu Datastar có thể giảm cả nhu cầu đó thì thật sự rất đáng mong đợi
    • Tôi khuyên nên đọc bài tiểu luận grugs around the fire trên trang Datastar
  • Tôi tham gia xu hướng hypermedia khá muộn, ban đầu dùng Datastar rồi dạo này chuyển sang HTMX. API của Datastar có phần tốt hơn, nhưng từ khi htmx 2.0 hỗ trợ cập nhật OOB (Out-Of-Band) thì phần lớn tôi nghiêng về htmx hơn
    • Câu “đến với hypermedia muộn” nghe khá ấn tượng. Sẽ thú vị nếu nhớ rằng Ted Nelson đã dùng thuật ngữ này lần đầu vào năm 1965, và khi đó ông viết rằng “hyperfilm— a browsable or vari-sequenced movie— is only one of the possible hypermedia that require our attention”. Xem bài báo liên quan
    • Điều tôi thấy tiếc khi xử lý phần tử OOB trong HTMX: 1. Nếu là OOB thì bắt buộc phải có htmx-swap-oob="true", nếu không có thì hoạt động sẽ khác kỳ vọng 2. Ngược lại, nếu không phải OOB mà lại có htmx-swap-oob="true" thì sẽ bị bỏ qua hoặc hoạt động sai. Vì vậy, khi muốn tái sử dụng cùng một component cho cả OOB và không OOB, server phải luôn trả xuống cờ isOob, khá là phiền
    • Tôi thích API của alpine-ajax hơn. Chỉ cần chỉ định nhiều target là có thể thay thế các phần tử một cách nhất quán mà không cần JS. Còn khái niệm signal/state của Datastar thì ngược lại làm tăng độ phức tạp nên tôi không thích lắm