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

Daha iyi bir hata ayıklama deneyimi

Geçtiğimiz birkaç ay boyunca Chrome Geliştirici Araçları ekibi, Chrome Geliştirici Araçları'ndaki hata ayıklama deneyiminde iyileştirmeler yapmak için Angular ekibiyle işbirliği yaptı. İki ekip de birlikte çalışarak geliştiricilerin, kaynak dil ve proje yapıları bakımından, yazma bakış açısıyla hata ayıklama ve web uygulamaları profili çıkarmasını sağlamak ve kendileri için aşina oldukları ve alakalı bilgilere erişim sağlamak adına gerekli adımları attı.

Bu gönderide, bunu elde etmek için Angular ve Chrome Geliştirici Araçları'nda hangi değişikliklerin yapılması gerektiğini görmek üzere arka plan bilgileri incelenmektedir. 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.

Yoksayılanlar listesine ekleme kodu

Chrome Geliştirici Araçları'nı kullanarak uygulamalarda hata ayıklarken yazarlar genellikle sadece yalnızca kendi kodlarını görmek ister. Alttaki çerçeveyi veya node_modules klasöründe gizlenmiş bir bağımlılığı görmek istemezler.

Geliştirici Araçları ekibi, bunu başarmak için kaynak haritalar için x_google_ignoreList adlı bir uzantıyı kullanıma sundu. Bu uzantı, çerçeve kodu veya paketleyici tarafından oluşturulan kod gibi üçüncü taraf kaynakları 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.

Geliştirici Araçları'nın öncesinde ve sonrasında gösterildiği animasyonlu GIF. Resimden sonraki resimde, Geliştirici Araçları'nın ağaçta Yazılmış Kodun nasıl göründüğünü, "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 dizisine başvurur ve ilgili kaynak haritasındaki bilinen tüm üçüncü taraf kaynaklarının dizinlerini listeler. Chrome Geliştirici Araçları, kaynak haritayı ayrıştırırken kodun hangi bölümlerinin yoksayılanlar listesine eklenmesi gerektiğini belirlemek için bunu kullanır.

Aşağıda, oluşturulmuş out.js dosyasının kaynak haritasını bulabilirsiniz. Çıkış dosyasının oluşturulmasına katkıda bulunan iki orijinal sources vardır: foo.js ve lib.js. Birincisi, bir web sitesi geliştiricisinin yazdığı bir şey, ikincisi ise kullandığı 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ındaki dosyalar olarak.
  • Hızlı Aç iletişim kutusunda sonuç olarak.
  • Bir ayrılma noktasında duraklatılmış durumdayken ve adım adım ilerlerken hata yığın izlemelerindeki eşlenmiş çağrı çerçevesi konumları.

Bu kaynaklardan hangilerinin birinci taraf veya üçüncü taraf kod olduğunu belirlemek için artık kaynak haritalarına dahil edilebilecek bir ek bilgi daha vardır:

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

Yeni x_google_ignoreList alanı, sources dizisine referans veren 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 yoksayılanlar listesine otomatik olarak eklenmesi gereken üçüncü taraf kodları olduğunu belirtir.

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

Çerçeve veya paketleyici geliştiricisiyseniz, Chrome Geliştirici Araçları'ndaki bu yeni özelliklerden yararlanmak için derleme işlemi sırasında oluşturulan kaynak haritalarının 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şaretlenmiştir.

Bu, web paketinin Compiler modülüne bağlanan bir eklenti kullanılarak angular-cli üzerinde yapılan bir değişiklikle elde edildi.

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 izleme, “buraya nasıl ulaştım” sorusunu yanıtlar, ancak çoğu zaman bu sorun makinenin bakış açısıyla gerçekleşir ve geliştiricinin bakış açısıyla ya da uygulama çalışma zamanının zihinsel modeliyle uyumlu olmayabilir. Bu durum özellikle bazı işlemler daha sonra eşzamansız olarak gerçekleşecek şekilde planlandığında geçerlidir. Bu tür işlemlerin “kök nedenini” veya planlama tarafını bilmek yine de ilginç olabilir ancak bu tam olarak eşzamansız bir yığın izlemenin parçası olmayacaktır.

V8, setTimeout gibi standart tarayıcı planlama temel öğeleri kullanıldığında bu tür eşzamansız görevleri izlemek için dahili olarak bir mekanizmaya sahiptir. Bu tür durumlarda bu işlem varsayılan olarak yapılır. Böylece geliştiriciler bunları zaten inceleyebilirler. 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.

Geliştirici Araçları, bu sorunu çözmek için console nesnesinde "Async Stack Tagging API" adlı mekanizmayı kullanıma sunar. Bu mekanizma, çerçeve geliştiricilerin hem işlemlerin planlandığı konumlara hem de yürütülecek yerlere dair ipucu verebilmelerini sağlar.

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

Eş zamansız Yığın Etiketleme kullanılmadığında, çerçeveler tarafından eşzamansız olarak yürütülen birçok koda ait yığın izlemeler (stack trace), planlandığı kodla bağlantı olmadan gösterilir.

Ne zaman planlandığıyla ilgili bilgi vermeyen ve eş zamansız olarak yürütülen bazı kodların 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ğlanabilir ve yığın izleme (stack trace) şu şekilde görünür:

Eş zamansız olarak yürütülen bazı kodların yığın izlemesi (stack trace), planlandığı tarihle ilgili bilgiler. Ö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ı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 de iç içe yerleştirilebilir. "Temel nedenler", yığın izlemede sırayla gösterilir.

Görevler istenilen sayıda çalıştırılabilir ve iş yükü her çalıştırma arasında farklılık gösterebilir. Planlama sitesindeki çağrı yığını, görev nesnesi atık toplanana kadar hatırlanır.

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

Angular'da, Angular'ın eşzamansız görevlerde devam eden yürütme bağlamı olan NgZone'da değişiklikler yapıldı.

Bir görev planlanırken mümkün olduğunda console.createTask() kullanılır. Ortaya çıkan Task örneği daha sonra kullanılmak üzere depolanır. Görev çağrıldıktan sonra NgZone, depolanan Task örneğini çalıştırmak için kullanır.

Bu değişiklikler, #46693 ve #46958 çekme istekleri üzerinden Angular'ın NgZone 0.11.8'ine yapıldı.

Samimi Telefon Çerçeveleri

Çerçeveler bir proje oluştururken genellikle her türlü şablon dilinden kod üretir. Örneğin, HTML görünümlü kodu sonunda tarayıcıda çalışan düz JavaScript'e dönüştüren Angular veya JSX şablonları. Bazen bu tür işlevlere çok kolay olmayan adlar verilir. Bu adlar küçültüldükten sonra tek harfli adlar veya küçük olsa bile belirsiz ya da tanıdık olmayan adlar olabilir.

Angular'da, yığın izlemelerde AppComponent_Template_app_button_handleClick_1_listener gibi adlara sahip çağrı çerçeveleri görmek normaldir.

Otomatik olarak oluşturulan bir işlev adını içeren yığın izlemenin ekran görüntüsü.

Chrome Geliştirici Araçları, bu sorunu çözmek için artık kaynak eşlemeleri aracılığıyla bu işlevlerin yeniden adlandırılmasını desteklemektedir. Kaynak eşlemede, işlev kapsamının (parametre listesinin sol parantezi) başlangıcı için ad girişi varsa çağrı çerçevesi, yığın izlemede bu adı göstermelidir.

Angular Dilinde Uygun Telefon Çerçeveleri

Angular'da arama çerçevelerini yeniden adlandırmak sürekli bir çalışmadır. Bu iyileştirmelerin zaman içinde kademeli olarak hayata geçirmesini 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ürecinin bir parçası olarak kaynak eşlemeleri de oluşturulur. Şu anda kaynak haritaların "adlar" alanına işlev adlarını dahil etmenin ve oluşturulan kod ile orijinal kod arasındaki eşlemelerde bu adlara referans vermenin yollarını araştırıyoruz.

Örneğin, bir etkinlik işleyici için işlev oluşturulursa ve bu işlev, küçültme sırasında uygun değilse veya küçültme sırasında kaldırılırsa kaynak eşlemeleri artık "adlar" alanında bu işlevin daha kolay kullanılan adını içerebilir ve işlev kapsamının başlangıcına ait eşleme artık bu ada (parametre listesinin sol parantezine) başvurabilir. Ardından Chrome Geliştirici Araçları, yığın izlemelerdeki çağrı çerçevelerini yeniden adlandırmak için bu adları kullanır.

Geleceğe dönük olarak

Çalışmamızı doğrulamak için Angular'ı test pilot programı olarak kullanmak harika bir deneyim oldu. Çerçeve geliştiricilerinin görüşlerini öğrenmek ve bu uzantı noktalarıyla ilgili geri bildirimlerinizi bizimle paylaşmaktan memnuniyet duyarız.

Keşfetmek istediğimiz başka alanlar da var. Özellikle de Geliştirici Araçları'nda profil oluşturma deneyiminin nasıl iyileştirileceği üzerine konuştuk.