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.
Nguyen Nhat Long
@longnn

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.

Đ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.

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:
1npm run build2npm 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:
- Thu thập tất cả generated chunks
- Tìm source maps tương ứng
- Upload cả chunks và source maps lên Sentry server
- Xóa source maps khỏi build output

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.

Verify setup đã đúng chưa
Sau khi chạy npm run build và npm 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.jschư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)

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.
Nguyen Nhat Long
@longnnThấy hay? Chia sẻ cho bạn bè!
Bài viết liên quan
Có thể bạn cũng thích
Tolaria Quản lý knowledge base bằng Markdown như dân chuyên nghiệp
Tolaria là desktop app open source giúp quản lý knowledge base bằng markdown files, git-first, offline-first. Đây có thể là thứ bạn đang thiếu cho second brain.
Floci: Giã từ LocalStack, chào đón AWS emulator miễn phí thực sự
LocalStack Community đã sunset. Floci là alternative mới — mã nguồn mở, không cần auth token, startup 24ms. Đây là lý do bạn nên thử ngay.
Tại sao AI vẫn tệ với Front-end?
AI có thể generate cả thế giới 3D, video, hình ảnh — nhưng tại sao nó vẫn chật vật với CSS và UI bespoke? Cùng mổ xẻ lý do nhé.