- Đội ngũ Hardcover đã migration sang Ruby on Rails + Inertia.js do gặp các vấn đề về suy giảm hiệu năng của kiến trúc dựa trên Next.js, chi phí cao và tốc độ phát triển chậm lại
- Họ chọn Inertia.js để đáp ứng các yêu cầu SSR hỗ trợ SEO, kết nối trực tiếp tới DB và tiếp tục dùng React
- Mức phí tăng vọt ngoài dự kiến trên Vercel và Cloud Run cùng với sự thiếu rõ ràng trong cơ chế cache của Next.js là yếu tố quyết định cho việc chuyển đổi
- Inertia.js trở thành cách lý tưởng để kết nối backend Rails với frontend React, giúp SSR và quản lý cache dễ hơn
- Sau khi chuyển đổi, điểm Google Pagespeed và SEO được cải thiện, đồng thời thời gian truy cập trên site và mức độ hiển thị trên tìm kiếm tăng lên
Bối cảnh chuyển đổi
- Ban đầu, nhóm chọn Next.js có hỗ trợ SEO và SSR và xây dựng trên kiến trúc dựa trên GraphQL API
- Phần lớn dữ liệu được yêu cầu phía client trong trình duyệt, còn dữ liệu tĩnh thì được cache ở server
- Theo thời gian, do thiếu cache nên số lượng yêu cầu API tăng lên, hiệu năng giảm sút và môi trường phát triển cũng chậm đi
Các vấn đề phát sinh với Next.js
- Ngay cả sau khi chuyển sang App Router, tốc độ cải thiện rất ít; các yêu cầu Apollo POST không được cache nên không đạt hiệu quả như kỳ vọng
- Do thay đổi chính sách giá của Vercel, chi phí hàng tháng tăng mạnh từ $30 → $354
- Cloud Run ban đầu cũng rẻ, nhưng sau đó tăng lên tới $524
- Khó nắm bắt cấu trúc cache của Next.js nên không thể quản lý hiệu quả
- Tốc độ phát triển giảm rõ rệt, gây khó khăn cho việc onboarding nhân sự mới
Lý do chọn Rails + Inertia.js
- Nhóm muốn duy trì SSR đồng thời lấy dữ liệu trực tiếp từ DB
- Họ cũng muốn tiếp tục dùng React, và dù đã xem xét Remix, react-rails, react_on_rails, cuối cùng vẫn chọn inertia-rails
- Inertia.js cho phép sử dụng routing của Rails mà không cần routing ở frontend, đồng thời triển khai SSR cũng thuận lợi
- Trong controller, việc render được xử lý bằng
inertia: 'tên trang', còn cache được triển khai bằng Rails.cache.fetch
- Trong component React, nhận props bằng
usePage()
Cấu trúc SSR và build
- Để hỗ trợ SSR, trong
application.tsx xử lý phân nhánh hydrateRoot / createRoot
- Vite được vận hành như một server độc lập và hỗ trợ hot reload trong quá trình phát triển
- Tự động hóa triển khai Rails + Vite thông qua Docker và Kamal, tách biệt giữa staging và production
- Khi deploy, chạy bằng lệnh
make deploy, asset host dùng CloudFlare để tối ưu cache
Hiệu quả sau chuyển đổi
- Sau khi phát hành bản migration vào ngày 18/03/2025, mức độ hiển thị trên Google tăng lên và tốc độ trang được cải thiện
- Total Blocking Time được cải thiện đáng kể, kéo theo điểm Pagespeed tăng
- Thời gian ở lại trung bình của khách truy cập tăng theo xu hướng từ 3 phút → 6 phút
- Lưu lượng truy cập được giữ ổn định trong khi số lượng đăng ký thành viên vẫn duy trì ổn định
Thách thức và điểm cần cải thiện sắp tới
- Khó tái sử dụng layout dùng chung, và vẫn tồn tại vấn đề render lại hoàn toàn ở từng trang
- Khó debug SSR, thiết lập môi trường phức tạp
- Thiếu tài liệu cho tổ hợp Inertia.js và Rails, nên nhóm phải giải quyết qua cộng đồng Discord
- Cần thích nghi với cách làm của Inertia thay vì Suspense
- Hiện tại vẫn tiếp tục dùng Hasura, nên một số tính năng của Inertia như form, flash... vẫn chưa được tận dụng
Kết luận và kỳ vọng
- Cấu trúc tích hợp React + Rails một cách tự nhiên đã nâng cao năng suất phát triển và khả năng bảo trì
- Việc chọn Inertia.js giúp đảm bảo đồng thời tốc độ, SSR và độ an toàn kiểu dữ liệu
- Trong tương lai, nhóm có kế hoạch mã nguồn mở hóa và thu hút thêm contributor
2 bình luận
Khi dùng
Linktrong next.js, đang có tranh cãi vì để sử dụng React Server Components thì URL sẽ được tạo và xử lý theo kiểu như?_rsc=1ip3i. Cũng có tin nói chi phí dùng CDN đã tăng vọt, và nghe nói đội ngũ phát triển next.js cũng đã biết về vấn đề này, nhưng vẫn chưa rõ sẽ được khắc phục theo cách nào và vào thời điểm nào.Ý kiến Hacker News
Server-side rendering (SSR) chưa bao giờ biến mất, và web giờ chỉ mới nhớ lại vì sao đó từng là mặc định. Lần render đầu tiên và SEO vẫn tốt hơn khi markup được gửi từ server. Nhiều framework như Rails + Turbo, HTMX, Phoenix LiveView, React Server Components đều lấy SSR làm nền tảng. Phần lớn dashboard và ứng dụng CRUD không cần client router, global state hay gói hydration 200kB, mà chỉ cần thay thế từng phần HTML
Động lực thực sự là chi phí của độ phức tạp. Mỗi dòng JS phía client đều kéo theo build tool, tiếng ồn từ npm audit và rủi ro chuỗi cung ứng. Giảm tải phần này sẽ đồng thời cải thiện hiệu năng và bảo mật. Tất nhiên, các ứng dụng như Figma hay Gmail vẫn hưởng lợi từ logic client nặng. Vì vậy, mô hình đang nổi lên là "HTML mặc định, JS chỉ ở nơi cần thiết". Hãy nghĩ theo kiểu các hòn đảo thay vì một SPA nguyên khối
Vì vậy, đúng là đang có sự quay lại với server, nhưng đây không phải nỗi hoài niệm về PHP năm 2004. Đó là việc điều chỉnh JavaScript cho hợp lý và để HTML xử lý 90% công việc nhàm chán mà nó vốn luôn làm tốt
Chúng tôi đã dùng NextJS cho một vài dự án nhưng hiện đã bắt đầu loại bỏ dần. Có nhiều lý do, nhưng một vài yếu tố chính là như sau
Câu chuyện xác thực khá khó khăn. next-auth có một số hạn chế nên chúng tôi chuyển sang dùng iron-session. Ví dụ, không thể dùng miền nhà cung cấp ID động nên chúng tôi phải tự sở hữu toàn bộ luồng openid. Vẫn làm được, nhưng đó là khoản tốn thời gian không ngờ tới đối với một framework đã trưởng thành
Vì server NextJS không phải API gateway chính của chúng tôi nên phải proxy mọi request. Tài liệu không rõ ràng, và điều đó còn làm phát sinh các vấn đề ngẫu nhiên như timeout request / kích thước header tối đa, v.v.
Framework này đẩy việc chuyển sang cloud quá quyết liệt, điều đó xung đột với mục tiêu của chúng tôi
Những người bảo trì đặc biệt không mấy hữu ích. Chúng tôi dùng các công cụ/framework khác dù có khuyết điểm, vì đội ngũ bảo trì rất dễ tiếp cận và hỗ trợ tốt (cảm ơn Chillicream/HotChocolate)
Tôi nhớ năm ngoái đã đọc một bài blog nói rằng SEO được cải thiện khi chuyển từ page router sang app router của Next.js. Lần này chúng tôi đang chuyển từ Next sang React+Inertia.js do chi phí Vercel tăng lên. Triển khai cùng ứng dụng đó lên VPS riêng thay vì nhà cung cấp cloud có lẽ đã giải quyết được vấn đề. Tuy nhiên, tôi không hiểu vì sao lại muốn thêm độ phức tạp. Tôi tự hỏi liệu một ứng dụng theo dõi sách có thực sự cần GraphQL, một framework frontend riêng biệt và quy trình build phức tạp hay không, hay lẽ ra có thể được giải quyết ngay từ đầu bằng cách triển khai một ứng dụng RoR duy nhất với HTML template lên VPS
Mỗi khi thấy các bài viết và thảo luận về web và stack, tôi đều tự hỏi: "Rốt cuộc đang giải quyết vấn đề gì?" Câu trả lời luôn là "hiển thị văn bản lên màn hình"
Tôi tò mò không biết mọi người làm gì khi muốn full stack JS, đặc biệt là khi có DB đi kèm. Tình hình ORM khá phân mảnh hoặc bạn phải viết SQL thuần. Và bạn vẫn phải quyết định backend. Dùng express chăng? Next.js thì nổi tiếng nhưng có vẻ theo đuổi một chương trình nghị sự đáng ngờ. Remix, Astro, TanStack, v.v. Mọi thứ khá rối vì lúc nào cũng phải cân chỉnh và đánh giá lại xem nên dùng gì
Với các dự án cá nhân, tôi thường quay lại Ruby on Rails. Lúc nào cũng thấy vui. Mặt khác, lại có quá ít lập trình viên Rails sẵn có (so với JS) nên nó không phù hợp cho các dự án chuyên nghiệp. Việc chọn JS và thường là Java cho backend không phải là thiếu trách nhiệm
Tôi muốn biết có ai khác cũng có cảm giác tương tự không
Lập trình viên frontend và backend từ lâu đã không thực sự nói chuyện tốt với nhau
Xét về lịch sử, với tư cách là một lập trình viên backend, tôi ghét Html/JS/CSS. Đây là một hệ tư duy khác hẳn so với Swing/Awt, WinForms, Android UX, v.v. Chỉ riêng điều đó cũng đủ khiến tôi nản và ở lại với backend. Để học frontend, tôi phải học cả ba thứ này. Mãi đến bây giờ tôi mới dần quen
Nhưng các lập trình viên frontend thì lại phải học "thêm một ngôn ngữ nữa". Nhiều ngôn ngữ có hệ thống build khác và khó chịu hơn so với nvm. Và như bất kỳ ai từng chuyển ngôn ngữ đều biết, bạn còn phải học framework mới, hệ tư duy mới, v.v.
Thay vào đó, một số người nhận ra rằng có thể đẩy JavaScript sang backend. Nó có nhiều nhược điểm, nhưng với những người chỉ cần "làm cho xong việc", đặc biệt trong một thế giới của "cứ thêm server đi" và "tiền VC là miễn phí! Đốt vào hạ tầng đi!", thì những nhược điểm đó chẳng đáng lo
Nhưng các lập trình viên frontend, giờ là "full stack developer" nhưng thực ra là "mọi thứ đều bằng JavaScript developer", vẫn tiếp tục tạo ra sản phẩm theo cách rất dễ thấy. Điều này hiện được phản ánh trong các tin tuyển dụng trên LinkedIn, nơi yêu cầu vai trò Next.JS/Node.JS/các vai trò tương tự. Một ngôn ngữ để thống trị tất cả
Chỉ là vài suy nghĩ, nhưng tôi cho rằng điều này liên quan rất mạnh đến lý do mọi người chọn Next.JS
Tôi không thể nói về khía cạnh kỹ thuật (vì tôi chỉ quen với Next.js chứ không quen Rails, nên không rõ bài viết này phản ánh sự thoải mái của tác giả với Rails hay một kiến trúc thực sự phù hợp hơn về mặt kỹ thuật). Tuy nhiên, tôi thấy khá lạ khi một công ty có nhiều kỹ sư phần mềm lại lo lắng về chi phí hạ tầng dưới 1.000 USD mỗi tháng. Lo lắng về chi phí hosting như vậy có vẻ không khôn ngoan
Nếu Rails tập trung vào việc mang lại hỗ trợ hạng nhất thực sự cho khả năng tương tác với các framework frontend, có lẽ giờ nó đã lớn hơn rất nhiều. Họ đã đổ nhiều công sức vào Hotwire, nhưng tôi muốn dùng React, và người khác cũng sẽ muốn dùng thứ họ đã quen
Tôi tự hỏi vì sao lại có cuộc tranh luận Next.js vs. SSR. Next.js là mô hình hybrid và hoạt động khá tốt. Không giống các framework SPA khác, Next.js tạo ra đầu ra HTML được prerender để tải lần đầu nhanh hơn, cung cấp các JS chunk hiệu quả, các công tắc cấu hình như preload khi hover lên link hoặc preload tất cả các liên kết n+1 sau khi render trang, đồng thời hỗ trợ tải trước hình ảnh hiệu quả theo breakpoint (đây thường là gót chân Achilles nếu so với các giải pháp SSR thuần)
Tôi đã viết Rails một chút, nhưng không thực sự hiểu vì sao mọi người lại quá hào hứng với nó. Nó hoàn toàn ổn, nhưng tôi không thấy điều gì đặc biệt