Nghiên cứu điển hình: Gỡ lỗi góc hiệu quả hơn bằng Công cụ cho nhà phát triển

Cải thiện trải nghiệm gỡ lỗi

Trong vài tháng qua, nhóm Chrome DevTools đã cộng tác với nhóm Angular để cải thiện trải nghiệm gỡ lỗi trong Chrome DevTools. Các thành viên của cả hai nhóm đã cùng nhau làm việc và thực hiện các bước để cho phép nhà phát triển gỡ lỗi và phân tích tài nguyên ứng dụng web từ góc độ tác giả: về ngôn ngữ nguồn và cấu trúc dự án, với quyền truy cập vào thông tin quen thuộc và liên quan đến họ.

Bài đăng này sẽ xem xét những thay đổi cần thiết trong Angular và Công cụ cho nhà phát triển Chrome để đạt được điều này. Mặc dù một số thay đổi này được minh hoạ thông qua Angular, nhưng bạn cũng có thể áp dụng các thay đổi đó cho các khung khác. Nhóm Công cụ phát triển Chrome khuyến khích các khung khác sử dụng API bảng điều khiển mới và các điểm mở rộng bản đồ nguồn để họ cũng có thể mang lại trải nghiệm gỡ lỗi tốt hơn cho người dùng.

Mã danh sách bỏ qua

Khi gỡ lỗi ứng dụng bằng Công cụ của Chrome cho nhà phát triển, tác giả thường chỉ muốn xem mã của họ, chứ không phải mã của khung bên dưới hoặc một số phần phụ thuộc nằm trong thư mục node_modules.

Để đạt được điều này, nhóm Công cụ cho nhà phát triển đã giới thiệu một tiện ích cho bản đồ nguồn, có tên là x_google_ignoreList. Tiện ích này dùng để xác định các nguồn của bên thứ ba, chẳng hạn như mã khung hoặc mã do trình tạo gói tạo. Khi một khung sử dụng tiện ích này, tác giả hiện sẽ tự động tránh mã mà họ không muốn xem hoặc bước qua mà không cần phải định cấu hình trước theo cách thủ công.

Trong thực tế, Chrome DevTools có thể tự động ẩn mã được xác định là như vậy trong dấu vết ngăn xếp, cây Nguồn, hộp thoại Mở nhanh, đồng thời cải thiện hành vi bước và tiếp tục trong trình gỡ lỗi.

Ảnh GIF động cho thấy DevTools trước và sau. Lưu ý cách trong hình ảnh sau, DevTools hiển thị Mã do tác giả tạo trong cây, không còn đề xuất bất kỳ tệp khung nào trong trình đơn "Mở nhanh" và hiển thị dấu vết ngăn xếp rõ ràng hơn nhiều ở bên phải.

Tiện ích bản đồ nguồn x_google_ignoreList

Trong bản đồ nguồn, trường x_google_ignoreList mới tham chiếu đến mảng sources và liệt kê các chỉ mục của tất cả các nguồn bên thứ ba đã biết trong bản đồ nguồn đó. Khi phân tích cú pháp bản đồ nguồn, Chrome DevTools sẽ sử dụng thông tin này để xác định những phần mã cần đưa vào danh sách bỏ qua.

Dưới đây là bản đồ nguồn cho tệp out.js được tạo. Có hai sources ban đầu đã góp phần tạo ra tệp đầu ra: foo.jslib.js. Mã nguồn đầu tiên là mã nguồn do nhà phát triển trang web viết và mã nguồn thứ hai là khung mà họ sử dụng.

{
  "version" : 3,
  "file": "out.js",
  "sourceRoot": "",
  "sources": ["foo.js", "lib.js"],
  "sourcesContent": ["...", "..."],
  "names": ["src", "maps", "are", "fun"],
  "mappings": "A,AAAB;;ABCDE;"
}

sourcesContent được đưa vào cả hai nguồn gốc này và theo mặc định, Chrome DevTools sẽ hiển thị các tệp này trên Trình gỡ lỗi:

  • Dưới dạng tệp trong cây Nguồn.
  • Dưới dạng kết quả trong hộp thoại Mở nhanh.
  • Là vị trí khung lệnh gọi được liên kết trong dấu vết ngăn xếp lỗi khi tạm dừng tại một điểm ngắt và khi thực hiện từng bước.

Giờ đây, bạn có thể thêm một thông tin khác vào bản đồ nguồn để xác định nguồn nào là mã gốc hoặc mã của bên thứ ba:

{
  ...
  "sources": ["foo.js", "lib.js"],
  "x_google_ignoreList": [1],
  ...
}

Trường x_google_ignoreList mới chứa một chỉ mục duy nhất tham chiếu đến mảng sources: 1. Điều này chỉ định rằng các vùng được liên kết với lib.js thực sự là mã của bên thứ ba sẽ tự động được thêm vào danh sách bỏ qua.

Trong ví dụ phức tạp hơn, như minh hoạ bên dưới, các chỉ mục 2, 4 và 5 chỉ định rằng các vùng được liên kết với lib1.ts, lib2.coffeehmr.js đều là mã của bên thứ ba sẽ tự động được thêm vào danh sách bỏ qua.

{
  ...
  "sources": ["foo.html", "bar.css", "lib1.ts", "baz.js", "lib2.coffee", "hmr.js"],
  "x_google_ignoreList": [2, 4, 5],
  ...
}

Nếu bạn là nhà phát triển khung hoặc trình tạo gói, hãy đảm bảo rằng sơ đồ nguồn được tạo trong quá trình tạo bản dựng có trường này để kết nối với các tính năng mới này trong Công cụ dành cho nhà phát triển Chrome.

x_google_ignoreList trong Angular

Kể từ Angular phiên bản 14.1.0, nội dung của thư mục node_moduleswebpack đã được đánh dấu là "bỏ qua".

Điều này được thực hiện thông qua thay đổi trong angular-cli bằng cách tạo một trình bổ trợ liên kết với mô-đun Compiler của webpack

Trình bổ trợ webpack mà các kỹ sư của chúng tôi đã tạo các trình nối vào giai đoạn PROCESS_ASSETS_STAGE_DEV_TOOLING và điền trường x_google_ignoreList trong bản đồ nguồn cho các thành phần cuối cùng mà webpack tạo ra và trình duyệt tải.

const map = JSON.parse(mapContent) as SourceMap;
const ignoreList = [];

for (const [index, path] of map.sources.entries()) {
  if (path.includes('/node_modules/') || path.startsWith('webpack/')) {
    ignoreList.push(index);
  }
}

map[`x_google_ignoreList`] = ignoreList;
compilation.updateAsset(name, new RawSource(JSON.stringify(map)));

Dấu vết ngăn xếp được liên kết

Dấu vết ngăn xếp trả lời câu hỏi “làm cách nào để tôi đến đây”, nhưng thường thì đây là từ quan điểm của máy và không nhất thiết phải khớp với quan điểm của nhà phát triển hoặc mô hình tinh thần của họ về thời gian chạy ứng dụng. Điều này đặc biệt đúng khi một số thao tác được lên lịch để diễn ra không đồng bộ sau này: bạn vẫn có thể muốn biết "nguyên nhân gốc rễ" hoặc khía cạnh lên lịch của các thao tác như vậy, nhưng đó chính xác là điều sẽ không có trong dấu vết ngăn xếp không đồng bộ.

V8 có một cơ chế nội bộ để theo dõi các tác vụ không đồng bộ như vậy khi sử dụng các nguyên hàm lập lịch trình trình duyệt chuẩn, chẳng hạn như setTimeout. Việc này được thực hiện theo mặc định trong những trường hợp đó, vì vậy, nhà phát triển có thể kiểm tra các lỗi này! Tuy nhiên, trong các dự án phức tạp hơn, việc này không đơn giản như vậy, đặc biệt là khi sử dụng một khung có cơ chế lên lịch nâng cao hơn, chẳng hạn như một khung thực hiện tính năng theo dõi vùng, tạo hàng đợi tác vụ tuỳ chỉnh hoặc chia các bản cập nhật thành một số đơn vị công việc được chạy theo thời gian.

Để giải quyết vấn đề này, DevTools hiển thị một cơ chế có tên là "Async Stack Tagging API" (API gắn thẻ ngăn xếp không đồng bộ) trên đối tượng console, cho phép các nhà phát triển khung gợi ý cả vị trí thực hiện các thao tác cũng như vị trí thực thi các thao tác này.

API gắn thẻ ngăn xếp không đồng bộ

Nếu không có tính năng Gắn thẻ ngăn xếp không đồng bộ, dấu vết ngăn xếp cho mã được thực thi không đồng bộ theo cách phức tạp bởi các khung sẽ xuất hiện mà không có mối liên kết nào với mã đã lên lịch.