- Mux đã chuyển mux.com và docs.mux.com sang React Server Components, và xác nhận rằng việc phân chia ranh giới thực thi giữa server và client ảnh hưởng trực tiếp đến kích thước bundle và chi phí hydration
- RSC cho phép component lấy dữ liệu trực tiếp trên server và streaming kết quả, nhờ đó vẫn có thể hiển thị trước một phần giao diện ngay cả khi có lệnh gọi dữ liệu chậm
- Trở ngại lớn nhất trong quá trình migration thực tế là không hỗ trợ CSS-in-JS, các giới hạn của React Context trong Server Components, và độ phức tạp của việc phải liên tục theo dõi ranh giới server/client
- Trong app directory của Next.js 13, mặc định là Server Component, và có thể triển khai dần dần bằng cách từ từ đẩy
use clientxuống thấp hơn trong cây gốc - Các pattern như Suspense,
loading.js, giữ thư viện chỉ chạy trên server, hayserver-onlychỉ nên được áp dụng cẩn trọng ở những nơi thật sự cần lợi ích hiệu năng, đồng thời phải tính cả chi phí nhận thức của đội ngũ
Phạm vi Mux đã chuyển sang RSC
- Mux đã chuyển mux.com và docs.mux.com sang Server Components trong quá trình tái cấu trúc trang tài liệu và đổi nhận diện thương hiệu
- React Server Components có thể áp dụng được trong codebase thực tế và có thể đáng để sử dụng, nhưng đi kèm với đó là các ràng buộc và độ phức tạp
- Trải nghiệm này được tổng hợp xoay quanh việc vì sao cần RSC, phù hợp với đâu, khó nhằn trong những tình huống nào, và cách đưa nó dần dần vào codebase thực tế
Vấn đề RSC nhắm tới sau CSR, SSR/SSG
- Các cách render phía server ban đầu với công nghệ như PHP sẽ lấy dữ liệu và xử lý các tác vụ CPU nặng trên server, rồi gửi HTML nhẹ về phía client
- CSR/SPA giúp gửi mã render bằng JavaScript xuống client để xử lý tương tác nhanh hơn, nhưng bộc lộ điểm yếu trong những trường hợp công cụ tìm kiếm không chạy JavaScript, khi cần giữ giá trị bí mật trên server, hoặc khi gặp thiết bị yếu và kết nối chậm
- SSR/SSG là cách dùng các công cụ như Next.js và Gatsby để tạo cả HTML lẫn JavaScript trên server rồi gửi về client
- Người dùng có thể thấy HTML ngay lập tức
- Khi JavaScript tải xong, website sẽ trở nên có thể tương tác
- Công cụ tìm kiếm cũng có thể đọc HTML
- Ngay cả SSR/SSG truyền thống vẫn còn chi phí
- Phần lớn JavaScript dùng để tạo trang vẫn phải gửi xuống client, và cần hydration để client chạy lại rồi gắn với HTML
- Nếu render phía server chậm do gọi database lâu hoặc chạy quá nhiều mã, người dùng vẫn phải chờ
React Server Components thay đổi ở đâu
- React Server Components là các React component chạy trên server thay vì trên client
- Framework hỗ trợ RSC cho phép phân chia rõ ràng nơi mã sẽ được thực thi
- Server Components: mã chỉ nên chạy trên server
- Client Components: mã nên chạy trên client
- Khi vị trí thực thi được tách ra, lượng JavaScript gửi xuống client giảm đi và công việc phải làm trong quá trình hydration cũng ít hơn
- Server Component có thể lấy dữ liệu trực tiếp bên trong component
- Có thể dùng thư viện Node hoặc
fetch - Có thể giảm cách lấy toàn bộ dữ liệu ở cấp trang bằng
getServerSidePropsrồi truyền props xuống liên tục - Cũng giảm những trường hợp phải quản lý trạng thái loading phức tạp bằng
useEffect
- Có thể dùng thư viện Node hoặc
- Sau khi lấy dữ liệu xong, Server Component có thể streaming kết quả về client
- Có thể hiển thị phần còn lại của website trước trong lúc chờ component chậm
- Cũng có thể phản hồi hành động người dùng ở client bằng cách lấy dữ liệu trên server và streaming phản hồi, nhưng về mặt chặt chẽ thì đó không phải RSC mà là React Actions
Những phần khiến RSC khó dùng
- CSS-in-JS hiện tại không hoạt động trong Server Components
- Trong quá trình chuyển sang RSC của Mux, phần chiếm công sức lớn nhất là chuyển từ styled-components sang Tailwind CSS
- Nếu codebase phụ thuộc nhiều vào CSS-in-JS thì sẽ cần thêm một đợt migration riêng
- React Context chỉ có thể được truy cập trong Client Components
- Nếu muốn chia sẻ dữ liệu giữa các Server Component mà không dùng props, nhiều khả năng sẽ phải dùng module thông thường
- Server Components không có cơ chế tốt để giới hạn dữ liệu chỉ trong một subtree cụ thể của ứng dụng React
- Ở trang tài liệu của Mux, đây không phải vấn đề lớn vì các khu vực dùng Context vốn có nhiều tương tác nên dù sao cũng phải gửi xuống client
- Ở website marketing, việc chia sẻ theme lại là vấn đề
- Mỗi component ở phần pre-footer cần biết rằng nó đang nằm trên nền xanh lá để có thể dùng viền xanh lá đậm
- Thay vì Context, họ đã tận dụng mạnh CSS custom properties để lách qua
- RSC mang lại sự linh hoạt về nơi thực thi và cách lấy dữ liệu, nhưng đổi lại cũng tăng độ phức tạp
- Lập trình viên mới phải liên tục kiểm tra “thứ gì chạy trên server và thứ gì chạy trên client”
- Trong mỗi PR đều có phản hồi về đoạn mã bị gửi xuống client không cần thiết
- Trong lúc phát triển, việc thêm
console.logđể kiểm tra log đang ra ở server hay browser diễn ra thường xuyên - Caching cũng làm tăng thêm một lớp phức tạp riêng
Cách dùng RSC cơ bản trong Next.js 13
- Tại thời điểm bài viết được viết, triển khai RSC sẵn sàng cho production là app directory của Next.js 13
- Trong app directory của Next.js 13, component được viết ra mặc định là Server Component
- Ở trạng thái mặc định, mã của trang không được gửi xuống client
- Client chỉ nhận HTML
- Gắn
asyncvào Server Component thì có thể lấy dữ liệu ngay bên trong component - Server Component có thao tác lấy dữ liệu chậm có thể được bọc bằng
React.Suspense- Client sẽ thấy fallback UI trước
- Khi server lấy dữ liệu xong và render hoàn tất, component kết quả sẽ được streaming
- Suspense boundary không chỉ dùng cho streaming dữ liệu mà còn có thể dùng cho selective hydration để điều chỉnh mức ưu tiên hydration của từng vùng tùy theo tương tác người dùng
- Mã cần chạy trên client thì thêm
"use client"ở đầu file- Dùng cho component cần tương tác với trạng thái phía client như
onClicklistener hayuseState - Mọi component được import bởi component có
"use client"cũng sẽ bị gửi xuống client
- Dùng cho component cần tương tác với trạng thái phía client như
- Các thư viện không hỗ trợ RSC có thể được import trong Client Component để đưa vào bundle phía client
- Ví dụ là component
ClientMuxPlayerbọc@mux/mux-player-react
- Ví dụ là component
Tiêu chí chọn Server Component hay Client Component
- Server Components phù hợp với mã không cần gửi xuống client
- Render nội dung bài blog
- Tác vụ tốn kém như syntax highlighting cho code block
- Lấy dữ liệu
- Client Components phù hợp với UI phản ứng với input của người dùng hoặc có trạng thái thay đổi theo thời gian
useState- Event listener
- Tương tác phía client
- Nếu toàn bộ ứng dụng đều là Client Components thì nó sẽ hoạt động tương tự framework SSR truyền thống
- Không cần chuyển cả ứng dụng sang Server Components trong một lần, có thể triển khai dần từ những chỗ có lợi ích lớn nhất
3 bước để đưa dần vào codebase thực tế
- Playbook Mux dùng gồm ba bước
- Thêm chỉ thị
"use client"vào root của ứng dụng - Di chuyển chỉ thị này xuống thấp nhất có thể trong cây render
- Chỉ áp dụng các pattern nâng cao khi vấn đề hiệu năng thực sự lộ ra
- Thêm chỉ thị
- Ở bước 1, thêm
"use client"vàopage.tsxcấp cao nhất của Next.js 13 để ứng dụng tiếp tục hoạt động như cũ - Nếu cần lấy dữ liệu phía server thì thêm một Server Component làm cha của Client Component
- Server Component sẽ lấy dữ liệu
- Truyền dữ liệu đã lấy vào Client Component qua props
- Có thể thay thế vai trò cũ của
getServerSideProps
- Ở bước 2, di chuyển
"use client"từ component cấp cao nhất xuống các component con- Với
<Title />không cần mã client, có thể bỏ chỉ thị để gửi dưới dạng HTML thuần - Với
<Player />cần mã client, nếu bỏ sẽ gây lỗi nên phải giữ"use client"
- Với
- Cách làm này khiến đội ngũ cân nhắc Server Components khi viết component mới hoặc refactor mã cũ, đồng thời giúp giảm một phần kích thước bundle
Các pattern được áp dụng khi có vấn đề hiệu năng
- Trang tài liệu của Mux phần lớn được tạo tĩnh, nhưng changelog sidebar thì lấy từ CMS
- Nếu bọc sidebar bằng Suspense thì phần còn lại của ứng dụng không cần phải chờ tới khi CMS fetch xong
- Quy ước loading.js của Next.js 13 cũng nội bộ dùng Suspense và streaming
- Nếu muốn giữ các thư viện lớn ở lại trên server thì cần điều chỉnh cách sắp xếp Client Components và Server Components
- Ví dụ là giữ thư viện syntax highlighting Prism trên server
Cách trộn Server Component vào bên trong Client Component
- Component được import bởi Client Component sẽ cùng trở thành Client Component
- Nếu muốn đặt Server Component làm con của Client Component thì không được import trực tiếp mà phải truyền qua
childrenhoặc props- Server Component sẽ được render trên server
- Kết quả đã được serialize sẽ được chuyển vào Client Component
- Cách sai là import trực tiếp Server Component trong file Client Component
- Cách đúng là đi lên Server Component cha gần nhất rồi truyền Server Component vào Client Component dưới dạng con hoặc prop
Không thể chia một file nửa server, nửa client
- Không thể tạo một file mà một nửa là Server Component và một nửa là Client Component
- Mux thường dùng pattern tách chức năng ra hai file
CodeBlock.server.js: import thư viện syntax highlighting lớn và render trên serverCodeBlock.client.js: dùnguseStatevàonClickđể cho phép người dùng chuyển đổi ví dụ mã
- Các ví dụ đã render trên server được truyền vào Client Component qua props nên công việc chỉ dành cho server không bị kéo vào bundle phía client
- Nếu
index.jsexport lạiCodeBlock.server.jsthì người dùng chỉ cần importCodeBlockmà không phải để ý đến việc tách server/client bên trong
Cách đảm bảo chỉ chạy trên server
- Ban đầu, trong lúc phát triển họ thêm
console.logđể kiểm tra log xuất ra từ server hay browser - Để đảm bảo mã chỉ dành cho server không bị đưa vào bundle, có thể import server-only package
server-onlyhữu ích để ngăn thư viện lớn hoặc secret key bị chuyển nhầm sang nơi không phù hợp- Next.js cũng cung cấp cơ chế bảo vệ để biến môi trường không vô tình bị đưa vào bundle của browser
server-onlyở đầu file cũng giúp việc bảo trì dễ hơn- Người bảo trì có thể nhận ra ngay file đó chạy trên server
Chi phí và lợi ích khi cân nhắc áp dụng
- React Server Components không phải là tính năng có được miễn phí
- Chi phí không chỉ gồm các giới hạn của CSS-in-JS và React Context mà còn bao gồm
- Hiểu vị trí thực thi giữa server và client
- Hiểu hydration
- Chi phí hạ tầng
- Độ phức tạp mã do trộn Client Components và Server Components
- Độ phức tạp làm tăng bề mặt nơi bug có thể xuất hiện và làm giảm khả năng bảo trì của code
- Framework có thể giảm bớt độ phức tạp nhưng không thể loại bỏ hoàn toàn
- Những lợi ích có thể kỳ vọng gồm
- Kích thước bundle nhỏ hơn
- Thực thi nhanh hơn
- Cải thiện hiệu năng quan trọng với SEO
- Các pattern tải dữ liệu nâng cao cho website phức tạp và nhiều dữ liệu
- Nếu đội ngũ sẵn sàng gánh thêm chi phí nhận thức và lợi ích hiệu năng đủ lớn, RSC có thể là lựa chọn phù hợp
1 bình luận
Các ý kiến trên Hacker News
Với render phía máy chủ, client nhận được HTML có thể xem ngay
Tôi cũng cảm nhận điều này: nếu đưa một tệp văn bản thuần lên máy chủ, nó được chuyển tới trình duyệt khá nhanh
Nếu đưa thêm một tệp văn bản thuần khác kết thúc bằng
.css, trình duyệt biết cách xử lý nên các phần tử ở màn hình đầu tiên có thể di chuyển và trông khá đẹp mắtĐây là một mẹo hay, nhưng vẫn chỉ là thứ phụ so với nội dung hữu ích có thể đọc được ngay ở màn hình đầu tiên
Không hiểu từ “hãy thêm tính năng để làm siêu văn bản mạnh hơn” đã biến thành “giờ thì hãy tự triển khai ứng dụng dùng được trên đống tính năng to lớn và thiếu nhất quán này” như thế nào
Tốt hơn nên dừng lại một chút trước khi lao vào RSC
Dù bạn định xây gì, một framework full-stack thật sự hoặc framework web cổ điển đều có thể xử lý dễ hơn, nhanh hơn và mở rộng tốt hơn nhiều
Có thể dùng Rails/Django/Laravel/… kèm Turbolinks/Htmx/…, hoặc chỉ rải một ít JavaScript phía client
Nếu biết Elixir/Phoenix, bạn còn có thể hưởng nhiều lợi thế cùng lúc
Dù có bao nhiêu người tweet đi nữa, cũng không nên đi sâu hơn vào RSC
Những người có chưa đến 10 năm kinh nghiệm trong ngành sẽ giẫm lại các vấn đề cơ bản từng gặp ở các site vanilla PHP ngày xưa, và tôi đã thấy cả hook SQL inline được đặt trong component React
Lần này còn cộng thêm nhiều độ phức tạp ngẫu nhiên hơn nữa
Hãy giữ tỉnh táo, nhanh chóng phát hành sản phẩm thật và kiếm đủ tiền mua Lamborghini là được
CORBA là cách trộn lẫn component cục bộ và component từ xa; nó đã trưởng thành và hoạt động trên nhiều ngôn ngữ
Vậy tại sao không phải ai cũng dùng? Hầu hết lập trình viên ngày nay có lẽ còn chưa từng nghe đến nó
Nếu muốn tạo thêm một kiến trúc component phân tán khác, nên tìm hiểu vì sao CORBA và các hậu duệ của nó không thể phổ biến rộng rãi
Gợi ý là ranh giới component bị ẩn tạo ra độ phức tạp bị ẩn
Trong khi đó, cả hai phe “HTML render trên server” và “HTML render trên client” đều đang vận hành tốt
Tôi thấy khá may mắn khi mỗi dự án web đều có thể dùng cả hai lựa chọn này
Hy vọng công việc về RSC không làm mờ đi sự hỗ trợ của React cho các ứng dụng render thuần phía client
Trừ khi nhất thiết cần một ứng dụng frontend giàu tính năng theo kiểu progressive hoàn chỉnh, phần lớn mọi thứ LiveView đều xử lý được qua component phía server với lượng JavaScript tối thiểu
Không chỉ vậy, mỗi người dùng còn có một thread phía server đi kèm, nên có thể chủ động đẩy thay đổi xuống frontend của người dùng mà không cần viết handler JavaScript tường minh
Có vẻ ngành này mắc chứng mất trí nhớ theo chu kỳ 10 năm
Việc rời xa UI render trên server từng có những lý do rất chính đáng
Tất nhiên luôn có lập luận về tối ưu hóa công cụ tìm kiếm, nhưng nếu lo chuyện đó thì cứ làm một site server template truyền thống là được
Đại đa số ứng dụng một trang hoàn toàn không cần SSR và sự phức tạp của nó
Giao diện dashboard ban đầu đều được render bằng Phoenix, và chỉ những trang thật sự cần tương tác client nâng cao mới nhúng React riêng lẻ
Vì sản phẩm đầu tiên là dashboard phân tích, tình huống đó nhanh chóng gần như trở thành toàn bộ dashboard, và việc chuyển sang một ứng dụng một trang hoàn chỉnh tận dụng API mà chúng tôi đã cung cấp cho khách hàng là điều tự nhiên
Khi đó là năm 2016 nên chưa có LiveView, nhưng nếu bây giờ làm lại sản phẩm đó, tôi cũng không chắc mình có quyết định khác không
Bài viết trên blog nói về ứng dụng vận hành site marketing công khai, với yêu cầu khá khác, nhưng tôi muốn nói rằng chúng tôi cũng dùng và thích Elixir/Phoenix
Có lẽ tôi đang già đi
Các framework ngày nay quá lớn và phức tạp
Ngay cả một trang web “Hello world” đơn giản cũng cần cả một pipeline build và compile đồ sộ, giờ lại còn gắn thêm cả component phía server
Tôi thật sự tò mò overhead lớn đến mức nào
Không biết để chạy một ví dụ Hello world thì code framework frontend và backend phải đi qua bao nhiêu lớp
Tôi sẽ quay về với framework component đơn giản 10KB, chỉ cần nhấn F5 là build lại
Đó chẳng khác nào tối ưu hóa quá sớm cho những tính năng hào nhoáng có thể xuất hiện sau này
Giống như nói rằng trước khi dựng chuồng gà, bạn phải thuê kỹ sư để lấy mẫu lõi và mô hình hóa sóng địa chấn
Các lập trình viên trẻ giờ đã bắt đầu nhận ra
Cũng như chúng ta từng bỏ lại những thứ kinh khủng như SOAP và XML để chuyển sang các công nghệ đơn giản hơn, dễ dùng hơn, thế hệ này cũng đang học lại rằng sự phức tạp là có hại
Biết đâu phát triển phần mềm sẽ lại trở nên thú vị trong vài năm, trước khi thế hệ mới lại làm nó rối tung lên
Pipeline có thể phức tạp hoặc đơn giản đến mức cần thiết tùy theo use case cụ thể
Bạn có thể chỉ dùng các file tĩnh, cũng có thể dùng một Makefile nhỏ với một lệnh
esbuild, hoặc một cấu hình Webpack khổng lồ với 30 pluginBạn hoàn toàn có thể chọn theo nhu cầu và độ phức tạp của thứ mình muốn xây dựng
Ngoài ra, đánh giá công cụ dựa trên việc có dễ tạo Hello world đơn giản hay không chỉ hữu ích khi công việc thực tế đúng là tạo những ứng dụng như vậy
Mỗi khi SSR hoặc các biến thể của nó xuất hiện trong cuộc thảo luận, tôi luôn tự hỏi liệu có phải nó đang làm mọi thứ phức tạp hơn một cách không cần thiết hay không
React server-rendered components nghe như đã đi quá xa, và đi ngược lại luồng trải nghiệm phát triển tự nhiên
Nếu độ phức tạp của ứng dụng tăng gấp đôi, các bẫy khi code nhiều hơn khiến lập trình viên chậm lại và bối rối hơn, trong khi thứ nhận được chỉ là một cải thiện hiệu năng nhỏ, thì tôi nghi ngờ liệu có đáng không
Các site PHP ngày xưa và ứng dụng Rails không phải single-page app cũng đã hoạt động tốt trong thời gian dài
Tôi đã trải qua chuyện này khi tạo một ứng dụng mới với Next.js và cấu trúc thư mục
appmớiThứ nhất, rất khó suy luận điều gì xảy ra trên server và điều gì xảy ra trên client
Muốn biết thì phải điều tra, nhưng khi viết code nhanh thì hầu hết sẽ không quá để ý
Chỉ một thay đổi nhỏ cũng rất dễ khiến một phần lớn của trang đột ngột muốn chuyển từ server sang client
Tôi biết trước khi release cuối cùng sẽ phải kiểm chứng cẩn thận, tốn thời gian theo từng trang, và điều đó chẳng hay ho gì
Thứ hai, khá nhiều thư viện React hiện có dùng hook nên được giả định là chạy trên client
Vì thế code có thể bị kéo sang client
Mục đích của việc vật lộn với paradigm mới là server-side rendering để tải nhanh và tối ưu hóa công cụ tìm kiếm, nhưng nếu thư viện được import không hợp tác tốt thì coi như hoàn toàn lãng phí
Thứ ba, paradigm thư mục
appmới của Next.js có bugNó vẫn còn mới và rất phức tạp, nên dynamic route, parallel route và tương tác giữa chúng có thể hỏng hoàn toàn
Tôi đã trực tiếp mở issue trên GitHub của Next.js và nhận được nhiều bình luận kiểu “tôi cũng vậy”
Một cách tiếp cận tôi từng dùng gần đây đã được một lập trình viên của Vercel sửa, nhưng lúc đó tôi đã chọn cách khác để né rồi
Điều khó chịu nhất là môi trường phát triển dùng lazy loading và phép màu caching
Có vẻ nó cố tính toán khác biệt của trang rồi gửi partial update qua thứ gì đó giống websocket, nhưng nó có thể hỏng hoàn toàn đến mức không thể khôi phục
Đôi khi việc biên dịch lại gây ra một giao tiếp nào đó từ server sang client, và khi quay lại tab Chrome thì tab bị treo cứng hoàn toàn, phải dùng Chrome Task Manager để kill process
Nhìn chung nó vẫn còn rất mới và có nhiều góc cạnh thô ráp
Nhiều hook cũng hoạt động ở phía server, và thực tế không làm gì ngoài việc khởi tạo giá trị
Điều thú vị là PHP và JavaScript thực ra gần như có cùng cú pháp
Khác biệt chỉ cỡ ký hiệu
$hay từ khóavar, nhưng NodeJS thì nói “chúng tôi muốn chạy JS trên máy chủ”Và 15 năm sau, JavaScript rốt cuộc cũng bắt kịp, về cơ bản trở nên giống PHP, chỉ là nhiều từ viết tắt hơn và đường cong học tập dốc hơn
Tất nhiên, việc stream dữ liệu từ máy chủ sang client component bằng Suspense thì rất hay
Tôi đang dùng NextJS 13, và thích việc nó làm cho SSR trở nên dễ dàng như PHP vốn luôn làm được; rất khuyến nghị
Khi mọi người gọi nó là “fractal của thiết kế tồi” thì hoàn toàn có lý, và việc họ tìm sang nơi khác để giải quyết vấn đề cũng là chính đáng
PHP ngày nay là một ngôn ngữ tốt hơn rất nhiều và đáng để xem lại, nhưng không nên giả vờ rằng từ xưa nó đã tốt như bây giờ
Và cũng không nên đánh giá NodeJS dựa trên hệ sinh thái React
Lượng API và wrapper khổng lồ cần thiết để vận hành các hệ thống dựa trên React là trách nhiệm của cộng đồng React
Đúng kiểu hội chứng Stockholm điển hình
Nhiều tiến bộ hiện đại có thể xảy ra cũng là vì trước hết trình duyệt đã tốt hơn
Không hẳn là đi trọn một vòng, mà giống một khối gì đó nhìn từ rất xa thì trông như hình tròn hơn
Một mặt, nó mang tính đột phá ở chỗ mô hình concurrency giúp tạo backend nhanh hơn, nhưng nó thiếu nhiều tính năng của các ngôn ngữ backend sẵn có như Java hay PHP, nên rất nhiều pattern đã bị phát minh lại
Bản thân ngôn ngữ cũng mất nhiều năm mới đạt tới mức “an toàn” mà Java đã có sẵn và PHP đang hướng tới
Những công nghệ đã được kiểm chứng và chuẩn hóa như XML cùng các bảo đảm dạng hợp đồng mà nó có thể mang lại cũng bị vứt bỏ vì những lý do như quá nặng, hay JSON dễ đọc dễ viết hơn cho con người
Tôi cảm thấy chúng ta đã mất rất nhiều thời gian và công sức khi bỏ XML
Việc viết tài liệu cho REST/JSON API đến nay vẫn còn đau đớn
Từ 20–25 năm trước, ta đã có thể sinh data model và parser từ payload XML rồi
Đến giờ tôi vẫn không hiểu XML có vấn đề gì nghiêm trọng đến vậy
Trên đường truyền nó nặng hơn JSON một chút, nhưng đó là vấn đề có thể giải quyết bằng nén hoặc biến nó thành giao thức nhị phân với EXI (https://www.w3.org/TR/exi/)
Tôi không biết EXI có thực sự được chấp nhận rộng rãi hay không, nhưng vì biết thời đó XML được trao đổi nhiều đến mức nào nên tôi đã khá kỳ vọng
Khi đó, I/O không chặn tạo ra cải thiện hiệu năng lớn
Nhưng trong đầu các lập trình viên hiện đại, nó dường như bị đẩy xuống thành một công cụ ngớ ngẩn chỉ để nhả JSON hoặc host toolchain
Có lẽ là dùng thứ quen thuộc, nhưng việc dùng React cho một trang tài liệu thay vì một static site generator hoặc CMS có sẵn kèm caching trông có vẻ lãng phí
Với lập trình viên thì React có thể thú vị hơn
Stripe đã khởi đầu luồng hiển thị các đoạn code có kèm API key của tài khoản để bạn có thể thử ngay
Các trang tài liệu frontend gần như luôn có ví dụ chạy được để có thể tương tác trực tiếp trong tài liệu
Bootstrap một dự án mới quá dễ và nhanh, theo đúng nghĩa còn dễ hơn bắt đầu một dự án HTML thuần
Tôi đang bỏ sót điều gì vậy?
Nhân tiện, tôi thật sự tò mò về góc nhìn của những người bấm không tán thành
Đây là nội dung tĩnh, tại sao không sinh ra HTML rồi gắn thêm chút JavaScript cho ô tìm kiếm nhỉ?
Lý do dùng React là để dùng một ngôn ngữ trên toàn bộ frontend
Có thể tránh cảnh người này dùng React cho một site, người khác dùng Gatsby/Hugo cho site khác
Next.JS có thể làm những việc giống Gatsby/Hugo, lại có nhiều tính năng hơn và dựa trên React
Tôi đủ lớn để còn nhớ thời máy chủ render mọi thứ, còn CSS và Javascript chỉ được dùng để bổ sung cho trang đã render
Web đã trở thành một nơi quá u ám và over-engineered
Gần như khó tin
Vì vậy cách tôi xây dựng ứng dụng là ưu tiên server rendering, rồi bổ sung sau
Dropdown có thể thu gọn hay kéo-thả bằng jQuery là những tính năng có thì tốt, nhưng tôi cũng nhớ rất rõ địa ngục quản lý trạng thái thời js/jQuery, nên không muốn quay lại đó
Đùa thôi, trang Geocities đầu tiên của tôi chỉ là HTML với vài thứ như bộ đếm lượt truy cập hay marquee
Ứng dụng/dự án PHP đầu tiên làm ở trường cũng chưa dùng JS; menu tĩnh và header thì dùng frame, còn dữ liệu chỉ được gửi về backend bằng form submit
Đã từng có một thời như vậy
Trong kỳ thực tập một năm đầu tiên thuộc chương trình đại học, chúng tôi dùng backend Java, template JSX ở tầng trình bày, và PrototypeJS cho những thứ như dialog hay accordion có animation
Khi đó animation nghĩa là “thay đổi chiều cao của phần tử này vài lần mỗi giây”
Ở công việc đầu tiên, tôi dùng khá nhiều JS để bổ sung cho trang, kiểu như thêm vào giỏ hàng, carousel ảnh, và đó là thời của jQuery
Ở công việc tiếp theo, chúng tôi làm rất tệ một UI bằng BackboneJS để nhân viên hỗ trợ khách hàng xem những thứ kiểu SAP
Công việc sau đó nữa cũng là làm lại frontend ngân hàng đầu tư cho khách hàng bằng BackboneJS
Đó là một use case rất hợp với thứ khi ấy được gọi là ứng dụng một trang
Không cần tối ưu hóa công cụ tìm kiếm, render thuần frontend đã đủ nhanh, lấy API làm trung tâm, và đó là giai đoạn mọi người nhận ra có thể dùng cùng một API cho web và mobile
Theo tôi, công cụ phát triển web chưa bao giờ tốt hơn bây giờ, và trải nghiệm người dùng cũng đã cải thiện cực kỳ nhiều trong nhiều năm qua
Thứ chúng ta từng gọi là AJAX đã phát triển từ một món đồ chơi bổ trợ gọn gàng thành thành phần mặc định hằng ngày dưới dạng client component và ứng dụng một trang
Máy chủ vẫn rất mạnh nếu muốn, nhưng với các ứng dụng tương tác như dashboard, bản đồ, game, diễn đàn, ứng dụng văn phòng, IDE online, năng lực mạnh phía client là điều tốt
Nhờ vậy, các ứng dụng hằng ngày đã có thể dịch chuyển quy mô lớn từ app desktop tùy biến cho từng hệ điều hành sang một nền tảng phổ quát bao phủ mọi laptop và desktop
Tất nhiên sức mạnh đó đòi hỏi nhiều độ phức tạp hơn
Viết blog hay landing page bằng HTML/CSS rất khác với viết một web app hoàn chỉnh
Angular và React được tạo ra để giúp phát triển các ứng dụng phức tạp hơn trước nhiều lần, vào thời JS runtime và bản thân ngôn ngữ còn thô sơ hơn nhiều so với các ngôn ngữ server-side lúc đó
Cuối thập niên 2010 đã có một giai đoạn thật sự đau đớn, khi nhiều framework JS mỗi cái chỉ giải quyết được một phần rất nhỏ của vấn đề
Ngày nay thì đỡ hơn
Next đã thắng và trở thành mặc định, và điều đó cũng xứng đáng
Nó cung cấp mức trừu tượng phù hợp cho ứng dụng có độ phức tạp trung bình, và cho phép trộn tốt server-side rendering với các trang client-side
React Server Components biến ranh giới đó thành một khái niệm hạng nhất gọn gàng hơn
Tuy nhiên nó chỉ có ý nghĩa từ một mức độ phức tạp nhất định trở lên
Nếu không cần thì đừng dùng
Nếu là blog hoặc trang tài liệu phần lớn tĩnh, có những kiến trúc đơn giản hơn
Bạn vẫn có thể viết HTML và rải vài dòng JS khi cần, và với đa số doanh nghiệp nhỏ thì WordPress hay Wix cũng dùng được
Nhưng nếu làm ứng dụng phức tạp hơn, React thật sự như một giấc mơ so với cách mỗi tương tác nhỏ đều phải đi vòng về server để tính lại UI và gửi toàn bộ trang HTML mỗi lần
Cách đó làm mất context, vị trí trang, các form đang điền dở, khuyến khích dùng dữ liệu form làm state, và thường khiến người dùng mất công việc vì lỡ bấm Back hoặc do server hay sập trước khi có mở rộng cloud dễ dàng
Theo tôi, nó chỉ là over-engineering khi áp dụng sai
Trong use case phù hợp, những công cụ này thật sự hữu ích và đôi khi là thiết yếu
Điều đáng tiếc có lẽ là chúng được dạy và khuyến khích dùng quá nhiều ngay cả trong những tình huống không cần, hoặc còn gây hại
Rốt cuộc phải dùng đúng công cụ cho đúng việc
Tôi không định đẩy React lên trên Vue, Svelte hay HTMX; ý tôi là độ phức tạp phía client cũng có ích
Tôi có cảm giác React đang chật vật đuổi theo những lựa chọn thay thế hiện đại hơn, dễ hơn, nhanh hơn và rẻ hơn
Nhưng thay vì sửa các vấn đề cốt lõi như re-render, memoization thường xuyên cần đến, và abstraction bị rò rỉ, React lại ngày càng phức tạp hơn
Nếu kết quả cuối cùng xuất sắc thì tôi có thể hiểu nỗ lực đó, nhưng không phải vậy
Trong môi trường thực tế, React chậm hơn những gì benchmark cho thấy, còn Next thì tệ hơn
Gần đây tôi thấy rất nhiều website cực kỳ chậm được làm bằng Next
Tôi thật sự không hiểu
Nếu đội React muốn cải thiện React, họ phải sửa phần lõi
Bây giờ có quá nhiều phụ thuộc trong hệ sinh thái nên sẽ làm vỡ mọi thứ
Target.com, Walmart.com, Microsoft Teams và vô số website khác đều là React
Còn có cả hệ sinh thái component khổng lồ và những công ty được xây trên đó
Khái niệm cốt lõi đã bị hỏng, nhưng sửa nó đồng nghĩa có thể phá vỡ mọi thứ còn lại
Nếu đằng nào cũng phá vỡ tất cả, tốt hơn là dùng thứ khác
Giờ đây vì khối lượng phụ thuộc quá lớn, người ta bị buộc vào React và cứ phải tiếp tục lăn theo nó
React mặc định re-render rồi cho bạn opt out, trong khi Vue, Solid, Preact, Svelte đều là opt in ở nơi cần thiết
Đây là một trong những lý do cốt lõi khiến nó khó dùng đúng và dễ dính một số loại bug nhất định
Bề ngoài trông như JavaScript bình thường, nhưng bạn luôn phải để ý xem có nên opt out tiếp không; ở các framework khác, những bug như vậy hiếm hoặc gần như không có
https://react.dev/blog/2023/03/22/react-labs-what-we-have-be...
Tôi không hiểu tại sao đến bây giờ lại dùng React ở backend để render HTML
Chẳng lẽ muốn quay lại 10 năm trước sao
Dạo này tôi thường qua lại giữa Svelte và template Django; chỉ riêng việc Svelte hiểu DOM đã khiến trải nghiệm tốt hơn rất nhiều
Tôi chưa từng thấy điều như vậy trong các hệ thống template không phải JS
Tôi cũng đã từng trải qua PHP, jQuery, v.v.
Hơn nữa, nếu frontend là React thì việc đặt toàn bộ phần tạo HTML ở một nơi sẽ dễ hơn nhiều
Thêm vào đó còn có hỗ trợ kiểu tĩnh
Tôi không định bênh vực rằng RSC hay React là giải pháp tốt nhất mọi thời đại, nhưng một số phản biện ở đây còn khá non
Lợi ích của React/RSC không giống về mặt kỹ thuật với việc server trả về HTML/CSS và một chút JavaScript
Nó vẫn là một ứng dụng duy nhất, và là cách xử lý ranh giới client/server thông minh hơn so với SSR/hydration
Tôi rất muốn đọc thêm những phản biện hiểu biết hơn về việc liệu React có tự thiết kế mình vào ngõ cụt hay không, và lối thoát là gì; nhưng quay lại PHP không phải là câu trả lời
React cũng không khó học đến vậy, và có lý do vì sao cả người không phải lập trình viên cũng nắm được cơ bản sau vài tuần bootcamp
JSX khách quan mà nói vượt trội hơn các hệ thống template của Django, PHP, Rails
Tôi đoán một nửa những phản biện ném ra qua loa thậm chí còn chưa benchmark dự án của mình bằng những thứ như Lighthouse