- Tôi thực sự thích ý tưởng nền tảng và đơn giản của Htmx, nhưng sau khi dùng thử trên phạm vi cả nhóm, chúng tôi nhận ra rằng trên thực tế nó không hề đơn giản mà khá phức tạp
Việc kế thừa thuộc tính trong Htmx rõ ràng là một sai lầm
- Trong các đoạn mã, việc kế thừa thuộc tính mang tính ngầm định và gây bất ngờ
- Giống như trong CSS, kế thừa là một mẹo rẻ tiền nhưng phải trả giá
- Điều này mâu thuẫn với lập luận về tính cục bộ của hành vi của tác giả
- Mặc định kế thừa khác nhau giữa nhiều thuộc tính (ví dụ:
hx-delete không được kế thừa nhưng hx-confirm và hx-ext thì có)
- Phải nhớ các ngoại lệ và cuối cùng phải biểu đạt mọi thứ một cách tường minh, khiến việc kế thừa trở nên vô nghĩa
Hầu hết các ứng dụng web thú vị không thể thay thế toàn bộ phần tử DOM
- Các phần tử DOM gần như luôn có trạng thái cục bộ trong trình duyệt (ví dụ: trạng thái mở/đóng của phần tử
<details>, giá trị nhập của phần tử <input>, trạng thái mở/đóng của các phần tử dropdown)
- Nếu Htmx dùng cách đơn giản là thay trực tiếp
outerHTML thì toàn bộ các trạng thái này sẽ bị mất
- Ngay cả phần mở rộng Morphdom đôi khi cũng ghi đè một số phần tử khác với kỳ vọng
Lưu trạng thái ngay trên phần tử DOM bản thân nó là một ý tưởng tệ
- Morphdom là để giải quyết nỗi đau ở mục trước, nhưng rồi người ta phát hiện cách Htmx vận hành được xây dựng trên việc thay thế toàn bộ phần tử
- Nó lưu hàng đợi request ngay trên chính phần tử DOM
- Khi bắt đầu một request, phần tử đó hoặc phần tử khác trỏ tới nó sẽ có hàng đợi request
- Nếu thay thế toàn bộ phần tử DOM thì hàng đợi sẽ được đặt lại, nhờ đó tránh được một số kiểu lỗi khó chịu
- Nhưng với Morphdom, phần tử được giữ lại nên hàng đợi cũng được giữ lại
- Kết quả là rơi vào một vùng hành vi kiểu như không được định nghĩa, nơi thiết kế của Htmx bị phá vỡ
Chế độ xếp hàng mặc định rất lộn xộn
- Theo mặc định, nếu Htmx kích hoạt một request khác từ cùng một hàng đợi (phần tử), nó sẽ hủy request đang chạy
- Đó lại còn là chiến lược mặc định
- Tác giả chỉ phát hiện ra điều này về sau
- Điều này rất phản trực giác và có nghĩa là công việc có thể bị mất
Kích hoạt sự kiện không mang tính cục bộ
- Kích hoạt sự kiện thường hữu ích để khiến điều gì đó xảy ra, nhưng đó là hiệu ứng không cục bộ và gặp vấn đề tương tự như kế thừa thuộc tính
- Làm DSL ở phía server có thể giúp phần nào, nhưng nó vẫn cho cảm giác giống kiểu lập trình callback JavaScript cổ điển
- Khi sự kiện xảy ra thì bạn “subscribe” vào nó và làm điều gì đó
Không thể duy trì tốt trạng thái của component
- Một vấn đề rộng hơn, tương tự vấn đề trạng thái của phần tử DOM, là các component của chính bạn cũng có trạng thái riêng
- Ví dụ, nếu bạn muốn một trang gồm ba section có trạng thái riêng mà server cần biết (chẳng hạn: trang của tập kết quả), đồng thời cũng có trạng thái cần cho React hoặc WebComponents, thì sẽ phát sinh vấn đề đồng bộ trạng thái giữa component cha và component con
- Htmx không đưa ra một cách làm tốt cho việc này
- Có các ý tưởng như dùng tham số truy vấn, hidden form input, event trigger, v.v. nhưng tất cả đều có lưu ý lớn
- React và Halogen có câu trả lời cho việc này
- Trong cả hai trường hợp, component con có trạng thái riêng, còn component cha có thể cung cấp các "props" giống như "lời khuyên"
- Component cũng có trạng thái nội bộ riêng và có thể bỏ qua hoặc ưu tiên hơn props
- Props thường được cung cấp từ server hoặc suy ra từ server, còn state thường là trạng thái phía client
- Những component dựng sẵn được cung cấp bằng React, hoặc những component buộc phải dùng, thường đòi hỏi React
- React và Htmx không tương tác tốt với nhau
- Tác giả từng làm một số thứ tạm ổn với WebComponents, nhưng chúng có những hạn chế kỳ quặc đầy bất ngờ
- Tác giả cũng từng tạo bridge trực tiếp tới các React component dùng trong ngôn ngữ phía server, nhưng nhìn chung Htmx và React tranh giành nhau về luồng trạng thái và việc quản lý phần tử DOM
- Tác giả đã thử Alpine, thấy ổn, nhưng đó lại là thêm một thư viện lập trình phía client nữa, nên sẽ bị trùng lặp nếu codebase đã có React
Dù vậy, vẫn có những ưu điểm
- Có thể dùng ngôn ngữ phía server là một lợi thế cực kỳ rõ ràng và khó có thể tranh cãi
- Không ai trong nhóm muốn viết lại toàn bộ logic nghiệp vụ này bằng TypeScript
- Không cần serialize từ kiểu dữ liệu DB sang kiểu dữ liệu frontend
- Không có rò rỉ dữ liệu và cũng không cần GraphQL
- Có thể tận dụng các khả năng trừu tượng mạnh hơn của ngôn ngữ phía server
- Có thể dùng form builder của ngôn ngữ phía server thay vì phải triển khai cùng một cơ chế validation ở cả frontend lẫn backend
- Tuy nhiên, các nhược điểm ở trên cũng là sự thật
Htmx-in-React?
- Một hướng đi tương lai hấp dẫn có thể là tái hiện thực Htmx trong React
- Server gửi một khối JSON và React chuyển nó thành các virtual DOM component
- Khi đó vấn đề trạng thái component sẽ được giải quyết
- Sẽ không cần một bridge đặc biệt để dùng React component
- Có thể dùng các thư viện fetch web gắn với React, đồng thời cẩn thận tránh lựa chọn xếp hàng mà Htmx đã thực hiện
- Vấn đề Morphdom và vấn đề phần tử input DOM trong trình duyệt cũng sẽ được giải quyết, vì đây gần như là các vấn đề đã được xử lý trong React
- Theo cách này có thể loại bỏ phụ thuộc vào Htmx nhưng vẫn giữ được lợi ích của ý tưởng, miễn là có ngân sách để bắt đầu một công việc lớn như vậy
Ý kiến của GN⁺
- Ý tưởng cốt lõi của Htmx rất hấp dẫn, nhưng khi dùng thực tế có thể gặp nhiều vấn đề phức tạp
- Một số thiết kế của Htmx như kế thừa thuộc tính, thay thế phần tử DOM, chế độ xếp hàng, v.v. không trực giác và có thể gây ra hành vi ngoài dự đoán
- Việc tích hợp với React hoặc WebComponents dường như cũng không hề dễ dàng
- Dù vậy, khả năng dùng ngôn ngữ phía server vẫn là một ưu điểm lớn
- Về sau, việc tái hiện thực Htmx dựa trên React cũng có thể là một hướng đi thú vị
12 bình luận
Quan tâm vẫn tốt hơn là thờ ơ mà~ Tôi thích HTMX. Cả triết lý của nó nữa.
Nó cũng có cảm giác rất giống với SQLite nữa haha
SQLite và HTMX giống nhau ở điểm nào?
Giống SQLite?
Bình luận này thật sâu sắc. Triết học ư..
Nếu bạn từng có kinh nghiệm phát triển web bằng server-side rendering & jQuery trước khi SPA xuất hiện, thì sẽ hiểu ngay đây là công nghệ thuộc phía đó. Có lẽ những người bước chân vào phát triển web từ thời SPA đang theo đuổi cái mới nên đã hiểu nhầm.
Bài viết này có vẻ không phải được viết ở Hàn Quốc nhỉ.
Đúng vậy. Có vẻ đây là một công cụ được tạo ra cho những trang đơn giản, nên tôi không hiểu vì sao lại nổ ra những cuộc tranh luận kiểu mang các ví dụ hay use case kỳ lạ vào rồi bảo rằng nó không phù hợp với những thứ đó.
Như có thể thấy từ trang chủ của htmx, htmx có lập trường khá gần với việc cho rằng (nếu chỉ có họ thôi) thì các công nghệ frontend hiện đại, bao gồm cả React, là không cần thiết.
Điều đó có liên quan đến lý do htmx được chú ý. Bài này cũng là bản dịch của một bài viết đóng góp từ nước ngoài, và ở nước ngoài người ta đã quá mệt mỏi với đủ kiểu quản lý trạng thái của React. Vì vậy, họ xem htmx — thứ cung cấp các tính năng tương tự React nhưng không cần quản lý trạng thái như React — là một lựa chọn thay thế cho React. Đó là lý do họ cứ tiếp tục so sánh htmx với React.
Ừm. Nếu là vì lý do đó thì chẳng phải nên mang một thứ được cho là có thể thay thế React ra để so sánh mới đúng sao?
Chỉ cần nhìn vào các đặc điểm được liệt kê trên trang này thôi cũng đủ thấy HTMX không phải là thứ phù hợp để dùng cho các trang phức tạp, và hoàn toàn không phải thứ gì đó có thể thay thế React.
Ý kiến trên Hacker News
Có ý kiến trái chiều về việc kế thừa thuộc tính. Có thể tắt bằng tùy chọn
htmx.config.disableInheritanceLý do không dấn thân vào frontend là vì có quá nhiều lựa chọn, quá nhiều tranh cãi, và xu hướng công nghệ thay đổi thường xuyên
Đang dùng HTMX để xây dựng một storefront có hiệu năng tốt, và khá hài lòng với kết quả
Ý tưởng "HTMX in React" giống như tái phát minh React Server Components
Không đồng ý với ý kiến cho rằng chế độ chờ mặc định là phi lý
Kết quả khi lần đầu dùng HTMX là có thể áp dụng dễ dàng cho các tác vụ đơn giản và thấy khá thú vị
Sau khi đọc lời phàn nàn về trạng thái, có cảm giác tác giả chưa từng làm website trước thời React
Tò mò không biết HTMX có tính năng giống Turbo Mount hay không
Muốn biết thêm về vấn đề morphdom đôi khi ghi đè một số phần tử ngoài dự đoán