مطالعه موردی: اشکال زدایی زاویه ای بهتر با DevTools

یک تجربه رفع اشکال بهبود یافته

طی چند ماه گذشته، تیم Chrome DevTools با تیم Angular همکاری کرد تا تجربه اشکال‌زدایی را در Chrome DevTools بهبود بخشد. افراد هر دو تیم با هم کار کردند و گام‌هایی برداشتند تا توسعه‌دهندگان را قادر به اشکال‌زدایی و نمایه‌سازی اپلیکیشن‌های وب از منظر نویسندگی کنند : از نظر زبان مبدأ و ساختار پروژه، با دسترسی به اطلاعاتی که برای آنها آشنا و مرتبط است.

این پست نگاهی به زیر می‌اندازد تا ببیند برای رسیدن به این هدف، چه تغییراتی در Angular و Chrome DevTools لازم است. اگرچه برخی از این تغییرات از طریق Angular نشان داده می شوند، اما می توان آنها را در سایر فریم ورک ها نیز اعمال کرد. تیم Chrome DevTools سایر چارچوب‌ها را تشویق می‌کند تا APIهای کنسول جدید و نقاط افزونه نقشه منبع را اتخاذ کنند تا آنها نیز بتوانند تجربه اشکال‌زدایی بهتری را به کاربران خود ارائه دهند.

کد فهرست بندی را نادیده بگیرید

هنگام اشکال‌زدایی برنامه‌ها با استفاده از Chrome DevTools، نویسندگان معمولاً فقط می‌خواهند فقط کد آنها را ببینند، نه چارچوب زیر یا برخی وابستگی‌ها را که در پوشه node_modules پنهان شده است.

برای رسیدن به این هدف، تیم DevTools افزونه‌ای را برای نقشه‌های منبع معرفی کرده است که x_google_ignoreList نام دارد. این برنامه افزودنی برای شناسایی منابع شخص ثالث مانند کد چارچوب یا کد تولید شده توسط بسته‌کننده استفاده می‌شود. وقتی چارچوبی از این پسوند استفاده می‌کند، نویسندگان اکنون به‌طور خودکار از کدهایی که نمی‌خواهند ببینند یا از آن عبور کنند ، بدون نیاز به پیکربندی دستی از قبل، اجتناب می‌کنند.

در عمل، Chrome DevTools می‌تواند به‌طور خودکار کدهای شناسایی شده را در ردیابی پشته، درخت منابع، گفتگوی باز سریع پنهان کند و همچنین رفتار گام‌گذاری و از سرگیری را در اشکال‌زدا بهبود بخشد.

یک GIF متحرک که DevTools را قبل و بعد نشان می دهد. توجه داشته باشید که چگونه در تصویر بعدی DevTools کد نوشته شده را در درخت نشان می‌دهد، دیگر هیچ یک از فایل‌های فریمورک را در منوی «باز کردن سریع» پیشنهاد نمی‌کند، و یک ردپای پشته بسیار تمیزتر را در سمت راست نشان می‌دهد.

پسوند نقشه منبع x_google_ignoreList

در نقشه‌های منبع، فیلد x_google_ignoreList جدید به آرایه sources اشاره دارد و شاخص‌های همه منابع شناخته شده شخص ثالث را در آن نقشه منبع فهرست می‌کند. هنگام تجزیه نقشه منبع، Chrome DevTools از این مورد استفاده می کند تا بفهمد کدام بخش از کد باید نادیده گرفته شود.

در زیر یک نقشه منبع برای یک فایل out.js تولید شده است. دو sources اصلی وجود دارد که به تولید فایل خروجی کمک کرده‌اند: foo.js و lib.js اولی چیزی است که یک توسعه دهنده وب سایت نوشته است و دومی چارچوبی است که آنها استفاده می کنند.

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

sourcesContent برای هر دوی این منابع اصلی گنجانده شده است و Chrome DevTools این فایل‌ها را به‌طور پیش‌فرض در سراسر Debugger نمایش می‌دهد:

  • به عنوان فایل در درخت Sources.
  • به عنوان نتیجه در گفتگوی باز سریع.
  • به عنوان مکان‌های فریم تماس نگاشت شده در خطا، ردیابی‌ها را در حین مکث در نقطه توقف و در حین پله‌گذاری، پشته می‌کنند.

یک اطلاعات اضافی وجود دارد که اکنون می تواند در نقشه های منبع گنجانده شود تا مشخص شود کدام یک از آن منابع کد اول یا شخص ثالث است:

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

فیلد جدید x_google_ignoreList حاوی یک فهرست واحد است که به آرایه sources اشاره دارد: 1. این مشخص می کند که مناطق نگاشت شده به lib.js در واقع کد شخص ثالثی هستند که باید به طور خودکار به لیست نادیده گرفته شوند.

در مثال پیچیده‌تر، که در زیر نشان داده شده است، شاخص‌های 2، 4 و 5 مشخص می‌کنند که مناطق نگاشت شده به lib1.ts ، lib2.coffee ، و hmr.js همگی کدهای شخص ثالثی هستند که باید به‌طور خودکار به فهرست نادیده گرفته شوند.

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

اگر یک توسعه‌دهنده فریم‌ورک یا بسته‌بندی هستید، مطمئن شوید که نقشه‌های منبع تولید شده در طول فرآیند ساخت شامل این فیلد می‌شوند تا به این قابلیت‌های جدید در ابزار توسعه کروم متصل شوید.

x_google_ignoreList در Angular

از Angular نسخه 14.1.0 ، محتویات node_modules و پوشه‌های webpack به‌عنوان «نادیده‌گرفتن» علامت‌گذاری شده‌اند.

این از طریق تغییر در angular-cli با ایجاد یک افزونه که به ماژول Compiler وب پک متصل می‌شود به دست آمد.

افزونه بسته وب که مهندسان ما ایجاد کرده‌اند، به مرحله PROCESS_ASSETS_STAGE_DEV_TOOLING متصل می‌شود و قسمت x_google_ignoreList را در نقشه‌های منبع برای دارایی‌های نهایی که بسته وب تولید می‌کند و مرورگر بارگیری می‌کند، پر می‌کند.

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)));

ردیابی پشته پیوند داده شده

ردپای پشته به این سوال پاسخ می دهد که «چگونه به اینجا رسیدم» ، اما اغلب این از منظر دستگاه است و لزوماً چیزی نیست که با دیدگاه توسعه دهنده یا مدل ذهنی آنها از زمان اجرای برنامه مطابقت داشته باشد. این امر به ویژه زمانی صادق است که برخی از عملیات‌ها قرار است بعداً به‌صورت ناهمزمان انجام شوند: هنوز هم می‌تواند جالب باشد که «علت ریشه‌ای» یا سمت زمان‌بندی چنین عملیاتی را بدانید، اما این دقیقاً چیزی است که بخشی از یک ردیابی پشته ناهمزمان نخواهد بود.

V8 در داخل دارای مکانیزمی برای ردیابی چنین کارهای ناهمزمانی است که از برنامه‌های اولیه زمان‌بندی مرورگر استاندارد استفاده می‌شود، مانند setTimeout . این به طور پیش فرض در آن موارد انجام می شود، بنابراین توسعه دهندگان می توانند از قبل این موارد را بررسی کنند! اما در پروژه‌های پیچیده‌تر، به این سادگی نیست، به‌ویژه زمانی که از چارچوبی با مکانیسم‌های زمان‌بندی پیشرفته‌تر استفاده می‌شود - برای مثال، چارچوبی که ردیابی منطقه، صف‌بندی وظایف سفارشی را انجام می‌دهد، یا به‌روزرسانی‌ها را به چندین واحد از کار تقسیم می‌کند. زمان.

برای رفع این مشکل، DevTools مکانیزمی به نام «Async Stack Tagging API» را در شی console نشان می‌دهد، که به توسعه‌دهندگان فریم‌ورک امکان می‌دهد هم مکان‌هایی را که عملیات‌ها برنامه‌ریزی می‌شوند و هم به مکان‌هایی که این عملیات اجرا می‌شوند اشاره کنند.

Async Stack Tagging API

بدون Async Stack Tagging، ردیابی‌های پشته‌ای برای کدهایی که به‌صورت ناهمزمان به روش‌های پیچیده توسط فریم‌ورک‌ها اجرا می‌شوند، بدون اتصال به کدی که برنامه‌ریزی شده بود، نشان داده می‌شوند.

ردیابی پشته ای از برخی کدهای غیرهمگام اجرا شده بدون هیچ اطلاعاتی درباره زمان برنامه ریزی آن. فقط ردیابی پشته را نشان می دهد که از «requestAnimationFrame» شروع می شود، اما هیچ اطلاعاتی از زمان برنامه ریزی آن در خود ندارد.

با Async Stack Tagging می توان این زمینه را فراهم کرد و stack trace به شکل زیر است:

ردیابی پشته ای از برخی کدهای غیرهمگام اجرا شده با اطلاعات مربوط به زمان برنامه ریزی آن. توجه داشته باشید که برخلاف قبل، «businessLogic» و «زمان‌بندی» را در ردیابی پشته شامل می‌شود.

برای رسیدن به این هدف، از یک روش console جدید به نام console.createTask() استفاده کنید که Async Stack Tagging API ارائه می کند. امضای آن به شرح زیر است:

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

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

فراخوانی console.createTask() یک نمونه Task را برمی گرداند که بعداً می توانید از آن برای اجرای کد async استفاده کنید.

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

// Task Execution
task.run(f);

عملیات ناهمزمان همچنین می تواند تودرتو باشد و "علل ریشه" به ترتیب در ردیابی پشته نمایش داده می شود.

وظایف را می توان هر تعداد بار اجرا کرد و بار کار می تواند بین هر اجرا متفاوت باشد. پشته تماس در سایت زمان‌بندی تا زمانی که شیء وظیفه جمع‌آوری شود، به خاطر سپرده می‌شود.

Async Stack Tagging API در Angular

در Angular، تغییراتی در NgZone ایجاد شده است - زمینه اجرای Angular که در تمام وظایف غیر همگام باقی می ماند.

هنگام برنامه ریزی یک کار، در صورت موجود بودن، از console.createTask() استفاده می کند. نمونه Task به دست آمده برای استفاده بیشتر ذخیره می شود. پس از فراخوانی وظیفه، NgZone از نمونه Task ذخیره شده برای اجرای آن استفاده می کند.

این تغییرات در NgZone 0.11.8 Angular از طریق درخواست‌های کشش #46693 و #46958 وارد شدند.

فریم های تماس دوستانه

فریم‌ورک‌ها معمولاً هنگام ساخت یک پروژه کد را از انواع زبان‌های قالب تولید می‌کنند، مانند قالب‌های Angular یا JSX که کدهای HTML را به جاوا اسکریپت ساده تبدیل می‌کنند که در نهایت در مرورگر اجرا می‌شود. گاهی اوقات، به این نوع توابع تولید شده نام‌هایی داده می‌شود که چندان دوستانه نیستند - یا نام‌های تک حرفی پس از کوچک‌سازی یا برخی نام‌های مبهم یا ناآشنا حتی زمانی که نیستند.

در Angular دیدن فریم های تماس با نام هایی مانند AppComponent_Template_app_button_handleClick_1_listener در ردیابی های پشته غیر معمول نیست.

تصویری از ردیابی پشته با نام تابعی که به صورت خودکار تولید می شود.

برای رفع این مشکل، Chrome DevTools اکنون از تغییر نام این توابع از طریق نقشه های منبع پشتیبانی می کند. اگر نقشه منبع یک ورودی نام برای شروع محدوده تابع (یعنی قسمت چپ لیست پارامترها) داشته باشد، فریم تماس باید آن نام را در ردیابی پشته نمایش دهد.

فریم های تماس دوستانه در انگولار

تغییر نام فریم های تماس در Angular یک تلاش مداوم است. ما انتظار داریم که این پیشرفت‌ها به تدریج در طول زمان انجام شود.

در حین تجزیه قالب های HTML که نویسندگان نوشته اند، کامپایلر Angular کد TypeScript را تولید می کند که در نهایت به کد جاوا اسکریپت تبدیل می شود که مرورگر بارگیری و اجرا می کند.

به عنوان بخشی از این فرآیند تولید کد، نقشه های منبع نیز ایجاد می شوند. ما در حال حاضر در حال بررسی راه هایی برای گنجاندن نام توابع در قسمت "نام" نقشه های منبع، و ارجاع آن نام ها در نگاشت بین کد تولید شده و کد اصلی هستیم.

به عنوان مثال، اگر تابعی برای شنونده رویداد ایجاد شود و نام آن غیردوستانه باشد یا در حین کوچک‌سازی حذف شود، نقشه‌های منبع اکنون می‌توانند نام دوستانه‌تر برای این تابع را در قسمت «نام‌ها» و نقشه‌برداری برای ابتدای تابع قرار دهند. scope اکنون می تواند به این نام (یعنی قسمت چپ لیست پارامترها) اشاره کند. Chrome DevTools سپس از این نام‌ها برای تغییر نام فریم‌های تماس در ردیابی پشته استفاده می‌کند.

با نگاه به آینده

استفاده از Angular به عنوان یک آزمایشی آزمایشی برای تأیید کار ما یک تجربه فوق العاده بوده است. ما دوست داریم از توسعه دهندگان فریمورک بشنویم و بازخورد خود را در مورد این نقاط توسعه ارائه دهند .

مناطق بیشتری وجود دارد که ما می خواهیم آنها را بررسی کنیم. به طور خاص، نحوه بهبود تجربه پروفایل در DevTools.