Playbook thực hành để debug DOM, CSS, JavaScript, Vue và bundle Webpack đã transpile hoặc minimize bằng Chrome DevTools.
Chrome DevTools: Frontend Debugging Playbook
Một trang web hiện đại thường đi qua nhiều lớp trước khi chạy trong trình duyệt:
Chrome luôn thực thi mã đã build. Source map chỉ làm cho Sources panel hiển thị và ánh xạ vị trí về mã bạn viết; nó không thay đổi code đang chạy. sourceURL lại dành cho source được tạo động bằng eval() hoặc new Function(). Hai khái niệm này thường bị nhầm khi debug Vue/Webpack.

Hướng dẫn hình ảnh chính thức: Debug JavaScript trong Chrome DevTools.
Quy trình 60 giây trước khi đặt breakpoint
Khi gặp lỗi, đừng bắt đầu bằng việc thêm thật nhiều console.log. Hãy thu hẹp sự kiện gây lỗi trước:
- Tạo một reproduction nhỏ và ghi lại thao tác chính xác: URL, input, thứ tự click, kích thước màn hình.
- Mở DevTools bằng
Ctrl+Shift+I, bật Preserve log trong Console và Network. - Trong Network, bật Disable cache khi DevTools đang mở; chỉ bật khi cần tái hiện tải tài nguyên thật.
- Chọn đúng frame trong Console nếu trang dùng iframe.
- Kiểm tra lỗi đầu tiên theo thứ tự thời gian. Lỗi đầu tiên thường là nguyên nhân, các lỗi sau có thể chỉ là hiệu ứng dây chuyền.
- Chọn một trong bốn điểm dừng: DOM bị đổi, CSS bị ghi đè, event không chạy, hoặc request trả về dữ liệu sai.
Command Menu (Ctrl+Shift+P) là cách nhanh nhất để tìm các tính năng ít dùng:
1. Elements: tìm nơi DOM bị thay đổi
DOM đang chạy khác với HTML nguồn
Tab Elements hiển thị DOM hiện tại, sau khi Vue, React hoặc JavaScript đã mount và mutate trang. View Source chỉ hiển thị HTML response ban đầu. Khi một node thiếu class, có text sai hoặc biến mất:
- Chọn node bằng
Ctrl+Shift+C. - Nhấn
Hđể ẩn node mà không xóa nó; dùngDeleteđể thử tác động của việc xóa node. - Nhìn vào
Attributes,Event Listeners,PropertiesvàComputedđể tìm khác biệt. - Dùng
Ctrl+Zđể hoàn tác thay đổi thử nghiệm trong DevTools.
Node đang chọn được gọi là $0; bốn node vừa chọn trước đó lần lượt là $1 đến $4.
Lưu ý: DOM sửa trong Elements chỉ là thí nghiệm cục bộ. Nó không sửa Vue template hay code trên server.
DOM breakpoints: bắt đúng dòng code mutate node
Click phải node → Break on:
- Subtree modifications: child được thêm/xóa hoặc text của child thay đổi.
- Attribute modifications:
class,style,aria-*,data-*hoặc attribute khác đổi. - Node removal: chính node bị xóa khỏi DOM.
Khi code chạy, debugger dừng tại dòng JavaScript gây mutation. Đây là cách nhanh nhất để tìm script nào liên tục thêm lại class hoặc render lại một vùng UI. Chrome liệt kê các loại DOM breakpoint và XHR/event breakpoint trong tài liệu Pause your code with breakpoints.
Tìm event listener thật sự
Nếu click không hoạt động, kiểm tra lần lượt:
- node có bị một phần tử khác che lên không;
pointer-events: nonecó đang bật không;- listener có được đăng ký trên node cha do event delegation không;
- handler có chạy nhưng return sớm vì điều kiện hay không;
- một DOM breakpoint có dừng ở đoạn code cập nhật state/render không.
2. CSS: phân biệt style sai với layout sai
Đọc Styles và Computed đúng cách
- Styles cho biết rule nào áp dụng, rule nào bị gạch ngang vì specificity hoặc thứ tự cascade.
- Computed cho biết giá trị cuối cùng mà browser sử dụng.
- Trong Computed, mở rộng một property để xem rule và file CSS tạo ra giá trị đó.
- Kiểm tra Inherited from khi
color,font,line-heighthoặcvisibilityđến từ ancestor. - Dùng
:hovđể ép:hover,:focus,:focus-within,:activevà:visited. - Dùng
clsđể bật/tắt class theo thời gian thực. - Click dấu
+để tạo rule tạm trongelement.style.

Tài liệu kèm hình: CSS features reference.
Các câu lệnh CSS hữu ích
Nếu box có kích thước đúng nhưng không nhìn thấy, kiểm tra opacity, visibility, display, overflow, clip-path, z-index và stacking context. Nếu layout nhảy, mở Layout và bật overlay Grid/Flex; đừng chỉ nhìn vào giá trị width của một node.
Debug CSS trong bundle đã minimize
- Bật Enable CSS source maps trong Settings → Preferences → Sources.
- Mở file CSS trong Sources và tìm
.vue/.scssgốc bằngCtrl+P. - Nếu không có map, dùng Styles để xác định selector bị ghi đè trước; chỉ sau đó mới tìm chuỗi selector trong file minified.
- Thử sửa rule trong DevTools. Nếu cần giữ bản sửa trong lúc reload, dùng Local Overrides hoặc Workspaces.
3. JavaScript debugger: dừng đúng thời điểm

Breakpoint theo tình huống
Đặt Conditional breakpoint bằng click phải số dòng. Ví dụ điều kiện:
Logpoint hữu ích khi bug chỉ xuất hiện sau 20 lần click: log index, id và state mà không cần commit console.log vào code.
Điều khiển khi đang paused
Khi paused, dùng Scope để xem local/closure/global variables, Watch để theo dõi expression và Call Stack để xem đường đi tới dòng hiện tại. Right-click frame → Restart frame có thể chạy lại function từ đầu, nhưng các side effect bên ngoài như network request hoặc DOM mutation không tự được hoàn tác.
debugger;, debug() và monitor()
debug(fn) cần nhận function object, không phải tên string. Nếu function đang nằm trong closure, hãy đặt breakpoint tại nơi nó còn nằm trong scope rồi gọi debug(fn) từ Console.
Async stack trace
Khi debugger dừng bên trong fetch, Promise, setTimeout hoặc event callback, xem Async stack traces để nối callback hiện tại với nơi đã tạo nó. Nếu stepping quá chậm trên ứng dụng lớn, mở menu Sources và tắt async stack traces tạm thời.
4. Vue + Webpack: debug code đã transpile hoặc minimize
sourceURL không thay thế source map
sourceURL đặt tên cho code được đánh giá động:
Source này sẽ xuất hiện với tên runtime-render-block.js trong Sources và stack trace. Cơ chế này hữu ích cho code sinh bằng eval()/new Function(), runtime template compiler, một số dev tooling hoặc loader dùng eval.
Nó không thể khôi phục một bundle Vue đã minimize về file .vue. Với bundle tĩnh, browser cần sourceMappingURL và file .map. Chrome chạy mã minified nhưng hiển thị mã bạn viết khi map hợp lệ: Debug your original code instead of deployed with source maps.
Cấu hình Webpack nên dùng
eval-source-map: phù hợp development, rebuild tốt và thường cho mapping chất lượng cao.source-map: phù hợp production/staging khi cần debug bundle sau minification.hidden-source-map: tạo map cho hệ thống error tracking nhưng không chèn reference công khai vào bundle.nosources-source-map: map vị trí nhưng không nhúng nội dung source; vẫn cần cân nhắc lộ path/module name.- Tránh
eval-*vàinline-*trong production vì bundle lớn hơn và có thể ảnh hưởng hiệu năng. Webpack production guide
Với Vue CLI, productionSourceMap mặc định bật; có thể cấu hình configureWebpack.devtool hoặc tắt khi không muốn phát hành map. Vue CLI configuration
Bật và kiểm tra source map trong Chrome
- Settings → Preferences → Sources → bật Enable JavaScript source maps và Enable CSS source maps.
- Mở Sources →
Ctrl+P→ tìm tên.vue,.ts,.scss. - Kiểm tra cây
webpack://hoặcvite://tùy bundler. - Đặt breakpoint trong file gốc, reload và tái hiện lỗi.
- Khi paused, kiểm tra Call Stack có frame ứng dụng của bạn hay chỉ có
webpack,node_modulesvà runtime.
Nếu không thấy source gốc, kiểm tra:
- response bundle có
//# sourceMappingURL=...không; - URL
.mapcó trả về200thay vì404/403không; - map được deploy cùng đúng hash của bundle không;
vue-loader, Babel, TypeScript và loader trước đó có bật source map không;- browser có đang dùng bundle cũ từ Service Worker/CDN không;
- source map có bị CORS, CSP hoặc authentication chặn không.
Khi production không có source map
- Mở file minified trong Sources.
- Bấm
{}để Pretty print. - Tìm chuỗi UI, endpoint, message lỗi hoặc tên CSS class bằng
Ctrl+Shift+F. - Dùng breakpoint gần chuỗi đó hoặc bật Pause on exceptions.
- Thêm pattern như
/node_modules/,webpack-internal:vào Ignore List để stepping bỏ qua framework/vendor. - Nếu chỉ có stack trace từ error tracker, dùng đúng artifact/map của build đó; map của build khác hash sẽ cho vị trí sai.
Pretty print chỉ format code đã generate. Nó không phục hồi tên biến, file .vue hoặc cấu trúc module đã bị minimizer loại bỏ.
Vue 2 và Vue 3 trong Console
Vue DevTools là lựa chọn tốt nhất để xem component tree, props, state và Pinia/Vuex. Khi cần chẩn đoán nhanh node đang chọn, có thể thử các thuộc tính nội bộ sau:
Đây là implementation detail; không dùng trong production code hoặc test. Nếu thuộc tính không tồn tại, hãy dùng Vue DevTools hoặc breakpoint tại handler/state mutation.
5. Console recipes cho JavaScript logic
Quan sát dữ liệu
Đo và đếm
Tìm object và listener
Các hàm $0, copy, debug, monitor, queryObjects là DevTools Console utilities; chúng không tồn tại trong JavaScript chạy trên người dùng.
6. Network: nối request với dòng code gọi nó
Trong Network:
- bật Preserve log trước khi chuyển trang;
- lọc
Fetch/XHR,status-code:404,status-code:401hoặcmethod:POST; - xem Payload, Response, Timing và Initiator;
- dùng Initiator để mở stack trace nơi request được dispatch;
- click phải → Copy → Copy as fetch để tái hiện request trong Console;
- dùng Sources → XHR/fetch Breakpoints với một phần URL để dừng ngay trước
fetch()/XHR gửi request.
Khi API trả HTTP 200 nhưng UI sai, đừng chỉ kiểm tra Network. So sánh response với object trong Scope sau bước parse/normalize; lỗi có thể nằm ở mapping field, cache hoặc race condition.
Một số filter nhanh:
7. Các workflow thực tế
Click button nhưng không có phản ứng
- Chọn button, kiểm tra
disabled,pointer-events, overlay và computedcursor. - Chạy
getEventListeners($0). - Bật Event Listener Breakpoint → Mouse →
click. - Nếu không dừng, kiểm tra listener ở ancestor do event delegation.
- Nếu dừng trong handler, xem Scope: input có đúng type không, state có bị stale không, branch nào return sớm.
- Nếu handler chạy nhưng DOM không đổi, đặt DOM breakpoint trên vùng render và kiểm tra state mutation.
Class bị thêm rồi bị xóa ngay
- Chọn node → Break on → Attribute modifications.
- Tái hiện thao tác.
- Khi paused, xem Call Stack và file gốc trong
webpack://. - Kiểm tra các effect/watch, cleanup của component, và code chạy sau
await.
Style đúng trong source nhưng không đúng trên trang
- Chọn node, kiểm tra Computed property thực tế.
- Mở rule bị gạch ngang để biết selector nào thắng.
- Ép
:hover/:focusbằng:hov. - Kiểm tra CSS source map và CSS chunk đã tải trong Network.
- Xác nhận không có shadow DOM hoặc iframe ở giữa.
Lỗi chỉ xuất hiện trong bundle production
- Lấy tên file và hash từ stack trace/error tracker.
- Đảm bảo đang dùng source map đúng build.
- Bật Pause on caught/uncaught exceptions.
- Nếu map có sẵn, đặt breakpoint trong
.vue/.ts; nếu không, Pretty print và tìm string/endpoint. - Kiểm tra khác biệt production: minification, dead-code branch, feature flag, environment variable, CSP và Service Worker.
- Thử Local Overrides để xác nhận giả thuyết trước khi sửa source thật.
Tìm nơi tạo request sai
- Network → lọc URL hoặc status.
- Mở request → Initiator.
- Đặt XHR/fetch breakpoint theo một phần URL.
- Khi paused, xem giá trị URL, headers và payload trước khi request được gửi.
- Nếu request được tạo sau nhiều promise, đọc Async stack trace để quay về event ban đầu.
8. Performance, memory và render
Performance
- Mở Performance, chọn CPU throttle phù hợp và record reload hoặc interaction.
- Tìm task trên 50 ms ở Main thread.
- Các block màu tím lặp lại thường liên quan Style/Layout; xem có DOM read/write xen kẽ gây layout thrashing không.
- Chọn function trong flame chart → xem Bottom-up để tìm self time lớn nhất.
- Kiểm tra marker LCP, CLS và INP.
Rendering
Command Menu → Show rendering:
- Paint flashing: vùng xanh là vùng vừa repaint.
- Layout shift regions: vùng gây dịch chuyển bố cục.
- Frame rendering stats: FPS và frame time.
- Emulate CSS media: thử
prefers-color-scheme,prefers-reduced-motion,forced-colors.
Memory leak
- Memory → Heap snapshot lần 1.
- Mở/đóng modal hoặc chuyển route nhiều lần.
- Force garbage collection.
- Chụp snapshot lần 2 → chọn Comparison.
- Xem object còn sống và mở Retainers để tìm listener, timer hoặc closure giữ reference.
9. Phím tắt cần nhớ
10. Checklist trước khi kết luận lỗi
- Đã tái hiện được lỗi bằng một chuỗi thao tác cụ thể.
- Đã kiểm tra đúng frame, đúng environment và đúng bundle hash.
- Đã kiểm tra DOM hiện tại thay vì chỉ xem HTML nguồn.
- Đã xem Computed và rule thắng trong CSS cascade.
- Đã bật breakpoint phù hợp thay vì thêm log ngẫu nhiên.
- Đã kiểm tra source map và file
.mapcủa đúng build. - Đã loại trừ cache, Service Worker, extension và request cũ.
- Đã phân biệt lỗi dữ liệu API với lỗi render/state.
- Đã tái hiện lại sau khi reload sạch trước khi sửa code.
Tài liệu chính thức và hình ảnh tham khảo
- Chrome DevTools overview
- Debug JavaScript
- Breakpoints reference
- Source maps
- CSS features reference
- Network features reference
- Webpack
devtoolvà source maps - Webpack production source maps
- Vue CLI
productionSourceMap - Vue Loader
Các ảnh trong trang lấy trực tiếp từ tài liệu Chrome for Developers; UI có thể thay đổi nhẹ giữa các phiên bản Chrome.