ניפוי באגים מודרני באינטרנט בכלי הפיתוח ל-Chrome

מבוא

כיום, מחברים יכולים להשתמש בהפשטות רבות כדי לבנות את אפליקציות האינטרנט שלהם. במקום להתממשק ישירות עם ממשקי ה-API ברמה נמוכה יותר שפלטפורמת האינטרנט מספקת, מחברים רבים משתמשים ב-frameworks, מפתחים כלים ומהדרים כדי לכתוב את האפליקציות שלהם מנקודת מבט ברמה גבוהה יותר.

לדוגמה, רכיבים שנבנו מעל ל-Agular framework נכתבים ב-TypeScript באמצעות תבניות HTML. מאחורי הקלעים, ה-CLI של Angular ו-webpack מרכזים את כל התוכן ב-JavaScript לתוך חבילה שנקראת, ולאחר מכן נשלחת לדפדפן.

במהלך ניפוי באגים או יצירת פרופילים של אפליקציות אינטרנט בכלי הפיתוח, אתם יכולים לראות ולנפות באגים בגרסה הזו של הקוד, במקום הקוד שכתבתם בפועל. אבל ככותבים, אין לכם מה לדאוג,

  • אתם לא רוצים לנפות באגים בקוד JavaScript מוקטן, אתם רוצים לנפות באגים בקוד ה-JavaScript המקורי.
  • בעת שימוש ב-TypeScript, לא רוצים לנפות באגים ב-JavaScript, כדאי לנפות באגים בקוד ה-TypeScript המקורי.
  • כשמשתמשים בתבניות כמו Angular, Lit או JSX, לא תמיד כדאי לנפות באגים ב-DOM שנוצר. כדאי לבצע ניפוי באגים ברכיבים עצמם.

באופן כללי, סביר להניח שתרצו לנפות באגים בקוד שלכם כפי שכתבתם.

מפות המקור כבר אומנם סוגרים את הפער הזה, אבל יש עוד דברים שכלי הפיתוח והסביבה העסקית יכולים לעשות בתחום הזה.

בואו נראה!

קוד בעל לעומת קוד נפרס

בשלב זה, כשמנווטים בעץ הקבצים בחלונית המקורות, אפשר לראות את תוכן החבילה של החבילה שעברה הידור (ולרוב מוקטן). אלה הקבצים שהדפדפן מוריד ומפעיל בפועל. כלי הפיתוח קוראים לקובץ הזה Deployed Code (קוד פרוס).

צילום מסך של עץ הקבצים בכלי הפיתוח ל-Chrome שבו מוצג הקוד Deployed.

זה לא כל כך שימושי, ולרוב קשה להבין את זה. ככותבים, אתם רוצים לראות את הקוד שכתבתם ולנפות באגים, ולא את הקוד שנפרס.

כדי לפצות על כך, אפשר עכשיו לבקש בעץ להציג את הקוד לאחר הכתיבה במקום זאת. כך העץ דומה יותר לקובצי מקור שאתם רואים בסביבת הפיתוח המשולבת (IDE), ועכשיו הקבצים האלה מופרדים מהקוד שנפרס.

צילום מסך של עץ הקבצים בכלי הפיתוח ל-Chrome שבו מוצג הקוד הרשום.

כדי להפעיל את האפשרות הזו בכלי הפיתוח ל-Chrome, יש לעבור אל הגדרות > ניסויים ומסמנים את התיבה קיבוץ מקורות בעצים שנכתבו ופרוסים.

צילום מסך של הגדרות כלי הפיתוח.

"רק הקוד שלי"

כאשר משתמשים ביחסי תלות או בונים על גבי מסגרת, הקבצים של הצדדים השלישיים עלולים להפריע לכם. ברוב המקרים רוצים לראות רק את הקוד, ולא את הספרייה של צד שלישי שמסתתרת בתיקייה node_modules.

כדי לפצות על כך, בכלי הפיתוח מופעלת הגדרה נוספת כברירת מחדל: הוספה אוטומטית של סקריפטים מוכרים של צד שלישי לרשימת קטעי הקוד להתעלמות. אפשר למצוא אותו בקטע DevTools > הגדרות > רשימת ההתעלמות.

צילום מסך של הגדרות כלי הפיתוח.

כשההגדרה הזו מופעלת, כלי הפיתוח מסתירים את כל הקבצים או התיקיות שיש להתעלם מהם באמצעות framework או כלי build.

החל מגרסה 14.1.0 של Angular, תוכן התיקיות node_modules ו-webpack שלה סומן ככזה. לכן, התיקיות האלה, הקבצים שנכללים בהן וארטיפקטים אחרים של צד שלישי כאלה לא מופיעים במקומות שונים בכלי הפיתוח.

ככותבים, לא צריך לעשות דבר כדי לאפשר את ההתנהגות החדשה הזו. יישום השינוי הזה נקבע על ידי ה-framework.

קוד שמופיע בדוחות קריסות

דוח הקריסות הוא מקום אחד שבו הקבצים האלה לא מוצגים יותר. ככותבים, תוכלו לראות עכשיו דוחות קריסות רלוונטיים יותר.

צילום מסך של דוח הקריסות בכלי הפיתוח.

כדי לראות את כל מסגרות הקריאה של דוח הקריסות, תמיד אפשר ללחוץ על הקישור הצגת מסגרות נוספות.

אותו עיקרון חל על מקבצים של שיחות שמוצגים בזמן ניפוי באגים וניווט בקוד. כש-frameworks או Bundles מיידעים את כלי הפיתוח לגבי סקריפטים של צד שלישי, כלי הפיתוח מסתיר באופן אוטומטי את כל מסגרות הקריאה הלא רלוונטיות ועובר מעל קוד שמופיע ברשימה להתעלמות במהלך ניפוי הבאגים.

צילום מסך של הכלי לניפוי באגים במקורות של כלי הפיתוח בזמן ניפוי באגים.

קוד שמופיע בעץ הקבצים שהמערכת מתעלמת ממנו

כדי להסתיר את הקבצים והתיקיות מהרשימה להתעלמות מעץ הקבצים קוד שנוצר בחלונית מקורות, מסמנים את הסתרת הקוד שמופיע ברשימת קטעי הקוד להתעלמות בתצוגת עץ המקורות בהגדרות > ניסויים בכלי הפיתוח.

צילום מסך של הגדרות כלי הפיתוח.

בפרויקט Angular לדוגמה, התיקיות node_modules ו-webpack מוסתרות עכשיו.

צילום מסך של עץ הקבצים בכלי הפיתוח ל-Chrome שבו מוצג הקוד הרשום, אבל לא מוצגים מודולים שלNode_Module.

קוד שמופיע ברשימה להתעלמות בתפריט 'פתיחה מהירה'

הקוד שהמערכת מתעלמת ממנו לא מוסתר רק בעץ הקבצים, אלא גם מוסתר מהתפריט 'פתיחה מהירה' (Control+P (Linux/Windows) או Command+P (Mac)).

צילום מסך של כלי הפיתוח עם התפריט 'פתיחה מהירה'.

שיפורים נוספים בדוחות הקריסות

אחרי הדיווחים רלוונטיים של דוחות הקריסה הרלוונטיים, כלי הפיתוח ל-Chrome כולל שיפורים נוספים לדוחות הקריסות.

דוחות קריסות מקושרים

כרגע, כשפעולות מסוימות מתוזמנות להתבצע באופן אסינכרוני, דוחות הקריסות בכלי הפיתוח מספרים רק חלק מהסיפור.

לדוגמה, הנה תזמון פשוט מאוד בקובץ 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();

... ואיך המפתח יכול להשתמש בו בקוד שלו בקובץ example.js:

function someTask() {
  console.trace("done!");
}

function businessLogic() {
  scheduler.schedule(someTask);
}

businessLogic();

כשמוסיפים נקודת עצירה (breakpoint) בתוך ה-method someTask או כשבודקים את נתוני המעקב שהודפסו במסוף, לא מופיע אזכור של הקריאה businessLogic() שהייתה 'שורש הבעיה' של הפעולה הזו.

במקום זאת, אתם רואים רק את הלוגיקה של תזמון ה-framework שהובילה לביצוע של המשימה, ללא נתיבי ניווט בדוח הקריסות, שעוזרים לכם להבין את הקשרים הסיבתיים בין האירועים שהובילו למשימה הזו.

דוח קריסות של קוד ביצוע אסינכרוני בלי מידע על המועד שבו הוא תוזמן.

בזכות התכונה החדשה שנקראת "תיוג ערימה אסינכרוני", אפשר לספר את כל הסיפור על ידי קישור בין שני החלקים של הקוד האסינכרוני.

ה-API Async Stack Tagging API כולל שיטת console חדשה בשם console.createTask(). זו החתימה של ה-API:

interface Console {
  createTask(name: string): Task;
}

interface Task {
  run<T>(f: () => T): T;
}

הקריאה console.createTask() מחזירה מכונה Task שאפשר להשתמש בה בהמשך כדי להריץ את תוכן המשימה f.

// Task Creation
const task = console.createTask(name);

// Task Execution
task.run(f);

המשימה יוצרת את הקישור בין ההקשר שבו היא נוצרה לבין ההקשר של הפונקציה האסינכרונית שמופעלת.

אם מחילים את הפונקציה makeScheduler שלמעלה, הקוד הופך להיות הבא:

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();
      }
    },
  };
}

בזכות זה, כלי הפיתוח ל-Chrome יכולים להציג דוח קריסות טוב יותר.

דוח קריסות של קוד ביצוע אסינכרוני עם מידע לגבי המועד שבו הוא תוזמן.

כדאי לראות איך הדוח businessLogic() נכלל עכשיו בדוח הקריסות. מלבד זאת, למשימה יש שם מוכר someTask במקום requestAnimationFrame כללי כמו קודם.

מסגרות שיחה ידידותיות

לעיתים קרובות, מסגרות יוצרות קוד מכל מיני שפות ליצירת תבניות בזמן בניית פרויקט, כמו תבניות Angular או JSX שהופכות קוד שנראה ל-HTML ל-JavaScript פשוט שרץ בסופו של דבר בדפדפן. לפעמים לפונקציות שנוצרות האפשרויות האלה יש שמות לא ידידותיים במיוחד – שמות של אות אחת אחרי מוקטנות או שמות מעורפלים או לא מוכרים גם אם הן לא שם.

בפרויקט לדוגמה, הדוגמה הזו היא AppComponent_Template_app_button_handleClick_1_listener, שמופיעה בדוח הקריסות.

צילום מסך של דוח הקריסות עם שם הפונקציה שנוצר באופן אוטומטי.

כדי לפתור את הבעיה, כלי הפיתוח ל-Chrome תומכים עכשיו בשינוי השם של הפונקציות האלה באמצעות מפות מקור. אם מפת מקור כוללת שם להתחלת היקף של פונקציה, השם הזה אמור להופיע במסגרת הקריאה בדוח הקריסות.

ככותבים, לא צריך לעשות דבר כדי לאפשר את ההתנהגות החדשה הזו. יישום השינוי הזה נקבע על ידי ה-framework.

במבט קדימה

הודות לתוספות שמתוארות בפוסט הזה, כלי הפיתוח ל-Chrome יכולים להציע לכם חוויית ניפוי באגים טובה יותר. יש עוד תחומים שהצוות רוצה לחקור. באופן ספציפי, איך לשפר את חוויית הפרופיילינג בכלי הפיתוח.

הצוות של כלי הפיתוח ל-Chrome מעודד את מחברי ה-framework לאמץ את היכולות החדשות האלה. במאמר מקרה לדוגמה: Better Angular Debugging with DevTools תוכלו למצוא הנחיות איך ליישם את זה.