Quay lại
Frontend
5 phút đọc4 tháng 4, 20261

Source maps trong Next.js + Sentry: Đọc stack trace như đọc code của mình

Hết thời nhìn stack trace toàn chunk vô nghĩa. Cách setup source maps cho Next.js với Sentry để debug production như debug local.

N

Nguyen Nhat Long

@longnn

Màn hình Sentry dashboard hiển thị một error với stack trace đã được de-minify: hiện đúng tên file gốc như app/page.tsx, đúng line number, có code context hiển thị đoạn code xung quanh dòng lỗi

Source maps trong Next.js + Sentry: Đọc stack trace như đọc code của mình

Bạn đã bao giờ nhận alert từ Sentry, mở ra và thấy stack trace kiểu static/chunks/12345-abc123.js:1:28374 chưa? Mình thì gặp hoài. Ngồi nhìn cái tên file đó rồi tự hỏi: "Đây là file nào của mình vậy trời?" — cảm giác như đọc một ngôn ngữ ngoài hành tinh vậy.

Vấn đề không phải Sentry hỏng. Vấn đề là bạn chưa cho Sentry thứ nó cần — source maps.

Chuyện gì xảy ra với code của bạn sau khi build?

Khi bạn viết một Next.js app, bạn viết React, TypeScript, JSX — rất dễ đọc, rất human-friendly. Nhưng cái users thực sự download về browser thì khác hoàn toàn.

Next.js build pipeline sẽ:

  • Compile TypeScript/JSX thành JavaScript thuần
  • Minify để giảm dung lượng
  • Code split thành nhiều chunks nhỏ để chỉ load những gì cần thiết

Tất cả những bước này đều tốt cho performance. Nhưng khi có lỗi xảy ra ở production, stack trace sẽ trỏ vào chunks/12345-something.js thay vì app/page.tsx mà bạn viết.

Sơ đồ minh họa quá trình build Next.js: từ file TypeScript/React gốc đi qua compile, minify, code splitting, ra thành các chunk files nhỏ với tên ngẫu nhiên, nền tối, phong cách flat design với mũi tên nối các bước

Điều mình thấy hay là source maps giải quyết đúng cái gap này. Mỗi chunk file được build ra sẽ kèm theo hai thứ quan trọng: một debug ID và một sourceMappingURL trỏ tới source map tương ứng. Source map về bản chất là một bản đồ ánh xạ ngược — từ code đã minify về lại code gốc, đúng file, đúng dòng, đúng cột.

Tại sao DevTools đẹp mà Sentry thì toàn chunks?

Đây là cái trap mà mình từng mắc. Chạy next dev, mở browser DevTools, throw một error — stack trace hiện ra đẹp lung linh, đúng filename, đúng line number. Rồi mình nghĩ: "Ủa Sentry cũng phải thấy vậy chứ?"

Không.

Khi chạy dev mode, browser có quyền truy cập trực tiếp vào source maps và source files nằm ngay trên máy bạn. Nó tự resolve được hết. Nhưng Sentry thì khác — Sentry chỉ thấy những gì bạn gửi cho nó. Không upload source maps = Sentry chỉ nhận được mấy cái bundle chunks vô nghĩa.

So sánh hai màn hình: bên trái là browser DevTools hiển thị stack trace rõ ràng với tên file gốc và line number chính xác, bên phải là Sentry dashboard hiển thị stack trace toàn chunk names ngẫu nhiên, phong cách split-screen với nền tối

Tệ hơn nữa, chunk names thay đổi sau mỗi lần build. Cùng một lỗi logic nhưng xuất hiện ở hai builds khác nhau sẽ tạo ra hai issues riêng biệt trong Sentry. Debug mà thấy vậy thì muốn bỏ nghề luôn.

Dùng Spotlight cho local, để dành Sentry cho production

Theo kinh nghiệm của mình, sai lầm phổ biến nhất là dùng Sentry cho cả local development. Bạn đang code feature, mỗi lần save là throw error, mỗi error tạo ra fresh chunks, gửi hàng đống near-duplicate events lên Sentry — vừa burn quota vừa làm noise cho team.

Giải pháp: dùng Spotlight cho local dev. Spotlight hoạt động tương tự Sentry nhưng chạy hoàn toàn local, giữ tất cả debug noise ở máy bạn. Sentry thì để dành cho production issues từ real users — những lỗi thực sự cần quan tâm.

Setup source maps: Bước thực hành

Để Sentry nhận được source maps, bạn cần chạy qua production build pipeline — không phải dev mode. Đơn giản thôi:

Terminal
1npm run build
2npm run start

npm run build tạo production build — đây là lúc Sentry hook vào. npm run start serve cái build đó như thể đang chạy production thật.

Sentry làm gì trong bước build?

Khi npm run build chạy xong phần compile, Sentry hook vào giai đoạn after production compile và thực hiện:

  1. Thu thập tất cả generated chunks
  2. Tìm source maps tương ứng
  3. Upload cả chunks và source maps lên Sentry server
  4. Xóa source maps khỏi build output
Sơ đồ quy trình Sentry hook vào Next.js build: sau bước production compile, Sentry thu thập chunks và source maps, upload lên Sentry server, rồi xóa source maps khỏi build output. Có icon ổ khóa ở bước cuối thể hiện bảo mật

Bước cuối rất quan trọng — source maps bị xóa khỏi output nên users không thể mở DevTools và đọc source code gốc của bạn. Bạn vẫn có readable stack traces trong Sentry, nhưng không expose code cho bất kỳ ai.

Điều mình thấy hay là cách Sentry dùng debug ID để match. Mỗi minified file và source map tương ứng đều có cùng một debug ID. Khi error xảy ra, Sentry nhận stack trace từ minified code, tìm debug ID, match với source map đã upload, rồi de-minify — trả về đúng file gốc, đúng dòng code bạn viết.

Minh họa cách debug ID hoạt động: một minified chunk file và một source map file cùng chứa debug ID giống nhau, Sentry dùng debug ID để ghép cặp và map ngược stack trace về code gốc

Verify setup đã đúng chưa

Sau khi chạy npm run buildnpm run start, trigger một sample error rồi kiểm tra trong Sentry. Nếu stack trace hiện đúng filename gốc và line number — bạn đã setup xong.

Nếu vẫn thấy chunks, check lại:

  • Sentry SDK đã được config đúng trong next.config.js chưa
  • Auth token có quyền upload source maps không
  • Build có chạy qua production pipeline không (không phải dev mode)
Màn hình Sentry dashboard hiển thị một error với stack trace đã được de-minify: hiện đúng tên file gốc như app/page.tsx, đúng line number, có code context hiển thị đoạn code xung quanh dòng lỗi

Những điều đáng nhớ

  • Source maps là cầu nối giữa production chunks và code gốc của bạn. Không có nó, Sentry chỉ thấy gibberish.
  • Debug ID là cơ chế Sentry dùng để match minified file với source map. Mỗi cặp chia sẻ cùng một ID.
  • Luôn test với production build (npm run build + npm run start), không phải dev mode.
  • Source maps bị xóa sau upload — users không thể đọc source code gốc qua DevTools.
  • Dùng Spotlight cho local dev, giữ Sentry sạch cho production errors thực sự.

Theo kinh nghiệm của mình, setup source maps là một trong những việc "làm một lần, hưởng mãi mãi" trong bất kỳ dự án Next.js nào. Mất khoảng 15-20 phút setup, nhưng tiết kiệm hàng giờ debug mỗi khi có production incident. Nếu bạn đang chạy Next.js + Sentry mà chưa setup source maps — hôm nay là ngày tốt để làm đấy.

NN

Nguyen Nhat Long

@longnn

Thấy hay? Chia sẻ cho bạn bè!

Bài viết liên quan

Có thể bạn cũng thích

Xem tất cả