डीबग करने का बेहतर अनुभव
पिछले कुछ महीनों में, Chrome DevTools की टीम ने Angular की टीम के साथ मिलकर काम किया है. इसका मकसद, Chrome DevTools में डीबग करने के अनुभव को बेहतर बनाना था. दोनों टीमों के लोगों ने मिलकर काम किया और डेवलपर को कॉन्टेंट बनाने के नज़रिए से वेब ऐप्लिकेशन को डीबग और प्रोफ़ाइल करने की सुविधा देने के लिए कदम उठाए. इसके लिए, वे डेवलपर के लिए काम की और उनके लिए सही जानकारी का ऐक्सेस देते हैं. यह जानकारी, सोर्स भाषा और प्रोजेक्ट के स्ट्रक्चर के हिसाब से दी जाती है.
इस पोस्ट में, इस बात की जानकारी दी गई है कि Angular और Chrome DevTools में कौनसे बदलाव किए गए थे, ताकि यह सुविधा उपलब्ध कराई जा सके. इनमें से कुछ बदलावों को Angular के ज़रिए दिखाया गया है, लेकिन इन्हें दूसरे फ़्रेमवर्क पर भी लागू किया जा सकता है. Chrome DevTools की टीम, अन्य फ़्रेमवर्क को नए कंसोल एपीआई और सोर्स मैप एक्सटेंशन पॉइंट को अपनाने का सुझाव देती है, ताकि वे भी अपने उपयोगकर्ताओं को डीबग करने का बेहतर अनुभव दे सकें.
अनदेखा किए जाने वाले कोड की सूची
Chrome DevTools का इस्तेमाल करके ऐप्लिकेशन डीबग करते समय, लेखक आम तौर पर सिर्फ़ अपना कोड देखना चाहते हैं, न कि फ़्रेमवर्क या node_modules
फ़ोल्डर में मौजूद किसी डिपेंडेंसी को.
इसे पूरा करने के लिए, DevTools की टीम ने सोर्स मैप के लिए एक एक्सटेंशन लॉन्च किया है. इसे x_google_ignoreList
कहा जाता है. इस एक्सटेंशन का इस्तेमाल, तीसरे पक्ष के सोर्स की पहचान करने के लिए किया जाता है. जैसे, फ़्रेमवर्क कोड या बंडलर से जनरेट किया गया कोड. जब कोई फ़्रेमवर्क इस एक्सटेंशन का इस्तेमाल करता है, तो लेखक अब उस कोड से अपने-आप बच जाते हैं जिसे उन्हें नहीं देखना है या जिसे पहले से मैन्युअल तरीके से कॉन्फ़िगर किए बिना, सिलसिलेवार तरीके से नहीं देखना है.
असल में, Chrome 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, इन फ़ाइलों को डिफ़ॉल्ट रूप से डीबगर में दिखाएगा:
- सोर्स ट्री में फ़ाइलों के तौर पर.
- क्विक ओपन डायलॉग में नतीजों के तौर पर.
- गड़बड़ी के स्टैक ट्रेस में, ब्रेकपॉइंट पर रोके जाने और सिलसिलेवार तरीके से आगे बढ़ने के दौरान, कॉल फ़्रेम की जगहों को मैप किया गया है.
सोर्स मैप में एक और जानकारी शामिल की जा सकती है. इससे यह पता चलता है कि उनमें से कौनसा सोर्स पहले या तीसरे पक्ष का कोड है:
{
...
"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],
...
}
अगर आप फ़्रेमवर्क या बंडलर डेवलपर हैं, तो पक्का करें कि बिल्ड प्रोसेस के दौरान जनरेट किए गए सोर्स मैप में यह फ़ील्ड शामिल हो. इससे, Chrome DevTools में इन नई सुविधाओं का इस्तेमाल किया जा सकेगा.
Angular में x_google_ignoreList
Angular v14.1.0 से, node_modules
और webpack
फ़ोल्डर के कॉन्टेंट को “अनदेखा करें” के तौर पर मार्क किया गया है.
ऐसा angular-cli
में बदलाव करके किया गया. इसके लिए, webpack के Compiler
मॉड्यूल में हुक करने वाला प्लग इन बनाया गया
हमारे इंजीनियरों ने PROCESS_ASSETS_STAGE_DEV_TOOLING
चरण में हुक बनाने के लिए, webpack प्लग इन बनाया है. यह प्लग इन, वेबपैक से जनरेट होने वाली और ब्राउज़र से लोड होने वाली फ़ाइनल ऐसेट के लिए, सोर्स मैप में 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 console
ऑब्जेक्ट पर “Async Stack Tagging API” नाम का एक तरीका दिखाता है. इससे फ़्रेमवर्क डेवलपर, उन जगहों के बारे में बता सकते हैं जहां ऑपरेशन शेड्यूल किए जाते हैं और जहां ये ऑपरेशन लागू किए जाते हैं.
Async Stack Tagging API
असाइन्टेक स्टैक टैगिंग के बिना, फ़्रेमवर्क के ज़रिए असाइन्टेक तरीके से जटिल तरीके से चलाए गए कोड के लिए स्टैक ट्रेस, उस कोड से कोई कनेक्शन नहीं दिखाता जहां इसे शेड्यूल किया गया था.
एक साथ काम नहीं करने वाले स्टैक टैगिंग की मदद से, यह कॉन्टेक्स्ट दिया जा सकता है. स्टैक ट्रेस इस तरह दिखता है:
ऐसा करने के लिए, console.createTask()
नाम के नए console
तरीके का इस्तेमाल करें. यह तरीका, एसिंक्रोनस स्टैक टैगिंग एपीआई उपलब्ध कराता है. इसका हस्ताक्षर इस तरह का है:
interface Console {
createTask(name: string): Task;
}
interface Task {
run<T>(f: () => T): T;
}
console.createTask()
को कॉल करने पर, एक Task
इंस्टेंस मिलता है. इसका इस्तेमाल बाद में, एसिंक्रोनस कोड चलाने के लिए किया जा सकता है.
// Task Creation
const task = console.createTask(name);
// Task Execution
task.run(f);
एसिंक्रोनस ऑपरेशन को नेस्ट भी किया जा सकता है. साथ ही, स्टैक ट्रेस में “मूल वजहें” क्रम से दिखेंगी.
टास्क को जितनी बार चाहें उतनी बार चलाया जा सकता है. साथ ही, हर रन के बीच वर्क पेलोड अलग-अलग हो सकता है. शेड्यूल करने वाली साइट पर कॉल स्टैक तब तक याद रखा जाएगा, जब तक टास्क ऑब्जेक्ट को गै़रबेज कलेक्शन नहीं किया जाता.
Angular में एसिंक्रोनस स्टैक टैगिंग एपीआई
Angular में, NgZone में बदलाव किए गए हैं. यह Angular का एक एक्सीक्यूशन कॉन्टेक्स्ट है, जो असाइन किए गए सभी टास्क के लिए काम करता है.
टास्क शेड्यूल करते समय, उपलब्ध होने पर console.createTask()
का इस्तेमाल किया जाता है. इससे मिलने वाले Task
इंस्टेंस को, आगे इस्तेमाल करने के लिए सेव किया जाता है. टास्क को ट्रिगर करने पर, NgZone उसे चलाने के लिए सेव किए गए Task
इंस्टेंस का इस्तेमाल करेगा.
ये बदलाव, पुल रिक्वेस्ट #46693 और #46958 के ज़रिए, Angular के NgZone 0.11.8 में किए गए हैं.
फ़्रेंडली कॉल फ़्रेम
फ़्रेमवर्क, प्रोजेक्ट बनाते समय अक्सर सभी तरह की टेंप्लेट लैंग्वेज से कोड जनरेट करते हैं. जैसे, Angular या JSX टेंप्लेट, जो एचटीएमएल जैसे दिखने वाले कोड को सामान्य JavaScript में बदल देते हैं. यह कोड, आखिर में ब्राउज़र में चलता है. कभी-कभी, जनरेट किए गए इस तरह के फ़ंक्शन को ऐसे नाम दिए जाते हैं जो आसानी से समझ में नहीं आते. जैसे, छोटा किए जाने के बाद एक अक्षर वाले नाम या ऐसे नाम जो समझ में न आएं या जो आम तौर पर इस्तेमाल न किए जाते हों.
Angular में, स्टैक ट्रेस में AppComponent_Template_app_button_handleClick_1_listener
जैसे नामों वाले कॉल फ़्रेम देखना आम बात है.
इस समस्या को हल करने के लिए, Chrome DevTools में अब सोर्स मैप की मदद से इन फ़ंक्शन के नाम बदले जा सकते हैं. अगर किसी सोर्स मैप में, फ़ंक्शन के स्कोप की शुरुआत के लिए कोई नाम डाला गया है (यानी, पैरामीटर सूची का बायां ब्रैकेट), तो कॉल फ़्रेम को स्टैक ट्रेस में वह नाम दिखाना चाहिए.
Angular में फ़्रेंडली कॉल फ़्रेम
Angular में कॉल फ़्रेम के नाम बदलने की प्रोसेस जारी है. हमें उम्मीद है कि ये सुधार समय के साथ धीरे-धीरे लागू होंगे.
लेखकों के लिखे गए एचटीएमएल टेंप्लेट को पार्स करते समय, Angular कंपाइलर TypeScript कोड जनरेट करता है. इसे आखिर में JavaScript कोड में ट्रांसपाइल किया जाता है, जिसे ब्राउज़र लोड और चलाता है.
कोड जनरेशन की इस प्रोसेस के तहत, सोर्स मैप भी बनाए जाते हैं. फ़िलहाल, हम सोर्स मैप के “names” फ़ील्ड में फ़ंक्शन के नाम शामिल करने के तरीकों को एक्सप्लोर कर रहे हैं. साथ ही, जनरेट किए गए कोड और ओरिजनल कोड के बीच की मैपिंग में उन नामों का रेफ़रंस दे रहे हैं.
उदाहरण के लिए, अगर किसी इवेंट लिसनर के लिए कोई फ़ंक्शन जनरेट किया जाता है और उसका नाम आसान नहीं है या छोटा करने के दौरान हटा दिया गया है, तो सोर्स मैप में अब “names” फ़ील्ड में इस फ़ंक्शन के लिए आसान नाम शामिल किया जा सकता है. साथ ही, फ़ंक्शन के स्कोप की शुरुआत के लिए मैपिंग में अब इस नाम का रेफ़रंस दिया जा सकता है. इसका मतलब है कि पैरामीटर सूची का बायां ब्रैकेट. इसके बाद, Chrome DevTools इन नामों का इस्तेमाल करके, स्टैक ट्रेस में कॉल फ़्रेम का नाम बदल देगा.
आगे की योजना
अपने काम की पुष्टि करने के लिए, टेस्ट पायलट के तौर पर Angular का इस्तेमाल करना एक शानदार अनुभव रहा. हमें फ़्रेमवर्क डेवलपर से सुझाव, राय या शिकायत मिलना पसंद है. साथ ही, इन एक्सटेंशन पॉइंट के बारे में हमें सुझाव/राय दें या शिकायत करें.
हम ऐसे और भी क्षेत्रों को एक्सप्लोर करना चाहते हैं. खास तौर पर, DevTools में प्रोफ़ाइलिंग के अनुभव को बेहतर बनाने का तरीका.