Tôi đã xây dựng ứng dụng với Next.js trong nhiều tháng qua. Hệ thống định tuyến tích hợp sẵn, hỗ trợ SEO và nhiều lợi ích khác khiến nó trở thành sự lựa chọn dễ dàng thay vì React thuần khi xây dựng các ứng dụng web full-stack. Nhưng có một điều luôn khiến tôi cảm thấy bực bội:
Tốc độ phát triển thực sự rất chậm
Next.js có tính năng Hot Reload giúp cập nhật nhanh từ mã sang trình duyệt, nhưng thực tế thì mỗi lần thay đổi nhỏ trong mã lại cảm giác như đang chờ biên dịch lại toàn bộ. Tôi gặp phải hiện tượng trình duyệt bị đơ, terminal bị lag – ngay cả khi chỉ đang làm việc với một trang landing page đơn giản. Điều này khiến tôi nghi ngờ liệu đây có thực sự là "React tăng lực" mà mọi người vẫn hay nói không?
Tôi đã từng làm việc với dự án Vite + React, và nhớ rằng tốc độ phát triển chưa bao giờ chậm đến mức như vậy, bất kể độ phức tạp của dự án. Vì vậy, tôi quyết định tạo một dự án đơn giản với Vite + React và một dự án Next.js để so sánh tốc độ. Chỉ trong vài phút, tôi nhận ra rằng app Vite + React NHANH HƠN RẤT NHIỀU — và thực sự là một trời một vực. Không có hiện tượng reload trang, không có độ trễ khi biên dịch — phản hồi gần như tức thì.
Và câu hỏi đặt ra là:
Nếu Vite mang lại trải nghiệm phát triển tốt như vậy, tại sao Next.js vẫn còn quá chậm?
Thực tế khi phát triển với Next.js
Khi nhìn vào các chiến dịch marketing, Next.js dường như là một giải pháp tuyệt vời cho các lập trình viên React (và thực sự là như vậy). Nó cung cấp:
- Định tuyến tích hợp
- Kết xuất phía server (SSR)
- Các route API
- Tối ưu hóa SEO
- Khả năng full-stack
Nhưng có một điểm trừ: Next.js đôi khi khiến bạn cảm thấy như nó đang chống lại mình khi phát triển.
Mỗi lần bạn lưu một file, terminal sẽ bắt đầu nhiều tiến trình biên dịch lại. Trình duyệt thì reload chậm, và nếu bạn làm việc với ứng dụng lớn, nhiều route động, mọi thứ càng tệ hơn. Việc chuyển trang tốn thời gian, và không phải do máy bạn yếu đâu (ban đầu tôi cũng nghĩ vậy). Vậy thì...
Tại sao Next.js lại chậm?
Sau một chút tìm hiểu, tôi nhận ra vấn đề không nằm ở tôi, mà nằm ở cách framework này được xây dựng. Dưới đây là những gì tôi phát hiện:
1. Next.js biên dịch mọi thứ — cả Client và Server
Là một framework full-stack, Next.js không chỉ biên dịch frontend như Vite, mà còn cả backend. Vì vậy, mỗi lần bạn nhấn “Save”, trình biên dịch phải xác định:
“Thay đổi này ảnh hưởng đến client? server? hay cả hai?”
...và sau đó biên dịch tương ứng. Do đó, chỉ một dòng thay đổi nhỏ cũng có thể kích hoạt chuỗi biên dịch mất vài giây thay vì mili giây.
2. Hot Reload ≠ Hot Module Replacement
Next.js sử dụng React Fast Refresh — giúp giữ trạng thái component giữa các lần chỉnh sửa. Nhưng trong thực tế, đặc biệt là với ứng dụng lớn, Fast Refresh lại chậm, không ổn định và đôi khi còn reload toàn bộ trang.
Trong khi đó, Vite sử dụng ESM gốc và Hot Module Replacement (HMR), chỉ thay module đã thay đổi mà không cần xử lý dư thừa. Nhẹ hơn rất nhiều.
3. Vẫn dùng Webpack (trừ khi bạn chuyển sang Turbopack)
Mặc định, Next.js vẫn dùng Webpack ở chế độ phát triển — và ai cũng biết Webpack không nổi tiếng vì tốc độ. Nó ra đời trước khi ESM phổ biến, và thường biên dịch quá mức.
Còn Vite thì dùng esbuild (viết bằng Go) và rollup cho production. Vite có thể khởi động server dev dưới 300–500 ms, trong khi Next.js có thể mất 10–20 giây với một dự án cỡ vừa.
4. Theo dõi file quá nhiều
Next.js theo dõi rất nhiều file — từ component, page, layout, đến các file cấu hình tùy chỉnh. Nếu bạn có hàng trăm route/component, việc theo dõi file sẽ ngốn CPU và làm mọi thứ chậm hơn.
5. Cấu hình máy vẫn là một yếu tố
Nếu bạn chạy cả server-side và client-side code cục bộ (với Next.js là như vậy), thì máy bạn phải xử lý gấp đôi. Nếu không dùng máy cấu hình tầm trung hoặc cao, trải nghiệm phát triển sẽ rất mệt mỏi.
Cách cải thiện trải nghiệm phát triển
Công bằng mà nói, Next.js là một framework full-stack nên làm rất nhiều việc đằng sau. Nhưng bạn có thể áp dụng vài mẹo sau để cải thiện tốc độ:
1. Dùng Turbopack với next dev --turbo
Vercel đang phát triển Turbopack — trình thay thế Webpack viết bằng Rust. Tuy còn sớm, nhưng nó cho thời gian refresh nhanh hơn — nhất là với app nhỏ.
Bạn có thể thay script trong package.json
như sau:
"scripts": { "dev": "next dev --turbopack", }
2. Giữ page và component nhỏ gọn
File lớn = thời gian biên dịch lớn. Tách nhỏ component và page sẽ giúp giảm phạm vi bị ảnh hưởng khi biên dịch lại.
3. Lazy-load các route hoặc component nặng
Đừng import các component nặng một cách tĩnh. Dùng dynamic()
để tải khi cần:
import dynamic from 'next/dynamic' const HeavyComponent = dynamic(() => import('../components/HeavyComponent'))
4. Tách backend riêng
Nếu bạn dùng API route của Next.js (/api
), điều đó có thể làm chậm hệ thống. Thay vào đó, tách backend riêng dùng Firebase, Supabase hoặc Express sẽ giúp nhẹ hơn khi phát triển.
Kết luận
Vậy có nên bỏ Next.js không? Còn tùy.
Tôi từng rất bực mình, nhưng sau cùng tôi nhận ra:
Khi nào nên dùng Next.js:
- Bạn xây dựng app full-stack có xử lý phía server
- Bạn cần tối ưu SEO hoặc static site
- Cần tối ưu ảnh, SSR, hoặc edge function cho production
Khi nào nên dùng Vite:
- App thiên về frontend hoặc công cụ thiết kế
- Bạn cần phản hồi tức thì khi phát triển
- Bạn đang làm prototype, cần tốc độ hơn cấu trúc
👉 Về trải nghiệm phát triển (nhất là tốc độ), hiện tại Vite tốt hơn rõ rệt.
Còn bạn thì sao? Bạn có gặp vấn đề tốc độ khi dùng Next.js không? Turbopack có giúp gì không, hay bạn đã chuyển hẳn sang Vite?
Hãy để lại comment phía bên dưới nhé!