Wstęp
Obecnie autorzy mogą tworzyć aplikacje internetowe przy użyciu wielu abstrakcji. Zamiast bezpośredniej interakcji z interfejsami API niższego poziomu dostępnych w ramach platformy internetowej wielu autorów korzysta z platform, narzędzi i kompilatorów, aby pisać swoje aplikacje z perspektywy wyższego poziomu.
Na przykład komponenty utworzone na platformie Angular są tworzone w języku TypeScript i zawierającym szablony HTML. Pod maską interfejs wiersza poleceń i pakiet internetowy Angular kompilują wszystko do języka JavaScript i tworzą tzw. pakiet, który jest następnie wysyłany do przeglądarki.
Podczas debugowania lub profilowania aplikacji internetowych za pomocą Narzędzi deweloperskich możesz obecnie zobaczyć i debugować skompilowaną wersję swojego kodu zamiast faktycznie napisanego. Nie jest to jednak potrzebne zachowanie jako autora:
- Chcesz debugować skompresowany kod JavaScript, tylko oryginalny.
- Korzystając z TypeScriptu, nie chcesz debugować JavaScriptu, tylko chcesz debugować oryginalny kod TypeScript.
- Jeśli używasz szablonów, jak w Angular, Lit lub JSX, nie zawsze chcesz debugować wynikowy DOM. Warto samodzielnie debugować komponenty.
Ogólnie rzecz biorąc, warto debugować własny kod w takiej postaci, w jakiej został napisany.
Mapy źródeł już w pewnym stopniu wypełniają tę lukę, ale Narzędzia deweloperskie w Chrome i ekosystem mogą osiągnąć w tym obszarze o wiele więcej.
Przyjrzyjmy się im bliżej.
Kod stworzony a kod wdrożony
Obecnie podczas poruszania się po drzewie plików w panelu Źródła widoczna jest zawartość skompilowanego – i często zminimalizowanego – pakietu. Rzeczywiste pliki, które są pobierane i uruchamiane przez przeglądarkę. W Narzędziach deweloperskich nosi on nazwę Deployed Code (Wdrożony kod).
Nie jest to proste i często trudne do zrozumienia. Jako autor chcesz wyświetlić i debugować napisany przez siebie kod, a nie wdrożony kod.
Aby to zrekompensować, możesz teraz wyświetlać w drzewie kod autora. Dzięki temu drzewo bardziej przypomina pliki źródłowe, które można zobaczyć w IDE, a te pliki są teraz rozdzielone od Wdrożonego kodu.
Aby włączyć tę opcję w Narzędziach deweloperskich w Chrome, otwórz Ustawienia > Eksperymenty i zaznacz Grupuj źródła w drzewa utworzone i wdrożone.
„Tylko mój kod”
Gdy korzystasz z zależności lub pracujesz nad strukturą, pliki innych firm mogą Ci w tym przeszkadzać. Zwykle chcesz zobaczyć tylko swój kod, a nie kod z biblioteki zewnętrznej ukrytej w folderze node_modules
.
Aby to zrekompensować, w Narzędziach deweloperskich domyślnie włączone jest dodatkowe ustawienie: Automatycznie dodawaj znane skrypty innych firm do listy ignorowanych. Znajdziesz go, klikając DevTools > DevTools > DevTools.
Gdy to ustawienie jest włączone, Narzędzia deweloperskie ukrywają każdy plik lub folder, który platforma lub narzędzie do kompilacji oznaczyło jako do ignorowania.
Od Angular w wersji 14.1.0 zawartość folderów node_modules
i webpack
jest tak oznaczona. Dlatego te foldery, zawarte w nich pliki i inne artefakty zewnętrzne nie są widoczne w różnych miejscach w Narzędziach deweloperskich.
Jako autor nie musisz nic robić, aby włączyć to nowe zachowanie. Wprowadzenie tej zmiany należy do zasad.
Kod z listy ignorowanych w zrzucie stosu
Pliki z listy ignorowanych nie pojawiają się już w zrzucie stosu. Jako autor masz teraz dostęp do bardziej trafnych zrzutów stosu.
Jeśli chcesz zobaczyć wszystkie ramki wywołań stosu zrzutu, kliknij link Pokaż więcej ramek.
To samo dotyczy stosów wywołań, które widzisz podczas debugowania i przeglądania kodu. Gdy platformy lub usługi tworzenia pakietów przekazują w Narzędziach deweloperskich informacje o skryptach innych firm, podczas debugowania kroku narzędzia te automatycznie ukrywają wszystkie nieistotne ramki wywołań i przeskakują nad wszelkimi kodami z listy ignorowanych.
Ignorowany kod w drzewie plików
Aby ukryć pliki i foldery na liście ignorowanych w drzewie plików Kod autora w panelu Źródła, w Narzędziach deweloperskich zaznacz Ukryj kod z listy ignorowanych w widoku drzewa źródeł w sekcji Ustawienia > Eksperymenty.
W przykładowym projekcie Angular foldery node_modules
i webpack
są teraz ukryte.
Ignorowany kod w menu „Szybkie otwieranie”
Ignorowany kod jest nie tylko ukryty w drzewie plików, ale także ukryty w menu „Szybkie otwieranie” (Control+P (Linux/Windows) lub Command+P (Mac)).
Więcej ulepszeń zrzutów stosu
Po omówieniu odpowiednich zrzutów stosu w Narzędziach deweloperskich w Chrome wprowadziliśmy jeszcze więcej ulepszeń.
Połączone zrzuty stosu
Jeśli niektóre operacje mają być wykonywane asynchronicznie, zrzuty stosu w Narzędziach deweloperskich przekazują obecnie tylko część historii.
Oto na przykład bardzo prosty algorytm szeregowania w hipotetycznym pliku framework.js
:
function makeScheduler() {
const tasks = [];
return {
schedule(f) {
tasks.push({ f });
},
work() {
while (tasks.length) {
const { f } = tasks.shift();
f();
}
},
};
}
const scheduler = makeScheduler();
function loop() {
scheduler.work();
requestAnimationFrame(loop);
};
loop();
...oraz jak deweloper może go użyć we własnym kodzie w pliku example.js
:
function someTask() {
console.trace("done!");
}
function businessLogic() {
scheduler.schedule(someTask);
}
businessLogic();
Podczas dodawania punktu przerwania w metodzie someTask
lub podczas badania logu czasu wyświetlanego w konsoli nie widzisz żadnego wywołania businessLogic()
, które było „główną przyczyną” tej operacji.
Zamiast tego widzisz tylko logikę harmonogramu platformy, która doprowadziła do wykonania zadania, a w zrzucie stosu nie ma menu nawigacyjnego, które pomagałoby w ustaleniu powiązań między zdarzeniami prowadzącymi do tego zadania.
Dzięki nowej funkcji o nazwie „Asynchroniczne tagowanie stosu” można opowiedzieć całą historię, łącząc ze sobą obie części kodu asynchronicznego.
Interfejs Async Stack Tagging API wprowadza nową metodę console
o nazwie console.createTask()
. Podpis interfejsu API wygląda tak:
interface Console {
createTask(name: string): Task;
}
interface Task {
run<T>(f: () => T): T;
}
Wywołanie console.createTask()
zwraca instancję Task
, której możesz później użyć do uruchomienia treści zadania f
.
// Task Creation
const task = console.createTask(name);
// Task Execution
task.run(f);
Zadanie tworzy połączenie między kontekstem, w którym zostało utworzone, a kontekstem wykonywanej funkcji asynchronicznej.
Po zastosowaniu do powyższej funkcji makeScheduler
kod zmienia się w taki sposób:
function makeScheduler() {
const tasks = [];
return {
schedule(f) {
const task = console.createTask(f.name);
tasks.push({ task, f });
},
work() {
while (tasks.length) {
const { task, f } = tasks.shift();
task.run(f); // instead of f();
}
},
};
}
Dzięki temu Narzędzia deweloperskie w Chrome mogą teraz wyświetlać lepszy zrzut stosu.
Zwróć uwagę, że zrzut stosu zawiera teraz fragment businessLogic()
. Oprócz tego zadanie ma znaną już nazwę someTask
, a nie ogólną nazwę requestAnimationFrame
.
Przyjazne ramki połączeń
Platformy często generują kod przy użyciu różnego rodzaju języków szablonów, na przykład Angular lub JSX, które zmieniają kod przypominający język HTML w zwykły kod JavaScript, który następnie działa w przeglądarce. Czasami tego rodzaju generowane funkcje mają nazwy, które nie są zbyt przyjazne – mogą to być nazwy jednoliterowe po zmniejszeniu albo nazwy mało znane lub nieznane, nawet jeśli takie nie są.
W przykładowym projekcie jest to na przykład AppComponent_Template_app_button_handleClick_1_listener
, który widać w zrzucie stosu.
Aby rozwiązać ten problem, w Narzędziach deweloperskich w Chrome możesz teraz zmieniać nazwy tych funkcji za pomocą map źródeł. Jeśli mapa źródeł zawiera wpis nazwy na początku zakresu funkcji, ramka wywołania powinna wyświetlać tę nazwę w zrzucie stosu.
Jako autor nie musisz nic robić, aby włączyć to nowe zachowanie. Wprowadzenie tej zmiany należy do zasad.
Perspektywy
Dzięki funkcjom opisanym w tym poście Narzędzia deweloperskie w Chrome oferują lepsze możliwości debugowania. Zespół chce zbadać więcej obszarów. W szczególności dowiesz się, jak ulepszyć profilowanie w Narzędziach deweloperskich.
Zespół Narzędzi deweloperskich w Chrome zachęca twórców platform do wdrożenia tych nowych funkcji. Wskazówki dotyczące implementacji znajdziesz w studium przypadku: Better Angular Debugging with DevTools (w języku angielskim).