Cải thiện trải nghiệm gỡ lỗi
Trong vài tháng qua, nhóm Công cụ của Chrome cho nhà phát triển đã cộng tác với nhóm Angular để cải thiện trải nghiệm gỡ lỗi trong Công cụ của Chrome cho nhà phát triển. Thành viên của cả hai nhóm đã làm việc cùng nhau và thực hiện các bước hướng tới tạo điều kiện cho các nhà phát triển gỡ lỗi và phân tích tài nguyên về ứng dụng web từ góc độ tác giả: xét về ngôn ngữ nguồn và cấu trúc dự án, đồng thời có quyền truy cập vào thông tin quen thuộc và phù hợp với 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 chỉ mã của họ chứ không muốn xem mã của khung bên dưới hoặc một phần phụ thuộc nào đó nằm gọn 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ế, Công cụ của Chrome cho nhà phát triển có thể tự động ẩn mã được xác định trong dấu vết ngăn xếp, cây Nguồn, hộp thoại Mở nhanh, đồng thời cũng cải thiện hành vi bước và tiếp tục trong trình gỡ lỗ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 được đư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
gốc đã góp phần tạo ra tệp đầu ra: foo.js
và lib.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, Công cụ của Chrome cho nhà phát triển 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 bổ sung vào bản đồ nguồn để xác định nguồn nào là mã gốc hay 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.coffee
và hmr.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 đóng gói, hãy đảm bảo bản đồ nguồn được tạo trong quá trình xây dựng có trường này để kết nối với những tính năng mới này trong Công cụ của Chrome cho nhà phát triển.
x_google_ignoreList
trong Angular
Kể từ Angular phiên bản 14.1.0, nội dung của thư mục node_modules
và webpack
đã đượ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 bổ trợ 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ể biết được "nguyên nhân gốc" hoặc khía cạnh lập lịch của các thao tác đó, nhưng chính xác thì đó không phải là một phần của 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! Nhưng 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.
Với tính năng Gắn thẻ ngăn xếp không đồng bộ, bạn có thể cung cấp ngữ cảnh này và dấu vết ngăn xếp sẽ có dạng như sau:
Để đạt được điều này, hãy sử dụng một phương thức console
mới có tên là console.createTask()
mà API gắn thẻ ngăn xếp không đồng bộ cung cấp. Chữ ký của đường liên kết này có dạng như sau:
interface Console {
createTask(name: string): Task;
}
interface Task {
run<T>(f: () => T): T;
}
Việc gọi console.createTask()
sẽ trả về một thực thể Task
mà sau này bạn có thể sử dụng để chạy mã không đồng bộ.
// Task Creation
const task = console.createTask(name);
// Task Execution
task.run(f);
Các thao tác không đồng bộ cũng có thể được lồng và "nguyên nhân gốc rễ" sẽ hiển thị trong dấu vết ngăn xếp theo trình tự.
Bạn có thể chạy tác vụ bất kỳ số lần nào và tải trọng công việc có thể khác nhau giữa mỗi lần chạy. Ngăn xếp lệnh gọi tại trang web lên lịch sẽ được ghi nhớ cho đến khi đối tượng tác vụ được thu gom rác.
API gắn thẻ ngăn xếp không đồng bộ trong Angular
Trong Angular, chúng tôi đã thực hiện các thay đổi đối với NgZone – ngữ cảnh thực thi của Angular vẫn tồn tại trên các tác vụ không đồng bộ.
Khi lên lịch cho một tác vụ, tính năng này sẽ sử dụng console.createTask()
(nếu có). Thực thể Task
thu được sẽ được lưu trữ để sử dụng sau này. Khi gọi tác vụ, NgZone sẽ sử dụng thực thể Task
đã lưu trữ để chạy tác vụ đó.
Những thay đổi này đã được đưa vào NgZone 0.11.8 của Angular thông qua các yêu cầu kéo #46693 và #46958.
Khung cuộc gọi thân thiện
Khung thường tạo mã từ mọi loại ngôn ngữ tạo mẫu khi xây dựng dự án, chẳng hạn như mẫu Angular hoặc JSX chuyển mã có giao diện HTML thành JavaScript thuần tuý và cuối cùng chạy trong trình duyệt. Đôi khi, những loại hàm được tạo này được đặt tên không thân thiện cho lắm — có thể là tên một chữ cái sau khi rút gọn hoặc một số tên ít người biết đến hoặc lạ lẫm ngay cả khi chúng không được dùng nữa.
Trong Angular, bạn thường thấy các khung lệnh gọi có tên như AppComponent_Template_app_button_handleClick_1_listener
trong dấu vết ngăn xếp.
Để giải quyết vấn đề này, Chrome DevTools hiện hỗ trợ việc đổi tên các hàm này thông qua bản đồ nguồn. Nếu bản đồ nguồn có mục nhập tên cho phần bắt đầu của phạm vi hàm (tức là dấu ngoặc đơn bên trái của danh sách tham số), thì khung lệnh gọi sẽ hiển thị tên đó trong dấu vết ngăn xếp.
Khung lệnh gọi thân thiện trong Angular
Việc đổi tên khung lệnh gọi trong Angular là một nỗ lực liên tục. Chúng tôi dự kiến những điểm cải tiến này sẽ được triển khai dần theo thời gian.
Trong khi phân tích cú pháp các mẫu HTML mà tác giả đã viết, trình biên dịch Angular tạo ra mã TypeScript. Mã này cuối cùng sẽ được dịch thành mã JavaScript mà trình duyệt tải và chạy.
Trong quá trình tạo mã này, bản đồ nguồn cũng được tạo. Chúng tôi hiện đang tìm hiểu các cách đưa tên hàm vào trường "tên" của bản đồ nguồn và tham chiếu các tên đó trong mối liên kết giữa mã được tạo và mã gốc.
Ví dụ: nếu một hàm cho trình nghe sự kiện được tạo và tên của hàm đó không thân thiện hoặc bị xoá trong quá trình rút gọn, thì bản đồ nguồn hiện có thể bao gồm tên thân thiện hơn cho hàm này trong trường "tên" và mối liên kết cho phần đầu của phạm vi hàm hiện có thể tham chiếu đến tên này (tức là dấu ngoặc đơn bên trái của danh sách tham số). Sau đó, Chrome DevTools sẽ sử dụng các tên này để đổi tên khung lệnh gọi trong dấu vết ngăn xếp.
Hướng đến tương lai
Việc sử dụng Angular làm chương trình thí điểm kiểm thử để xác minh công việc của chúng tôi là một trải nghiệm tuyệt vời. Chúng tôi rất mong nhận được ý kiến của các nhà phát triển khung và ý kiến phản hồi của bạn về các điểm mở rộng này.
Chúng tôi muốn khám phá thêm nhiều lĩnh vực khác. Cụ thể là cách cải thiện trải nghiệm phân tích tài nguyên trong Công cụ cho nhà phát triển.