13 điểm bởi GN⁺ 2025-06-13 | 5 bình luận | Chia sẻ qua WhatsApp
  • Từ Next.js 15.1.8, cách xử lý metadata đã thay đổi, gây ra các vấn đề nghiêm trọng trong môi trường triển khai ngoài Vercel
    • Metadata không còn được render trực tiếp trong phần head của HTML mà được gửi riêng bằng cơ chế gọi là "metadata streaming"
  • Nếu công cụ tìm kiếm không chạy JavaScript thì metadata sẽ hoàn toàn không lộ ra, khiến SEO bị tổn hại nghiêm trọng
    • Có xử lý ngoại lệ bằng cơ chế phát hiện crawler (htmlLimitedBots), nhưng không hoàn hảo
  • Các nền tảng không phải Vercel như Netlify, Cloudflare, AWS... đang cố tương thích qua OpenNext, nhưng trên thực tế Next.js bị ràng buộc quá chặt với hạ tầng Vercel nên bản thân việc port đã khó và đầy lỗi
  • Ngay cả bản build tĩnh cũng không đưa metadata vào phần head của HTML, khiến mọi môi trường triển khai bị buộc phải xử lý phát hiện crawler/chạy JS theo cấu trúc phức tạp
  • Vấn đề bảo mật (lỗ hổng nghiêm trọng được công bố vào tháng 3/2025)
    • Nếu cố bám vào phiên bản cũ để tránh metadata streaming thì sẽ bị phơi bày trước lỗ hổng bảo mật nghiêm trọng (bản vá chỉ có từ 15.2.3)
  • Metadata streaming trên thực tế che giấu vấn đề hiệu năng trang và còn tác động tiêu cực đến SEO
  • Kết luận:
    Next.js trông như mã nguồn mở, nhưng trên thực tế đã trở thành một framework phụ thuộc nghiêm trọng vào Vercel, nên với dự án mới sẽ khôn ngoan hơn nếu cân nhắc lựa chọn khác

Tổng quan

  • Từ phiên bản Next.js 15.1.8, việc xử lý metadata gặp vấn đề nghiêm trọng trong các môi trường ngoài Vercel
  • Điều này về bản chất làm mức độ phụ thuộc vào hạ tầng Vercel sâu hơn, đồng thời làm giảm tối ưu hóa công cụ tìm kiếm (SEO), thậm chí còn dẫn tới đe dọa bảo mật

Khởi đầu của vấn đề: sự xuất hiện của metadata streaming

  • Trong năm 2024, Vercel đã giới thiệu tính năng thử nghiệm metadata streaming
  • Khác với cách cũ, metadata (các thẻ như title, description, Open Graph...) không được render trực tiếp vào HTML `` mà được gửi riêng sau khi tải trang ban đầu
  • Tính năng này khiến việc thực thi JavaScript trở thành bắt buộc

Giải thích kỹ thuật của Vercel và các vấn đề thực tế

  • Lý do đưa vào: nhằm giải quyết nút thắt tính toán khi tạo metadata
  • Nhưng trên thực tế metadata phần lớn là dữ liệu tĩnh và rất nhỏ (dưới 1KB)
  • Chi phí round-trip từ server còn lớn hơn xử lý inline
  • Metadata động chỉ là một số rất ít trường hợp ngoại lệ
  • Việc triển khai metadata streaming làm tăng thêm độ phức tạp và sự rối rắm

Bối cảnh của vấn đề hiệu năng

  • Một số lập trình viên từng gặp vấn đề hiệu năng là độ trễ khi tạo metadata, chẳng hạn khi tích hợp API bên ngoài
  • Để giải quyết việc này, Vercel đã phát triển cách tiếp cận streaming

Ảnh hưởng tới crawler của công cụ tìm kiếm và SEO

  • Các công cụ tìm kiếm không chạy JavaScript sẽ không đọc được metadata
  • Vì vậy điều này gây ảnh hưởng xấu lớn đến SEO
  • Như một cách khắc phục, Vercel cung cấp tính năng htmlLimitedBots để khi server phát hiện crawler thì bỏ qua streaming và đưa metadata vào HEAD

Giới hạn của các nhà cung cấp cloud khác

  • Netlify, Cloudflare, AWS... cũng đã tạo dự án adapter OpenNext để tương thích với Next.js
  • Nhưng vì Next.js phụ thuộc quá chặt vào Vercel, việc di chuyển đòi hỏi phải reverse engineering
  • Do vấn đề chất lượng của OpenNext nên trên thực tế nó không hoạt động đúng như kỳ vọng

Ngay cả build tĩnh cũng chưa hoàn chỉnh

  • Build site tĩnh (Static Build) cũng không còn đưa metadata vào phần head của HTML
  • Vì được bundle cùng React Server Components nên cần thực thi JavaScript
  • Đã vậy còn nảy sinh sự vô lý là phải tự triển khai cả logic phát hiện crawler chỉ để có metadata HTML cơ bản

Lỗ hổng bảo mật nghiêm trọng và vấn đề cập nhật

  • Ngày 21/3/2025, lỗ hổng nghiêm trọng (mức bảo mật 9.1, GHSA-f82v-jwr5-mffw/CVE-2025-29927) đã được công bố
  • Lỗ hổng này cho phép vượt qua bảo mật xác thực của middleware bằng cách thao túng một header cụ thể
  • Bản vá được áp dụng ở Next.js 15.2.3, nhưng nếu ở lại 15.1.8 để tránh metadata streaming thì sẽ rất dễ tổn thương về mặt bảo mật

Hệ quả tiêu cực do streaming mang lại

  • Metadata streaming càng che giấu các vấn đề hiệu năng tiềm ẩn
  • Nếu việc xử lý metadata của trang bị chậm, người dùng thực tế sẽ không nhận ra
  • Nhưng crawler của công cụ tìm kiếm sẽ áp dụng điểm phạt SEO khi phản hồi chậm

Kết luận

  • Next.js đã biến chất thành vendor lock-in của Vercel được ngụy trang dưới dạng framework mã nguồn mở
  • Khi chọn tech stack cho dự án tiếp theo, sẽ khôn ngoan hơn nếu cân nhắc framework khác thay vì Next.js

5 bình luận

 
kansm 2025-06-13

Vậy thì Remix sẽ là phương án thay thế nhỉ?

 
bth15923 2025-06-13

Đúng như đã nêu trong bài, mức độ khóa nhà cung cấp quá mức, cách vận hành quá kiểu hộp đen, và các API thiếu trực quan. Hơn nữa, phía React cũng đang công khai quảng bá kiểu phát triển render trên server như thể đó là phương thức phát triển tiêu chuẩn của React. Tôi cho rằng phần lớn ứng dụng chỉ cần một SPA dựa trên Vite là đủ.

 
pcj9024 2025-06-13

Việc bị khóa vào nhà cung cấp ở một mức độ nào đó thì có thể chấp nhận được, nhưng ý kiến về chính công nghệ Next.js nếu cứ đọc thì có vẻ cũng không vượt quá mức "tôi không muốn đọc bài viết".

 
ndrgrd 2025-06-13

Trước đây họ vẫn liên tục tỏ ra cởi mở nhưng hành xử khép kín, giờ thì cuối cùng cũng gần như khóa chặt cửa rồi.

 
GN⁺ 2025-06-13
Ý kiến trên Hacker News
  • Tôi tuyệt đối không khuyên dùng Next. Trải nghiệm lập trình viên quá tệ, vendor lock-in nặng, lại có nhiều quy ước kỳ quặc không được tài liệu hóa, nên trừ khi chỉ làm B2B SaaS đơn giản kiểu CRUD thì cảm giác chỗ nào cũng có mìn. Đặc biệt, tôi từng gặp trường hợp thẻ Next <Image /> làm FPS của cảnh webgl trên cùng trang rơi xuống 2

    • Tôi tự hỏi Vercel đã từ từ "luộc ếch" người dùng React phổ thông vào vendor lock-in như thế nào. React vốn là dự án mà Meta nhấn mạnh tính mã nguồn mở, và tôi từng hy vọng open source sẽ giúp ngăn vendor lock-in, nhưng thực tế lại không như vậy, khá thất vọng

    • Hoàn toàn đồng ý. Gần đây tôi dùng lại Next sau một thời gian dài và trải nghiệm phát triển thực sự rất thất vọng. Tài liệu mơ hồ, khó tìm, bản thân app cũng mặc định có cảm giác chậm. Tôi đã gặp vô số khó khăn khi cố deploy lên AWS bằng Docker vì Dockerfile mẫu mà Vercel cung cấp

    • Tôi tò mò không biết bạn đã tự phân tích trực tiếp vấn đề <Image /> đó chưa hay chỉ đang suy đoán đó là lỗi của NextJs. Tôi đang làm việc với tổ hợp NextJs, <Image>, RTF nhưng chưa từng gặp vấn đề như vậy

  • Tôi đã dùng Next.js trong công việc suốt 3 năm qua và thật sự thấy rất đau khổ. Hosting trên Vercel, công ty thì gần như triển khai toàn bộ dịch vụ của Vercel nên đúng kiểu trải nghiệm vendor lock-in toàn diện. Trước đây tôi đã chia sẻ trải nghiệm tệ trong một bài Dan đăng trên HN về RSC, và tôi thấy nhận định của anh ấy rất chính xác. Kiểu như câu "bản thân RSC giờ đã khá vững, nhưng các framework như Next.js thì vẫn còn hơi thô". Tổng thể thì React giờ cũng đã dưới mức trung bình, còn Next.js thì lại càng làm tăng tốc danh tiếng xấu đó. Tốt nhất là tránh xa

  • Vercel chắc sẽ sửa bug lần này, nhưng giờ những vấn đề vặt vãnh kiểu này tích lại khiến tôi mệt mỏi với Next.js. Ví dụ, cách nhận diện prefetch trong middleware đã bị hỏng suốt vài tuần, thậm chí vài tháng. Những lỗi nhỏ kiểu này cứ dồn lại nên tôi rất ngán Next.js. Nhưng bản thân hệ sinh thái JS thì tôi vẫn rất yêu thích

    • Tôi đã rời Next.js để sang Astro. Tôi muốn quay về những thứ cơ bản, nhưng lại ngại tự cấu hình route/template/static asset/build. Astro lo hết mấy phần đó và mặc định là SSR. Cảm giác như dùng React/Vue đúng với mục đích ban đầu: phủ lên như một lớp tương tác. Nhờ vậy tôi mới nhận ra JS framework thực ra không cần thiết đến mức nào. Next ngày càng có nhiều yếu tố "ma thuật", server action thì gượng gạo, và có quá nhiều cách làm kiểu "chuẩn NextJS"

    • Hiện tôi vẫn dùng Next.js cho công việc và dự án cá nhân, nhưng nó từng là một công cụ vui vẻ và hiệu quả, còn từ sau khi chuyển từ pages sang app router thì hướng đi trở nên đáng tiếc

    • Từ phiên bản 15.1.8, một số thư viện1 bị hỏng, khiến phải hạ xuống đúng phiên bản dễ bị tổn thương mà tác giả đã nhắc tới

    • Đồng ý. Về sau tôi chỉ định dùng Next.js cho site tĩnh hoặc SPA build sẵn

  • Next giờ gần như thành trò cười. Sau khi Remix biến thành react-router theo cách khó mà hiểu nổi, cảm giác số framework React ổn áp giờ cực kỳ hiếm. Cuối cùng tôi lại quay về tổ hợp vite thuần và tanstack router

    • Tôi khá ngạc nhiên là những bài viết chỉ trích như thế này vẫn còn tồn tại trên Hacker News. Trước đây khi tôi đăng bài nói rằng một thứ có thể được làm đơn giản hơn bằng Remix, đã có nhiều nhân viên Vercel nhắn tin cho tôi bảo gỡ xuống hoặc xin họp. Họ còn liên hệ đồng thời qua nhiều tài khoản mạng xã hội khác nhau

    • Không rõ ý bạn là sau khi đổi thương hiệu thì bạn không còn dùng Remix nữa, hay là bạn cho rằng nó không còn là framework. RR7 (React Router 7) vẫn hoạt động bình thường như một framework1. Tôi làm backend 15 năm rồi mới chuyển sang full-stack gần đây, được một người bạn rất giỏi giới thiệu RR7 và dùng xong ngày nào cũng thấy ấn tượng

    • Tôi thử TanStack Router cho một dự án mới và thấy thích quá nên thêm cả TanStack Query lẫn TanStack Form

    • Tôi tò mò lựa chọn thay thế nào là tốt nhất, và vì sao lại dùng Vite. Tôi dùng Next cho các dự án nhỏ vì nghe nói điểm mạnh lớn nhất là SEO. Chỉ cần tạo file tĩnh rồi upload lên S3 là xong, chẳng phải như vậy là đủ sao?

    • Tôi muốn biết cụ thể việc Remix biến thành react-router thì có gì là vấn đề. Theo tôi thấy thì chỉ là đổi thương hiệu thôi mà

  • Tôi đã nhấn mạnh suốt nhiều năm rằng những thứ như React, Next, Svelte do các công ty kiểu Vercel dẫn dắt thì cần tiếp cận cẩn trọng hơn nhiều. Mục tiêu của họ giống Heroku, nhưng còn hung hăng hơn nhiều trong việc dẫn đến lock-in toàn bộ stack, từ ngôn ngữ-runtime-máy. Các công ty khác cũng có vấn đề. Ví dụ, công cụ deploy CLI của Cloudflare chỉ hỗ trợ macOS 13.5+ (mới hơn 2 năm một chút), không rõ vì sao. Thật buồn khi một hệ điều hành ra mắt 2 năm trước đã bị xem là cũ. Có thể vẫn dùng wrangler bản cũ, nhưng tài liệu và tính năng lại không khớp, và kiểu gì tình hình cũng sẽ tệ hơn. Rồi sẽ đến lúc tính tương thích cũng bị cắt. Trong khi đó, các công cụ khác như vim, neovim, emacs... vẫn chạy được trên OS X rất cũ. Tôi nghĩ đó là vì các công cụ mở này không có động cơ lock-in

  • Next và RSC là thứ bức bối nhất tôi từng đụng trong frontend. Frontend vốn đã đủ đau đầu rồi, giờ còn thêm "ma thuật" của Next và vendor lock-in của Vercel. Tuần này nhóm tôi sẽ chuyển sang tanstack router và vite để thử làm một CSA bình thường, khá háo hức

    • Tôi tò mò không biết RSC có gì mà bức bối đến vậy. Theo trải nghiệm của tôi thì nó hoạt động rất tốt, và lý do duy nhất tôi vẫn dùng Next.js cũng chính là vì RSC
  • Mọi người cần nói nhiều hơn về chuyện trong chế độ phát triển của Next.js, việc compile route mất tới 10 giây. Trông Rust compiler còn như đang đứng hút thuốc ở góc phòng

    • Gần như không dùng nổi. Đây là devx tệ nhất tôi từng trải qua. Lần cuối tôi ghét một stack đến vậy là khi phải hỗ trợ một site Sharepoint

    • Giờ ngay cả JS, vốn chỉ là ngôn ngữ script đơn giản, cũng phải qua build/compile nhiều lớp, mà còn mất thời gian hơn cả compiler C++. Đến mức nhét cả Clang vào trình duyệt có khi còn cho trải nghiệm tốt hơn. Nhân tiện, công ty tôi cũng dùng PHP và ở đó cũng gặp vấn đề tương tự. Cứ tưởng là ngôn ngữ script thì sẽ đơn giản, nhưng vì giới hạn hiệu năng của bản thân PHP nên phải thêm bước sinh mã trước và bước build composer riêng. Mà cái hệ build do lập trình viên PHP làm ra này cũng chậm nốt. Chắc vì không phải do những người làm GCC tạo ra

    • Kỳ lạ là ngay cả tùy chọn next dev —-turbo cũng không nhanh hơn trên codebase của công ty tôi

    • Rust compiler thì đúng là đang làm việc compile thật, còn compiler của Next.js có thực sự làm thứ gì phức tạp đến mức đó không thì tôi nghi ngờ

  • Thật đáng buồn với tình trạng hiện tại của Next.js. Tôi vẫn dùng nó, nhưng đến mức phải tự fork rồi vá để dùng. next.config.js là một lối thoát gian nan để thay đổi hành vi mặc định, mà theo tôi đáng ra các tùy chọn như vậy phải được cung cấp như điểm mở rộng ngay từ đầu, chứ không nên giấu sau "feature flag". Giờ nó gần như là một framework điểm D với code spaghetti hoàn toàn

  • Nếu không phải NextJS thì mọi người khuyên tổ hợp full-stack nào? Tôi là backend dev 15 năm kinh nghiệm, nhưng frontend thì đây là lần đầu kể từ AngularJS. Gần đây tôi muốn làm một app full-stack cho dự án cá nhân, tìm kiếm một vòng thì cả Gemini lẫn tài liệu chính thức đều khuyên NextJS. Tôi vẫn còn ở giai đoạn đầu nên muốn học phương án thay thế. Mọi thứ tôi sẽ tự vận hành trên VPS bằng Docker nên tránh Vercel/Netlify

    • Nếu không cần server rendering thì tôi khuyên dùng React không framework kết hợp với Vite1. Khi phát triển thì chạy bằng Vite, còn build production chỉ ra HTML + JS rồi đưa lên hosting tĩnh như S3 là xong. Tôi đã dùng hơn 10 năm và không có vấn đề gì. Backend thì dùng thứ bạn thấy thuận tay, còn dạo này tôi chủ yếu dùng PostgREST2. Phía client gọi API thì tôi khuyên dùng react-query3

    • Tôi tò mò bạn đang phát triển loại dự án gì. Tôi đang làm một webapp SaaS điển hình, và tổ hợp React/Refine.dev/Vite dùng rất ổn. Nhờ Refine.dev mà có thể tập trung phát triển tính năng thay vì phải bận tâm về các trang CRUD

  • Tôi nghĩ vụ việc lần này đang bị làm quá. Với ai hiểu cách streaming hoạt động trong React thì chuyện không thể stream HTML từng dòng là điều quá hiển nhiên. Không nên chặn first paint vì metadata, mà là first paint của HTML chứ không phải JS. Việc xử lý ngoại lệ cho một số user agent trong hành vi này là hợp lý. Với phần lớn traffic thì điều quan trọng là hiển thị nhanh nhất có thể. Nếu có những người dùng mà việc tải metadata mất quá lâu, tôi tò mò không biết nên giải quyết thế nào