- So sánh Backbone của đầu những năm 2010 với React của năm 2025, đồng thời nhìn lại xem frontend đã thực sự tiến bộ được bao nhiêu trong 15 năm qua
- React bề ngoài có vẻ gọn gàng và hiện đại, nhưng bên trong lại giả lập sự đơn giản thông qua các tầng trừu tượng phức tạp
- Backbone tuy dài dòng hơn, nhưng luồng sự kiện và thao tác DOM đều tường minh, nên ngay cả lập trình viên mới cũng dễ dàng lần theo cách nó hoạt động
- React có cấu trúc khiến việc debug trở nên khó khăn nếu không hiểu cơ chế bên trong, do các vấn đề như quản lý state, mảng dependency, closure
- Cuối cùng, bài viết gợi nhắc lại bản chất “event + state = UI”, đồng thời đặt ra nhu cầu về một mô hình mới vừa đơn giản vừa dễ can thiệp (hackable)
15 năm tiến bộ
- Một ví dụ về ô nhập mật khẩu, một bên được viết bằng framework của thập niên 2010 (Backbone), bên còn lại bằng React đã phát triển hơn 10 năm
- Hai cách triển khai có độ dài tương tự và chức năng cũng giống nhau
- React được hậu thuẫn bởi rất nhiều thời gian của lập trình viên và một hệ sinh thái khổng lồ
- Tuy vậy, tác giả cho rằng điều thú vị hơn không phải là “React đã cải thiện đến đâu” mà là “nó tiến bộ ít đến mức nào”
- React mang lại ảo giác về sự đơn giản ở bề mặt, nhưng trên thực tế lại khó hiểu hơn do các lớp trừu tượng phức tạp
- Backbone biểu đạt rõ ràng luồng đơn giản: sự kiện xảy ra → chạy handler → tạo HTML → chèn vào DOM
- Trong khi đó React che giấu hoạt động nội bộ, và khi vượt qua các ví dụ đơn giản sẽ xuất hiện những vấn đề chỉ có thể giải quyết nếu hiểu cơ chế bên trong
Ảo giác về sự đơn giản (The Illusion of Simplicity)
- Mã React trông sạch sẽ, nhưng đó là kết quả của việc chọn độ phức tạp trừu tượng thay cho sự đơn giản tường minh
- Backbone dài dòng hơn, nhưng cho thấy rõ “điều gì xảy ra và xảy ra khi nào”
- Ngay cả lập trình viên mới cũng có thể dễ dàng lần theo luồng mã
- Trong React, state nội bộ và logic render bị che giấu nên bug ngoài dự kiến xuất hiện khá thường xuyên
- Ví dụ: nếu đổi key của một mục trong danh sách thành index, React sẽ nhận đó là một component khác và reset state
- Khi
value đổi thành undefined, sẽ xảy ra hiện tượng chuyển từ uncontrolled sang controlled component, khiến giá trị input bị reset
- Khi dùng
useEffect, vấn đề vòng lặp vô hạn cũng rất phổ biến
- Nếu mảng dependency chứa một object được tạo mới ở mỗi lần render, React sẽ coi đó là thay đổi
- Để tránh điều này, cần dùng
useMemo, useCallback để ổn định identity (stabilize identities)
- Điều này tạo thêm gánh nặng phải chú ý tới những khái niệm mà trước đây không cần bận tâm
- Ngoài ra còn có vấn đề click handler tham chiếu tới state cũ (stale state)
- Vì hàm sẽ capture state tại thời điểm nó được tạo ra
- Cách giải quyết là đưa state vào mảng dependency, hoặc dùng functional update như
setState(x => x + 1)
- Nhưng cả hai cách đều mang lại cảm giác như một biện pháp chắp vá (workaround)
Cái giá của phép màu (Magic Has a High Price)
- Những vấn đề này không phải ngoại lệ, mà là các vấn đề phổ biến thường gặp ở ứng dụng từ quy mô trung bình trở lên
- Để debug, cần hiểu thuật toán reconciliation, render phase, và scheduler (batch update)
- React là kiểu cấu trúc “vẫn chạy dù không biết vì sao nó chạy”, nhưng khi có sự cố thì bắt buộc phải hiểu bên trong mới xử lý được
- React phức tạp đến mức có câu nói rằng “muốn thật sự hiểu React thì phải tự tay xây nó”
- Có những tutorial như “Build your own React”
- Tuy nhiên, việc phải hiểu virtual DOM, mức ưu tiên scheduling, và concurrent rendering chỉ để làm một trình kiểm tra mật khẩu là một hàm ý đáng để phê phán
- Backbone và jQuery có cấu trúc trung thực và dễ can thiệp
- Có thể xem trực tiếp source code và chỉnh sửa
- Dựa trên các phương thức DOM nên dễ hiểu và dễ mở rộng
- Ngược lại, tầng trừu tượng của React khiến việc truy cập và chỉnh sửa nội bộ trở nên khó khăn
Bước tiếp theo là gì (So, What's Next?)
- Xét cho cùng, cả React lẫn Backbone đều là những nỗ lực nhằm giải quyết cùng một bài toán: “event + state = UI”
- Ở các ứng dụng lớn, sự phức tạp của React có thể là điều hợp lý, nhưng với phần lớn ứng dụng nhỏ và vừa thì đó là gánh nặng quá mức
- Cần một mô hình UI mới có sự đơn giản và tính minh bạch
- Một hệ thống vững chắc nhưng trực quan như DOM
- Hướng tới một cấu trúc có thể hiểu và sửa được ngay lập tức như Backbone hay jQuery
2 bình luận
Với các ứng dụng nhỏ và vừa, có vẻ việc thiết kế
JavaScript Classsẽ là tư thế chuẩn bị cho tương lai hơn là dùng Backbone hay JQuery.Việc phải học lại rồi triển khai theo các template có trong JQuery hay Backbone giống như đang thụt lùi.
Ý kiến Hacker News
Đã dùng hết Backbone, Angular 1, Ember cho đến React
Không nên bỏ qua lý do vì sao React trở nên phổ biến. React đã giải quyết những vấn đề cố hữu của các framework trước đó ở các mặt như kết hợp component, xử lý sự kiện, quản lý trạng thái, cập nhật DOM hiệu quả
Backbone khiến việc quản lý vòng đời DOM trở nên phức tạp, lại phải chỉ định event handler bằng chuỗi nên rất khó bảo trì. React đơn giản hóa các vấn đề này bằng luồng trạng thái một chiều và virtual DOM
Nếu là bây giờ, khi muốn dùng JS thuần, tôi nghĩ một giải pháp template như lit-html tốt hơn Backbone rất nhiều
Frontend trước đây đã phức tạp, bây giờ cũng vẫn phức tạp, nhưng giờ đỡ đau hơn rất nhiều
Độ phức tạp của ứng dụng không đến từ số lượng component mà đến từ quản lý trạng thái
Tôi thường xuyên gặp vấn đề UI bị treo vì luồng dữ liệu hai chiều của Backbone Store. Đột phá của React là kiến trúc Flux lấy luồng dữ liệu một chiều làm trung tâm
Tôi nghĩ một framework tốt là công cụ tự nhiên dẫn người dùng vào “cái bẫy thành công (Pit of Success)”. React đã làm tốt vai trò đó
Ví dụ như các vấn đề stale closure, vòng lặp useEffect vô hạn, input bị reset do thay đổi key là những thứ Backbone không có
Vấn đề của Backbone thì lộ rõ và dễ debug, còn vấn đề của React lại ẩn sau tầng trừu tượng
Phần lớn ứng dụng không ở quy mô Facebook, nên cách tiếp cận tường minh và đơn giản đôi khi còn tốt hơn
Việc khẳng định một công nghệ phổ biến là “tệ” nghe giống một kiểu kiêu ngạo ngây thơ
Tất nhiên, độ phổ biến không đảm bảo chất lượng, nhưng cho rằng tất cả những kỹ sư giỏi trên thế giới đều bị lừa thì hơi quá
Khi doanh nghiệp lớn và marketing cùng đẩy mạnh, các CTO sẽ chấp nhận nó, và khi sự nghiệp bị ràng buộc vào đó thì chẳng ai muốn nói “cái này không ổn”. Phổ biến ≠ phù hợp
React không thắng chỉ nhờ ưu thế kỹ thuật mà còn nhờ marketing của Facebook và sự tự củng cố của hệ sinh thái
Dù đã 15 năm trôi qua, độ dài và độ phức tạp của code vẫn không giảm đi bao nhiêu. Chỉ là nó trở nên phức tạp theo cách khác mà thôi
Việc nhìn lại quá khứ không phải vì hoài niệm, mà để kiểm tra xem liệu chúng ta có đang thêm vào độ phức tạp không tương xứng hay không
Web vẫn giống như miền Tây hoang dã của các design pattern. Chấp nhận điều đó xong thì tôi thấy nhẹ đầu hơn
Cuối cùng, mỗi dự án vẫn phải đánh giá lại các trade-off
Lập luận “việc đơn giản thì không cần React” là một ngụy biện React (React fallacy) rất phổ biến
Đánh giá React bằng các ví dụ đơn giản cũng giống như “đánh giá một ngôn ngữ qua độ dài của Hello World”
Lý do dùng React cho cả việc đơn giản là vì nó cũng được dùng cho việc phức tạp. Bộ công cụ nhất quán có lợi cho bảo trì
Backbone là kiểu “trông như framework nhưng thực chất là một đống glue code”
Chiến thắng thực sự của React là không còn cần thao tác DOM trực tiếp và có thể quản lý trạng thái theo kiểu reactive. Hai điều này đã nâng năng suất phát triển lên đáng kể
Link tutorial cũ, bản lưu trữ
Giờ tôi quan tâm hơn đến việc LLM hiểu code như thế nào. Cú pháp khai báo như JSX khá thân thiện với LLM
Nhưng React sau thời useEffect lại cho cảm giác mờ hơn về mặt biểu đạt và tính tường minh
Điều này cho thấy khá rõ vì sao React trở nên phổ biến
Code React phần lớn chỉ là JS thuần và HTML, và cốt lõi chỉ là
useState. Nó trực quan đến mức có thể hiểu mà không cần tài liệuBackbone phụ thuộc vào các string selector như
.space-y-2, nên bảo trì đúng là địa ngục. Chỉ cần đổi một class name là nửa ứng dụng có thể hỏngReact đã giải quyết vấn đề này theo cách có tính cấu trúc
Code Backbone cho thấy rõ “việc gì xảy ra khi nào”, còn React thì phải hiểu được cơ chế nội bộ của nó
Tôi cũng đã phải đọc đi đọc lại hướng dẫn useEffect của Dan Abramov và blog của Mark Erikson để hiểu thời điểm React hoạt động như thế nào
Code Backbone thì dù 10 năm sau nhìn lại vẫn hiểu ngay
Sáu năm trước chúng tôi chuyển team từ Backbone sang Angular
Backbone có cấu trúc trực quan và không có ma thuật, nên khá phù hợp cho junior, nhưng cuối cùng TypeScript và Angular vẫn bài bản hơn
Hiện tại chúng tôi dùng NG20 và thấy hài lòng. Nếu một ngày nào đó trình duyệt mặc định hỗ trợ nhiều thứ hơn, có lẽ chúng tôi sẽ lại quay về cách làm đơn giản hơn
Chúng ta luôn lập trình trên các tầng trừu tượng
Điều quan trọng là tầng trừu tượng đó có mang lại lợi ích năng suất tương xứng với độ phức tạp hay không, và liệu nó có đáng tin cậy hay không
Ít nhất trong trường hợp xấu nhất vẫn phải debug được
Trường input của React xử lý thao tác Undo tự nhiên hơn so với Backbone
Backbone hoàn tác từng ký tự một, còn React hoàn tác theo từng từ