12 điểm bởi GN⁺ 2025-09-03 | 7 bình luận | Chia sẻ qua WhatsApp
  • Middleware của Next.js bị hạn chế về cấu hình logging, và logging mặc định chỉ được bật trong môi trường phát triển nên khó theo dõi sự cố trong môi trường production
  • Trong middleware chỉ có thể truyền header, và không thể chain nhiều middleware nên việc triển khai logging phức tạp bị hạn chế
  • Logging dùng AsyncLocalStorage có hành vi không như mong đợi trong runtime Edge, và việc chia sẻ context giữa page và middleware không hoạt động đúng cách
  • Ngay cả khi dùng custom server cũng khó giải quyết vấn đề logging, và các ràng buộc thiết kế của Next.js ép lập trình viên vào một cách làm nhất định
  • SvelteKit của Vercel cung cấp middleware linh hoạt và cơ chế truyền dữ liệu tốt hơn, cho thấy thiết kế thân thiện với lập trình viên hơn Next.js

Bối cảnh của vấn đề logging trong Next.js

  • Khi vận hành một dịch vụ Next.js và thử triển khai ghi log production, tác giả nhận ra tính năng log mặc định chỉ được kích hoạt trong môi trường phát triển
  • Trong bối cảnh cần một hệ thống logging phù hợp với môi trường vận hành, tác giả đã đụng phải các giới hạn của Next.js

Giới hạn của middleware

  • Theo tài liệu chính thức, middleware được chạy trước routing và phù hợp để triển khai các chức năng như xác thực, logging, redirect
  • Nhưng trên thực tế, tham số có thể truyền vào middleware bị giới hạn ở 4, và về cơ bản chỉ có header là thứ có thể truyền đi hữu dụng
  • Cấu trúc chain hoặc kết hợp nhiều middleware không được hỗ trợ
  • Trong Node.js đã có những thông lệ middleware được thiết lập vững chắc qua Express và các framework khác, nhưng trong Next.js thì không thể áp dụng đúng nghĩa

Thử lách bằng AsyncLocalStorage

  • Tác giả thử dùng pino và AsyncLocalStorage để quản lý instance logging ở cấp middleware
  • Có thể lưu log với context riêng cho từng request trong middleware, nhưng lại phát hiện hiện tượng chỉ hoạt động bình thường trong môi trường trình duyệt
  • Nguyên nhân là middleware của Next.js mặc định dùng runtime edge, và ngay cả khi cấu hình sang runtime nodejs thì vẫn có thể không ổn định tùy tình huống dự án

Sự cố ở component trang

  • Khi thực sự gọi hàm logging trong page hoặc layout component, logger() trả về null
  • Có một vấn đề cấu trúc là context logger được tạo trong middleware không được truyền sang ngữ cảnh render bất đồng bộ
  • Cách giải quyết gần như duy nhất là nhét thông tin logging như requestId vào header để truyền đi, khiến code phức tạp hơn và cấu trúc import cũng trở nên rối rắm
  • Ở client component cũng cần thêm sự tách biệt cấu trúc tương tự

Thử đưa vào custom server

  • Tác giả làm thử theo ví dụ custom server trong tài liệu chính thức, tận dụng http.createServerapp.getRequestHandler của next.js
  • Trong môi trường này, tác giả lại muốn dùng AsyncLocalStorage, nhưng hiện tượng không thể liên kết context giữa middleware – page – custom server tiếp tục lặp lại
  • Về bản chất, Next.js chỉ dùng AsyncLocalStorage đúng cách bên trong nội bộ của nó, còn lập trình viên thì không được cung cấp cùng mức quyền đó
  • Trên thực tế, cách truyền từ middleware sang page gần như chỉ còn thay đổi response header và điều hướng bằng redirect/rewrite
  • Từ góc nhìn người dùng, việc mở rộng linh hoạt hay truyền custom context là cực kỳ khó

So sánh với SvelteKit

  • SvelteKit của Vercel cung cấp hệ thống middleware linh hoạt hơn Next.js
    • Có thể tự do truyền dữ liệu request qua đối tượng event.locals
    • Có thể định nghĩa nhiều hàm handle để chain, nên dễ triển khai logic phức tạp
  • SvelteKit cho thấy một thiết kế thân thiện với lập trình viên, đối lập với các ràng buộc của Next.js
    • Dù cũng là sản phẩm của Vercel, SvelteKit vẫn mang lại trải nghiệm tốt hơn Next.js dù bị xem là dự án thứ yếu

Phê phán issue tracker và văn hóa hệ sinh thái

  • GitHub issue tracker chính thức của Next.js gần như không phản hồi feedback từ người dùng
  • Ngay cả những issue hay bug nổi bật cũng thường bị bỏ mặc rất lâu mà không có câu trả lời hay cách xử lý
  • Ngay cả khi chuẩn bị mã tái hiện tối giản để mở issue, vẫn không có phản hồi thực chất hay hành động tiếp theo

Kết luận và suy ngẫm

  • Các bug và giới hạn cấu trúc được phát hiện trong Next.js liên tục làm tổn hại năng suất của lập trình viên, và dường như cần có cải thiện tận gốc
  • So với các framework khác như SvelteKit, Next.js dù là sản phẩm chủ lực vẫn thua về tính dễ dùng
  • Hiện tại chưa dễ có kế hoạch thay thế Next.js ngay, nhưng với các dự án tương lai, tác giả bắt đầu muốn cân nhắc những lựa chọn khác

7 bình luận

 
bichi 2025-09-03

Có vẻ họ vẫn chưa nghĩ tới việc React làm giảm năng suất.

 
ahwjdekf 2025-09-03

Lần này tôi đã thử làm web chỉ vì hứng thú cá nhân, một lĩnh vực hoàn toàn không liên quan đến mảng tôi vốn phát triển. Tôi làm một bảng tin bằng next.js v15 app router, nhưng mỗi khi đọc những bài như thế này thì cảm giác như động lực muốn thử cái mới ở phía web lại mất đi. Sao hệ sinh thái lại bất ổn đến vậy nhỉ. Rồi lỡ lại có thứ mới xuất hiện thì mọi người lại ào ào chạy theo, dùng một thời gian, vừa chê vừa đi tìm thứ khác sao. Mảng phát triển web đúng là chắc khó thật.

 
preserde 2025-09-04

Đặc thù của ngành là thay đổi nhanh vừa là ưu điểm nhưng cũng là nhược điểm haha. Nhưng vấn đề trong bài về cơ bản là do Vercel khuấy rối. Nếu làm frontend thì cần đặc biệt lưu ý Vercel hu hu

 
joyfui 2025-09-03

Có lẽ vì tôi bắt đầu sự nghiệp với web nên web (đặc biệt là frontend) vốn dĩ được phát triển theo cái kiểu đó ấy haha
Cái kiểu thay đổi xoành xoạch...

 
regentag 2025-09-03

Phía JS hơi mang cảm giác như vậy. Có cả một đống thứ được nói là tốt, nhưng mỗi cái lại đều có chút vấn đề, rồi xu hướng thì thay đổi rất nhanh theo mốt...
Có thể là vì trước đây tôi chủ yếu làm với Java, EJB và Struts nên mới cảm thấy như vậy.

 
GN⁺ 2025-09-03
Ý kiến trên Hacker News
  • Tôi đồng ý 100%, tôi cũng đã gặp đúng những vấn đề đó và sẽ không bao giờ dùng Next.js nữa, đồng thời dự định khuyên mọi team trong công ty dùng giải pháp khác.
    Next.js có một lớp trừu tượng khổng lồ mà 99.9999% dự án không cần tới; với số ít trường hợp thực sự cần kiểu này, tôi nghĩ thà tự làm một giải pháp tùy biến từ các thành phần cấp thấp còn tốt hơn.
    Trong tất cả công nghệ tôi từng dùng, Next.js tệ nhất không cần bàn cãi.

    • Thật mừng vì không chỉ mình tôi nghĩ vậy.
      Tôi đã làm một ứng dụng production có doanh thu, độ phức tạp tầm trung bằng Next.js; ban đầu dùng Vercel và Google Firebase, sau đó chuyển sang tự host và thay bằng Pocketbase.
      Pocketbase là trải nghiệm ổn duy nhất, còn lại thì thực sự khủng khiếp.
      Độ phức tạp vô tận, breaking change liên tục, tài liệu khó tiếp cận, không có gì là dễ cả.
      Tôi tin chắc rằng nếu frontend 5 năm qua bớt chạy theo trào lưu và tập trung dạy cho tốt những công nghệ đã tồn tại lúc đó, thì giờ mọi thứ đã tốt hơn nhiều.
      Tôi cũng từng làm vài frontend React khá phức tạp; tôi vốn đã không thích React lắm, nhưng Next.js còn tệ hơn.
      Tôi cũng từng làm CMS bằng Go và vanilla JS; DX có thể kém hơn một chút, nhưng ít nhất tôi có cảm giác mình thực sự biết chuyện gì đang diễn ra.
      Tôi không hiểu tại sao với React và Next.js, sau 6 năm rồi mà lúc nào cũng phải đoán xem chuyện gì sẽ xảy ra.
      Tôi đã tích lũy được kinh nghiệm để gỡ rối mớ hỗn độn của framework, nhưng tổng thể vẫn có cảm giác quá bẩn và thiết kế tệ.
      Với Go thì ngoài 6 tháng đầu tiên ra, gần như không có gì làm tôi bất ngờ, và những codebase cũ vẫn rất vững vàng.
      Thật tiếc là phía frontend không tạo ra được trải nghiệm như vậy.

    • Theo kinh nghiệm của tôi, những phần thô ráp của Next.js không phải bug mà là feature.
      Mọi thứ cho cảm giác như được thiết kế để khiến người dùng bỏ cuộc và bị trói vào hosting của Vercel.

    • Tôi nghĩ mọi thứ rồi sẽ còn tệ hơn.
      Ngay cả các khóa học online kiểu PluralSight hiện giờ cũng chỉ đẩy Next.js trong các khóa về React.
      Tôi không biết vì sao lại thành ra như thế này, nhưng chúng ta đã tới đây rồi.

    • Với tôi thì Sharepoint để lại ký ức bẩn hơn, nên Next.js đứng thứ nhì trong danh sách tệ nhất.

    • Điều khiến tôi bực nhất ở Next.js là nó giả vờ như một full-stack framework kiểu Rails, Wordpress hay Meteor, tức là cung cấp đủ mọi thứ, nhưng trên thực tế lại chỉ có ý kiến về những phần nhàm chán và hạn hẹp nhất như middleware, image resizing, SSR..., còn những quyết định thực sự có giá trị như database, ORM, giao thức truyền thông thì đẩy hết cho người dùng.
      Thực tế nó khá khác với Rails/Wordpress/Meteor, và đáng ra framework phải định hình hạ tầng, nhưng ở đây lại thành ra hạ tầng chi phối framework.
      Trên dashboard của tôi, "Fluid Active CPU" và "ISR Writes" là những mục tiêu tốn hàng đầu, và tôi chỉ biết trả $20 rồi cầu mong đừng vượt quá 100%.
      Tên các hạng mục thì đầy những thuật ngữ nghe như Star Trek, và vì có vẻ sang major version sau lại đổi nữa nên tôi cũng chẳng muốn học làm gì.
      Khá nhiều người quen của tôi từng phát cuồng vì Zeit rồi cuối cùng cũng chuyển dự án và khách hàng sang nơi khác.
      Nếu Vercel hỏi tôi ở major release tới nên đổi gì, thì tôi chỉ có thể nói: "Mọi quyết định kể từ App Router trở đi đều sai."
      Tôi không biết cứu vãn chuyện này kiểu gì nữa.

  • Tôi nghĩ nhiều vấn đề của Next.js bắt nguồn từ chuyện người ta không thực sự biết code đang chạy ở đâu.
    Browser, middleware, edge và node, SSR... tất cả bị trộn vào nhau tạo ra độ phức tạp khổng lồ.
    Những trường hợp kiểu này chỉ hợp khi:

    • bạn vận hành dịch vụ B2C toàn cầu và muốn giảm độ trễ bằng ngữ nghĩa edge

    • bạn sẵn sàng trả cho gói hosting đắt đỏ của Vercel

    • bạn chỉ cần kiến trúc không quá phức tạp, không cần background job
      Ngoài ra thì react-vite SPA hoặc SSR truyền thống như Rails dễ chịu hơn nhiều.

    • Tôi còn không đồng ý với cả các điều kiện trên.
      Ngay cả khi Next.js có vẻ phù hợp, sự suy giảm về năng suất và khả năng bảo trì cũng chẳng đáng đổi lấy nó chút nào.
      Tôi đang dùng Lustre của Gleam và không có ý định quay lại.
      Bài keynote của nhà sáng lập Elm cũng là một ví dụ đi ngược lại Next.js theo tôi nghĩ.
      https://www.youtube.com/watch?v=sl1UQXgtepE

    • Tôi xem Vercel là ung thư của web hiện đại.
      Họ len lỏi vào mọi hệ sinh thái framework, lạm dụng chúng để bán gói trả phí, trong khi chỉ giả vờ như đang vì mã nguồn mở, vì cạnh tranh và vì sự phát triển của web.

    • Ngay cả với trường hợp đầu tiên, tôi cũng khó tin rằng dùng Vercel và SSR sẽ giải quyết được nút thắt hiệu năng.
      Phần lớn suy giảm hiệu năng đến từ những thứ cơ bản như bundle quá lớn, quá nhiều API call chậm, v.v.
      Làm profiling, tối ưu hóa, đơn giản hóa từ những thứ nền tảng trước sẽ hiệu quả hơn chuyện làm kiến trúc phức tạp lên rất nhiều.

    • Tôi đồng cảm với ý "không biết code chạy ở đâu".
      Ngày trước tôi từng nghĩ cái kiểu JavaScript làm được mọi thứ là ưu điểm, nhưng giờ lại thấy đó mới là vấn đề.
      Công ty tôi dùng Inertia.js + Vue, tổng thể cấu hình đơn giản hơn nhiều, vẫn có sức mạnh render frontend nhưng routing thì 100% xử lý phía server và không cần API riêng.
      Bạn cũng có thể dùng Inertia với React hoặc Svelte.
      Ban đầu chúng tôi dùng Nuxt, nhưng nó phức tạp tới mức phải vận hành đồng thời cả backend server lẫn frontend server, và rất khó biết code đang chạy ở đâu.
      Giờ thì chỉ cần phân biệt PHP là server, JS là browser nên khỏi phải suy nghĩ gì nữa.
      Đó là lợi thế cực lớn với chúng tôi.

    • Tôi nghĩ đây là phần tóm lược rất đúng trọng tâm.
      Vercel đang theo đuổi tối ưu hiệu năng bằng React Server Components, Partial Pre-rendering, Edge server, streaming, v.v.
      Những quyết định thiết kế và API kỳ lạ đều bắt nguồn từ đó.
      Trong trường hợp cần thiết thì những thứ này có thể hữu ích, nhưng chỉ cần tận dụng SSR hợp lý ở một phần edge function thôi cũng đã cải thiện đáng kể rồi.

  • Cảm ơn vì đã để lại phản hồi.
    Chúng tôi nhận thức được các vấn đề DX trong Middleware, và ở phiên bản 15.5 đã có một bước tiến lớn là hỗ trợ Node runtime[1].
    Nếu được làm lại, có lẽ chúng tôi đã đổi tên nó thành Routing Middleware hoặc Routing Handler, để thể hiện rõ hơn rằng đây là một escape hatch nâng cao ở giai đoạn routing, có thể được chuyển tới CDN edge.
    Nếu bạn cần log, có thể dùng OpenTelemetry và xử lý theo thông lệ instrumentation.ts[2].
    [1] https://nextjs.org/blog/next-15-5#nodejs-middleware-stable
    [2] https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation

    • Cảm ơn vì phản hồi.
      Nhưng khi bạn nhắc tới instrumentation và observability thì lại giống như đang giải bài toán log đơn giản bằng thêm một tầng phức tạp khác.
      Không phải ứng dụng nào cũng cần OpenTelemetry.
      Tôi không hiểu vì sao một cách bình thường như logger().info() lại không dùng được.
      Ngôn ngữ và framework khác đều có, vậy sao chuyện này ở đây lại khó đến thế.

    • Không khí ở đây khá tiêu cực nên tôi muốn nói trước: Next.js là phần mềm rất tốt nếu dùng đúng mục đích thực tế của nó.
      Tôi nghĩ họ đã làm rất tốt một phần mềm chống lưng cho hàng triệu website.
      Vấn đề nằm ở chỗ thiếu reference và tài liệu chi tiết; tài liệu có nói cái gì tồn tại, nhưng lại không chỉ rõ cách dùng thực tế, thời điểm nó chạy, các bẫy thường gặp, v.v.
      Nó thân thiện với người mới nhưng lại thiếu hướng dẫn về runtime context phức tạp và derived complexity.
      Đây là xu hướng tôi thấy ở khá nhiều dự án dạo này.
      Cân bằng giữa sự thân thiện với người dùng và giải thích chi tiết là chuyện cực khó.
      Tôi hy vọng họ sẽ tiếp tục cải thiện.

    • Nói ngắn gọn thêm một câu thôi.
      Tác giả bài viết này chỉ là không nhận ra sự khác nhau giữa các domain và cố gọi hàm giống nhau ở mọi nơi.
      Lỗi của Next.js là cố gượng ép hợp nhất những domain vốn có bản chất khác nhau.
      Nếu cứ trộn edge, SSR, Node và client theo kiểu đó thì độ phức tạp chỉ tăng lên.
      Tài liệu cũng không giải quyết được, mà ngược lại còn làm rối thêm.

    • Tôi từng được khuyên dùng cách instrumentation trong một comment trên Reddit.
      Nếu tôi setup opentelemetry cho Next vào đúng khoảng thời gian tương tự, dù tài liệu có khác đi thì chắc sau trải nghiệm đó tôi vẫn sẽ viết một bài blog.
      Không hẳn là lỗi của các bạn, nhưng gần như mọi package opentelemetry đều gắn nhãn experimental, nên khi đưa vào production rất khó tạo cảm giác tin tưởng.
      Việc setup pino instrumentation cũng rất vất vả.
      Phải thêm pino vào serverExternalPackages thì nó mới chạy đúng.
      Auto-instrumentation cũng cực kỳ nhạy với thứ tự import, và chỉ instrument được default export của pino.
      Biến cục bộ ở mức module cũng không hoạt động như mong đợi nên tôi phải dùng globalThis.
      Mà cuối cùng tôi còn dính cả https://github.com/vercel/next.js/issues/80445.
      Kết luận là cuối cùng nó vẫn hoạt động, nhưng setup thực sự rất khó chịu.
      Trải nghiệm như vậy là vì tôi dùng manual router (= không dùng vercel/otel).

    • Nếu đã quyết định hỗ trợ server-side middleware, tôi không hiểu vì sao đến giờ vẫn chưa hỗ trợ middleware chain, tức nối nhiều hàm lại với nhau, mà chỉ cho một cái duy nhất.
      Đây là tính năng mà framework server khác nào cũng có.

  • Tôi nghi ngờ câu "không thể chain nhiều middleware" có thật không.
    https://nextjs.org/docs/messages/nested-middleware
    Nếu có nhiều cái thì phải gộp vào một file rồi chạy, nghe thật khó tin.

    • Nếu tôi đọc không nhầm, vậy là Next.js đang bảo đừng cấu trúc thành nhiều file mà hãy nhét hết vào một file à?
      Là vì vấn đề scoping nên không dùng nhiều file được sao? Với tư cách framework thì đây là yêu cầu quá vô lý.

    • Tôi không thể bỏ qua nghi ngờ rằng phần lớn những quyết định ngớ ngẩn như vậy được đưa ra không phải vì lợi ích của framework, mà vì nó có lợi hơn cho phía Vercel.

  • Ngay khi nhìn Next.js lần đầu tôi đã nghĩ ngay tới Meteor.js.
    Tôi từng đầu tư kha khá để học nó cho dự án cá nhân, nhưng vì trừu tượng hóa quá mức và quá cứng nhắc nên rất khó vượt quá mức prototype.
    Những giải pháp kiểu "kèm sẵn mọi thứ" như vậy cứ liên tục xuất hiện, vì setup của chúng tiện.
    Gần đây trên Hacker News cũng có thảo luận so sánh Laravel với Symphony, trong đó có ý rằng càng phức tạp thì càng dễ vỡ.
    So với kiểu tự lắp ghép từng phần như NodeJS/React SPA trước đây, mỗi mảnh đều là một trừu tượng cấp thấp độc lập nên linh hoạt hơn và cũng dễ thay từng phần hơn.
    Nó cũng có nhược điểm, nhưng vẫn mượt mà hơn overengineering, tức cái kiểu chất chồng độ phức tạp.
    Tôi hoàn toàn hiểu vì sao kiểu "kèm sẵn mọi thứ" lại phổ biến.
    Việc ghép đủ thứ tool và library lại cho tương thích thực sự rất phiền.
    Kiểu tiếp cận lắp ghép này thường chỉ chạy tốt khi có người đủ kinh nghiệm đứng ra setup.

    • Tôi quen với asp.net, và dù trong cộng đồng dev startup nó bị chê khá nhiều, thực tế đây là một framework được thiết kế rất tốt.
      Nó đúng là kiểu "kèm sẵn mọi thứ", nhưng tôi luôn có thể thoát khỏi framework và override bất cứ lúc nào, chưa bao giờ có cảm giác phải đánh nhau với framework.
      Blazor Server và Blazor Webasm đều cho phép dùng C# ở frontend, và cả hai đều phù hợp với các panel nội bộ hoặc ứng dụng SaaS theo cách riêng.
      Quan trọng hơn cả là SSR truyền thống cũng giải quyết được mọi thứ.
      Nếu ai đang bực mình với web framework thì tôi rất khuyên nên thử.
      Giờ nó cũng hỗ trợ cross-platform tốt, nhanh và dễ học.
      Dù có learning curve, nhưng một khi hiểu cấu trúc module rồi thì tôi có thể override theo ý mình rất nhanh.
      So với framework khác, việc chạm trần giới hạn thực sự là cực kỳ hiếm.

    • Các thành phần lắp ghép kiểu trong NodeJS/React SPA khá xa lạ với Angular.
      Angular không phải library mà là framework, nên phần lớn thứ bạn cần đều đã có sẵn khá đầy đủ.
      (RxJS có learning curve hơi cao một chút, nhưng chỉ cần nắm những phần cơ bản là đã rất mạnh.)
      Thông thường tôi hiếm khi có trải nghiệm phải vật lộn với framework trong các SPA.
      Tài liệu và tutorial của nó, bao gồm cả Tour of Heroes, đều rất xuất sắc.
      https://v17.angular.io/tutorial/tour-of-heroes
      Tài liệu mới nhất có thể xem tại https://angular.dev/

    • Laravel là một ví dụ thành công của trừu tượng hóa bị overengineer.
      Nhờ Laravel mà tôi chưa bao giờ phải hối hận trong production.

    • Hơi lạc đề một chút, nhưng công việc của tôi đúng nghĩa là cứ phải nối các tool và library nhỏ nhỏ không tương thích hoàn toàn với nhau.
      Team tôi nhỏ nên tốn rất nhiều thời gian chỉ để cập nhật và bảo trì, chưa kể rất hay gặp package đã ngừng hỗ trợ từ lâu.

    • Không chỉ là kinh nghiệm, mà thời gian ban đầu để dựng hệ thống và chi phí bảo trì còn lớn hơn nhiều so với mọi người nghĩ.
      Tự làm rồi mới thấy Rails năng suất hơn kiểu ráp từng library bằng Node phải gấp 10 lần.
      Chỉ khi bạn không hợp với nền tảng và triết lý của framework thôi, ví dụ ghét ActiveRecord, thì mới thành vấn đề.
      Câu "càng phức tạp là càng vỡ" thực ra là vì thiếu năng lực kỹ thuật.

  • Tôi là người rất bênh React, và cũng thích việc chuyển từ class component sang hooks.
    Nhưng mỗi lần dùng Next.js là tôi hoàn toàn không biết rốt cuộc mọi thứ bắt đầu sai từ đâu.
    Tôi cũng thích rất nhiều framework và ngôn ngữ lạ, nhưng Next.js là trường hợp duy nhất mà tôi không hiểu nổi một nửa thông báo lỗi của nó.
    Đặc biệt là tôi đã tốn vô số thời gian vì những hydration issue rất kỳ quặc.

    • Tôi không dùng React hay Next.js.
      Cá nhân tôi thích HTML+CSS kèm một ít vanilla JS hơn.
      Tôi từng thấy một landing page Next.js đơn giản bị lỗi trên Firefox.
      Tệ hơn là kiểu fail mà toàn bộ nội dung bị phủ bởi màn hình đen với chữ trắng chỉ hiện đúng câu "An application client side error has occurred".
      Tôi khá sốc vì đến cả landing page đơn giản mà cũng không render nổi; rồi khi biết nguyên nhân là do JS frontend framework thì tôi chỉ nghĩ "à, cũng hợp lý".
      Có thể điều đó chấp nhận được với những người đang cố thuyết phục người dùng, nhưng với người ngoài ngành thì khá khó hiểu.

    • Tôi nghĩ Next tự phá hỏng chính nó rồi.
      Những nơi đi qua chu kỳ VC cuối cùng đều thành như vậy.
      Giờ tôi không dùng nổi nữa, Vite trở thành lựa chọn mặc định.
      Tôi luôn thích các giải pháp nhẹ hơn.

  • Từ "middleware" trong Next.js rất dễ gây hiểu lầm.
    Thực ra nó là một edge function nhẹ chạy trước khi request chạm tới ứng dụng, ví dụ để kiểm tra header, routing, guard đơn giản, v.v.
    Nó chạy trên edge runtime, là môi trường tách biệt với app server.
    Có vẻ tác giả cũng đang nhầm lẫn giữa edge runtime và server runtime.
    Lúc đầu tôi cũng thấy ranh giới này khó hiểu, và vì mọi thứ đều xoay quanh JavaScript nên lại càng dễ mờ đi.
    Tôi nghĩ cần có một mental model rõ ràng.
    Việc trách độ phức tạp của Next.js có cảm giác như đang trách một hộp đồ nghề vì trong đó có nhiều dụng cụ chứ không chỉ mỗi cái búa.

    • Vấn đề là độ phức tạp của Next.js do chính nó tự tạo ra.
      Từ middleware trong gần như mọi framework đã có một nghĩa rất rõ ràng.
      Thông thường middleware là một chain các hàm được gọi trước request trong runtime, với giả định chúng chạy trong cùng một process.
      Next.js lại triển khai nó trên edge và còn chỉ cho một cái duy nhất.
      Trong phần lớn ứng dụng, người ta không cần đến edge; đúng ra phải để opt-in khi cần.
      Nếu dùng ví dụ hộp đồ nghề thì nên chỉ thêm những công cụ thực sự cần đến.
      Next.js không nên dùng từ "middleware" trong bối cảnh như vậy.

    • Đây không chỉ là dùng sai mà còn là lạm dụng thuật ngữ.
      Middleware là khái niệm đã có định nghĩa lâu đời trong ngành web app, nên nếu nó có nghĩa hoàn toàn khác thì lẽ ra không nên dùng từ đó.

    • Tôi đang dùng Next.js app router và khá hài lòng.
      Next.js khiến việc qua lại giữa frontend và backend rất dễ, đến mức có vẻ khiến mọi người hiểu lầm rằng cả phần đó cũng đã được trừu tượng hóa hết.
      Thực ra đây là một hệ thống rất phức tạp, và bạn phải tự gánh lấy độ phức tạp đó.
      Độ phức tạp cao không phải lúc nào cũng đồng nghĩa với chậm hoặc kém năng suất.
      Một hệ thống tách frontend và backend ra thì dễ xử lý hơn nhiều, nhưng cũng phiền hơn tương ứng.
      Biết React rồi vẫn thấy Next.js như phải học lại từ đầu, và có nhiều thứ chỉ khi tự trải qua mới hiểu được.
      Dù vậy, một khi đã quen phần nào thì đây là một hệ thống rất tiện để qua lại giữa frontend và backend.

    • Có khá nhiều người downvote comment của tôi, và tôi muốn họ giải thích lý do.
      Tôi luôn sẵn sàng học hỏi.
      Trong các cuộc thảo luận kiểu này, đừng chỉ phủ định theo cảm tính mà hãy tranh luận cho ra hồn.

    • Cuối cùng cũng thấy một ý kiến có lý.
      Ví dụ, nếu bạn lẫn lộn khái niệm package/module của Python với module của Go mà không suy nghĩ, rồi đi than Go dở, thì cũng tương tự vậy.
      Dùng bất kỳ công nghệ nào cũng cần hiểu biết nền tảng tối thiểu về nó.

  • Từ khi Next.js chuyển sang app router, tôi có cảm giác như họ giao việc cải tiến express API cho những người mới ra bootcamp.
    Mọi server interface như servlet, rack, plug, v.v. đều cho thấy thiết kế kiểu búp bê Nga lồng nhau được tích lũy qua nhiều năm là hợp lý, nên express API ít nhất vẫn là một cách tiếp cận trưởng thành.
    Không chỉ middleware API tệ hại, mà việc loại bỏ request parameter và thay bằng các hàm toàn cục như cookies()/headers() cũng là một quyết định kỳ quặc.
    Có vẻ đằng sau là một số ràng buộc thiết kế nền tảng, nhưng nhìn từ bên ngoài thì giống như họ vứt hết mọi bài học trước đây rồi lặp lại y nguyên các sai lầm cũ.

    • Tôi cho rằng sự ám ảnh với streaming là nguyên nhân lớn nhất tạo ra những ràng buộc này.
      Cộng thêm cả việc phải hỗ trợ edge runtime theo lowest common denominator nữa nên các giới hạn càng nặng hơn.
  • Tôi luôn cố dùng nhiều stack khác nhau cho dự án mới.
    Tôi đã dùng cả frontend lẫn backend với express+react, angular, vue, next, nuxt, go, .net, node, php, v.v.
    Với hầu hết framework tôi đều thấy được ưu nhược điểm và cũng thích thú vì được học cái mới.
    Chỉ riêng Next.js là ngoại lệ: tôi đã làm một ứng dụng khá lớn với nó, và từ đầu đến cuối mọi thứ đều cho cảm giác hoặc là kỳ quặc, hoặc chậm, hoặc bất tiện, hoặc được thiết kế vô lý.
    Tôi vẫn đang phải bảo trì nó, và đây là thứ duy nhất mà tôi thực sự ghét.
    Người ta bảo hệ sinh thái ổn và rất phổ biến, nhưng trải nghiệm thực tế của tôi thì tiêu cực đến mức không thể cứu vãn.
    Nghe lạ thật, nhưng đó là sự thật.

  • Có ai biết địa chỉ bưu điện của Vercel không?
    Issue này sang năm là đến tuổi vào lớp 1 rồi, nên tôi muốn gửi cho công ty một tấm thiệp kiểu "chúc em đi học vui vẻ!"
    https://github.com/vercel/next.js/issues/10084

 
bth15923 2025-09-03

Câu nói trong ý kiến trên Hacker News bên dưới đúng là chuẩn thật.

"Next.js có một tầng trừu tượng khổng lồ không cần thiết đối với 99,9999% dự án; còn với số ít trường hợp thực sự cần thứ như vậy thì tôi nghĩ thà tạo một giải pháp tùy biến bằng các thành phần cấp thấp còn tốt hơn"

API phức tạp quá mức một cách vô ích, vừa thiếu ổn định vừa chưa hoàn thiện nhưng vẫn ngang nhiên quảng bá là production ready, lại còn phụ thuộc cực lớn vào Vercel nên nếu không dùng Vercel thì cũng khó mà vận hành nghiêm túc.