Örnek Olay: Geliştirici Araçları ile Daha İyi Angular Hata Ayıklama

Geliştirilmiş hata ayıklama deneyimi

Chrome Geliştirici Araçları ekibi, son birkaç aydır Chrome Geliştirici Araçları'ndaki hata ayıklama deneyiminde iyileştirmeler yapmak için Angular ekibiyle birlikte çalıştı. Her iki ekipten de ekip, geliştiricilerin, kaynak dil ve proje yapıları açısından, kendilerine alışık oldukları ve alakalı bilgilere erişim ile web uygulamalarındaki hataları yazma bakış açısıyla, hata ayıklama ve profil oluşturma imkanı sağlamak için gerekli adımları attı.

Bu gönderide, bu hedefe ulaşmak için Angular ve Chrome Geliştirici Araçları'nda hangi değişikliklerin gerekli olduğunu görmek üzere konuyu ayrıntılı olarak ele alıyoruz. Bu değişikliklerin bazıları Angular üzerinden gösterilse de diğer çerçevelere de uygulanabilir. Chrome Geliştirici Araçları ekibi, kullanıcılarına daha iyi bir hata ayıklama deneyimi sunabilmeleri için diğer çerçeveleri de yeni konsol API'lerini ve kaynak harita uzantı noktalarını benimsemeye teşvik etmektedir.

Liste dışı bırakma kodu

Chrome Geliştirici Araçları'nı kullanarak uygulamalarda hata ayıklama yapan yazarlar genellikle alttaki çerçevenin veya node_modules klasöründe gizlenmiş bazı bağımlılıkların kodunu değil, yalnızca kendi kodlarını görmek ister.

Bu hedefe ulaşmak için DevTools ekibi, kaynak haritalar için x_google_ignoreList adlı bir uzantı kullanıma sundu. Bu uzantı, çerçeve kodu veya paketleyici tarafından oluşturulan kod gibi üçüncü taraf kaynaklarını tanımlamak için kullanılır. Bir çerçeve bu uzantıyı kullandığında, yazarlar artık önceden manuel olarak yapılandırmak zorunda kalmadan görmek veya adım adım uygulamak istemedikleri kodlardan otomatik olarak kaçınıyor.

Chrome Geliştirici Araçları pratikte yığın izlemelerde, Kaynaklar ağacında, Hızlı Aç iletişim kutusunda tanımlanan kodları otomatik olarak gizleyebilir ve hata ayıklayıcıdaki adım atma ve devam ettirme davranışını iyileştirebilir.

DevTools'un öncesini ve sonrasını gösteren animasyonlu GIF. Resimden sonraki resimde, Geliştirici Araçları'nın ağaçta Yazılan Kodun nasıl gösterildiğini, "Hızlı Aç" menüsündeki çerçeve dosyalarının hiçbirini artık önermediğini ve sağda daha temiz bir yığın izleme gösterdiğini unutmayın.

x_google_ignoreList kaynak eşleme uzantısı

Kaynak eşlemelerinde yeni x_google_ignoreList alanı, sources dizisini ifade eder ve ilgili kaynak haritasındaki bilinen tüm üçüncü taraf kaynaklarının dizinlerini listeler. Kaynak haritasını ayrıştırırken Chrome Geliştirici Araçları, kodun hangi bölümlerinin yoksayılacaklar listesine ekleneceğini belirlemek için bu değeri kullanır.

Oluşturulan out.js dosyasının kaynak haritası aşağıda verilmiştir. Çıkış dosyasının oluşturulmasına katkıda bulunan iki orijinal sources vardır: foo.js ve lib.js. İlki, bir web sitesi geliştiricisinin yazdığı bir şeydir ve ikincisi, kullandıkları bir çerçevedir.

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

sourcesContent, bu orijinal kaynakların her ikisi için de dahil edilir ve Chrome Geliştirici Araçları bu dosyaları varsayılan olarak hata ayıklayıcıda gösterir:

  • Kaynaklar ağacında dosya olarak.
  • Hızlı Aç iletişim kutusunda gösterilir.
  • Bir durak noktasında duraklatıldığında ve adım atıldığında hata yığın izlemelerinde eşlenen çağrı çerçevesi konumları.

Artık kaynak haritalara, bu kaynaklardan hangisinin birinci taraf kodu, hangisinin üçüncü taraf kodu olduğunu belirlemek için ek bir bilgi eklenebilir:

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

Yeni x_google_ignoreList alanı, sources dizisine atıfta bulunan tek bir dizin içerir: 1. Bu, lib.js ile eşlenen bölgelerin aslında yoksayılanlar listesine otomatik olarak eklenmesi gereken üçüncü taraf kodu olduğunu belirtir.

Aşağıda gösterilen daha karmaşık bir örnekte, 2, 4 ve 5 dizinleri, lib1.ts, lib2.coffee ve hmr.js ile eşlenen bölgelerin hepsinin, yoksayma listesine otomatik olarak eklenmesi gereken üçüncü taraf kodu olduğunu belirtir.

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

Bir çerçeve veya paketleyici geliştiriciyseniz Chrome DevTools'taki bu yeni özellikleri kullanabilmek için derleme işlemi sırasında oluşturulan kaynak eşlemelerinin bu alanı içerdiğinden emin olun.

Açısal x_google_ignoreList

Angular 14.1.0 sürümü itibarıyla node_modules ve webpack klasörlerinin içeriği "yoksayılacak" olarak işaretlendi.

Bu, webpack'ın Compiler modülüne bağlanan bir eklenti oluşturarak angular-cli'da yapılan bir değişiklik sayesinde başarıldı.

Mühendislerimizin oluşturduğu web paketi eklentisi, PROCESS_ASSETS_STAGE_DEV_TOOLING aşamasına kancalar oluşturur ve web paketinin oluşturduğu ve tarayıcının yüklediği nihai öğeler için kaynak haritalarındaki x_google_ignoreList alanını doldurur.

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

Bağlı yığın izlemeler

Yığın izlemeleri, "Buraya nasıl geldim?" sorusunu yanıtlar. Ancak bu genellikle makinenin bakış açısından yanıtlanır ve geliştiricinin bakış açısıyla veya uygulama çalışma zamanına dair zihinsel modeliyle eşleşmeyebilir. Bu durum özellikle bazı işlemlerin daha sonra eşzamansız olarak gerçekleşmesi planlandığında geçerlidir: Bu tür işlemlerin "temel nedenini" veya planlama yönünü bilmek yine de ilginç olabilir, ancak bu tam olarak eşzamansız yığın izlemenin bir parçası olmayacak bir şeydir.

V8, setTimeout gibi standart tarayıcı planlama ilkelleri kullanıldığında bu tür eşzamansız görevleri takip etmek için dahili bir mekanizmaya sahiptir. Bu işlem, bu durumlarda varsayılan olarak yapılır. Böylece geliştiriciler bu verileri zaten inceleyebilir. Ancak daha karmaşık projelerde bu kadar basit değildir. Özellikle de daha gelişmiş zaman çizelgesi oluşturma mekanizmalarına sahip bir çerçeve kullanırken (ör. bölge takibi, özel görev sıraya alma veya güncellemeleri zaman içinde yürütülen birkaç çalışma birimine bölen bir çerçeve) kullanmak bu kadar basit değildir.

Bu sorunu gidermek için DevTools, console nesnesinde "Asenkron Yığın Etiketleme API'si" adlı bir mekanizma sunar. Bu mekanizma, çerçeve geliştiricilerin hem işlemlerin planlandığı hem de bu işlemlerin yürütüldüğü konumları belirtmesine olanak tanır.

Eş Zamansız Yığın Etiketleme API'si

Asynkron yığın etiketleme olmadan, çerçeveler tarafından karmaşık şekillerde eşzamansız olarak yürütülen kodun yığın izlemeleri, planlandığı kodla bağlantısı olmadan gösterilir.

Ne zaman planlandığıyla ilgili bilgi içermeyen, bazı asynkron olarak yürütülen kodun yığın izlemesi. Yığın izleme (stack trace) yalnızca "requestAnimationFrame" değerinden itibaren gösterilir ancak planlandığı zamana ait bilgi içermez.

Eş zamansız yığın etiketleme ile bu bağlamı sağlamak mümkündür ve yığın izleme şöyle görünür:

Planlandığı zamanla ilgili bilgiler içeren, bazı asynkron olarak yürütülen kodun yığın izlemesi. Öncekinden farklı olarak yığın izlemeye "businessLogic" ve "schedule" ekleyin.

Bunun için Eş Zamansız Yığın Etiketleme API'sinin sağladığı console.createTask() adlı yeni bir console yöntemini kullanın. İmzası aşağıdaki gibidir:

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

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

console.createTask() çağrısı yapıldığında, daha sonra eşzamansız kodu çalıştırmak için kullanabileceğiniz bir Task örneği döndürülür.

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

// Task Execution
task.run(f);

Eşzamansız işlemler iç içe yerleştirilebilir ve "temel nedenler" yığın izlemede sırayla gösterilir.

Görevler istediğiniz sayıda çalıştırılabilir ve çalışma yükü her çalıştırma arasında farklılık gösterebilir. Görev nesnesi çöp toplanana kadar planlama sitesindeki çağrı yığını hatırlanır.

Angular'da Async Stack Tagging API

Angular'da, Angular'ın asenkron görevler arasında devam eden yürütme bağlamı olan NgZone'da değişiklikler yapıldı.

Görev planlarken, mümkün olduğunda console.createTask() kullanılır. Elde edilen Task örneği daha sonra kullanılmak üzere saklanır. NgZone, görev çağrıldıktan sonra çalıştırmak için saklanan Task örneğini kullanır.

Bu değişiklikler, #46693 ve #46958 çekme istekleriyle Angular'ın NgZone 0.11.8 sürümüne eklendi.

Dostluk Görüşmesi Çerçeveleri

Çerçeveler, proje oluştururken genellikle her türlü şablonlama dilinden kod oluşturur. Örneğin, HTML benzeri kodu tarayıcıda çalışacak basit JavaScript'e dönüştüren Angular veya JSX şablonları. Bazen bu tür oluşturulan işlevlere çok kullanışlı olmayan isimler verilir. Bu isimler, sıkıştırıldıktan sonra tek harfli isimler veya sıkıştırılmamış olsalar bile belirsiz ya da tanıdık olmayan isimler olabilir.

Angular'da yığın izlemelerinde AppComponent_Template_app_button_handleClick_1_listener gibi adlara sahip çağrı çerçeveleri görmek yaygındır.

Otomatik olarak oluşturulmuş bir işlev adının yer aldığı yığın izleme ekran görüntüsü.

Bu sorunu gidermek için Chrome DevTools artık kaynak haritalar aracılığıyla bu işlevlerin yeniden adlandırılmasını desteklemektedir. Bir kaynak haritasında işlev kapsamının başlangıcı (yani parametre listesinin sol parantezi) için bir ad girişi varsa çağrı çerçevesi, yığın izlemede bu adı göstermelidir.

Angular'da Kullanıcı Dostu Arama Çerçeveleri

Angular'da arama çerçevelerini yeniden adlandırmak sürekli bir çalışmadır. Bu iyileştirmelerin zaman içinde kademeli olarak kullanıma sunulmasını bekliyoruz.

Yazarların yazdığı HTML şablonlarını ayrıştırırken, Angular derleyicisi TypeScript kodu oluşturur. Bu kod sonunda tarayıcının yüklediği ve çalıştırdığı JavaScript koduna dönüştürülür.

Bu kod oluşturma süreci kapsamında kaynak haritalar da oluşturulur. Şu anda kaynak haritalarının "adlar" alanına işlev adlarını ekleme ve oluşturulan kod ile orijinal kod arasındaki eşlemelerde bu adlara referans verme yollarını araştırıyoruz.

Örneğin, bir etkinlik dinleyicisi için bir işlev oluşturulur ve adı, sıkıştırma sırasında kullanıcı dostu değilse veya kaldırılırsa kaynak haritalar artık "adlar" alanına bu işlevin daha kullanıcı dostu adını dahil edebilir ve işlev kapsamının başlangıcı için eşleme artık bu ada (yani parametre listesinin sol parantezine) atıfta bulunabilir. Chrome Geliştirici Araçları, yığın izlemelerindeki çağrı çerçevelerini yeniden adlandırmak için bu adları kullanır.

Geleceğe dönük olarak

Çalışmalarımızı doğrulamak için Angular'ı test pilotu olarak kullanmak harika bir deneyim oldu. Çerçeve geliştiricilerden bu uzantı noktaları hakkında geri bildirim almaktan memnuniyet duyarız.

Keşfetmek istediğimiz daha fazla alan var. Özellikle de DevTools'daki profil oluşturma deneyimini iyileştirme.