Geliştirici Araçları mimarisi yenileme: Geliştirici Araçları'nı TypeScript'e taşıma

Tim van der Lippe
Tim van der Lippe

Bu gönderi, Geliştirici Araçları mimarisinde yaptığımız değişiklikleri ve nasıl oluşturulduğunu açıklayan bir dizi blog yayınının bir parçasıdır.

JavaScript modüllerine ve Web Bileşenlerine geçiş sürecinin ardından, bugün Devtools'un mimarisinde yaptığımız değişiklikler ve nasıl oluşturulduğu ile ilgili blog yayını dizimize devam ediyoruz. (Daha önce izlemediyseniz DevTools mimarisini modern web'e yükseltme çalışmalarımız hakkında bir video yayınladık. Bu videoda, web projelerinizi nasıl iyileştireceğiniz konusunda 14 ipucu bulabilirsiniz.)

Bu yayında, Closure Derleyici türü denetleyiciden TypeScript'e geçen 13 aylık yolculuğumuzu anlatacağız.

Giriş

DevTools kod tabanının boyutu ve bu kod üzerinde çalışan mühendislere duyulan güvenin artması nedeniyle tür denetleyicisi kullanmak bir zorunluluktur. Bu amaçla DevTools, Closure Compiler aracını 2013'te kullanmaya başladı. Closure'un benimsenmesi, DevTools mühendislerinin değişiklikleri güvenle yapmalarına olanak tanıdı. Closure derleyicisi, tüm sistem entegrasyonlarının doğru yazıldığından emin olmak için tür kontrolleri gerçekleştirir.

Ancak, zaman geçtikçe modern web geliştirmede alternatif tür denetleyiciler popüler hale geldi. TypeScript ve Flow dikkate değer iki örnektir. Dahası, TypeScript Google'da resmi programlama dili haline geldi. Bu yeni tür denetleyicilerin popülerliği artarken, bir tür denetleyici tarafından yakalanması gereken regresyonlar da gönderdiğimizi fark ettik. Bu nedenle, tür denetleyici seçimimizi yeniden değerlendirmeye ve Geliştirici Araçları'ndaki geliştirme sürecinin sonraki adımlarını belirlemeye karar verdik.

Tür denetleyicilerini değerlendirme

DevTools zaten bir tür denetleyici kullandığı için yanıtlamamız gereken soru şuydu:

Closure Compiler'ı kullanmaya devam edecek mi yoksa yeni bir tür denetleyiciye mi geçeceğiz?

Bu soruyu yanıtlamak için tür denetleyicileri birkaç özellikle birlikte değerlendirmemiz gerekti. Tür denetleyicisi kullanımımız mühendisin güvenine odaklandığından, bizim için en önemli özellik tür doğruluğudur. Başka bir deyişle: Tip denetleyicisi gerçek sorunları keşfetmede ne kadar güvenilirdir?

Değerlendirmemiz, gönderdiğimiz regresyonlara ve bunların temel nedenlerinin belirlenmesine odaklandı. Buradaki varsayım, Closure Compiler aracını zaten kullandığımız için Closure'un bu sorunları fark edemeyeceği yönündedir. Dolayısıyla, başka bir tür denetleyicinin bunu yapıp yapamayacağını belirlememiz gerekirdi.

TypeScript'te yazma doğruluğu

TypeScript, Google'da resmi olarak desteklenen bir programlama dili olduğu ve popülerliği hızla arttığı için öncelikle TypeScript'i değerlendirmeye karar verdik. TypeScript ekibi ilginç bir seçim oldu çünkü TypeScript ekibi de JavaScript tür kontrolüyle uyumluluklarını izlemek için test projelerinden biri olarak Geliştirici Araçları'nı kullanıyor. Şirketin referans referans testi çıktısı, TypeScript'in çok sayıda tür sorunu (Closure derleyicisinin algılayamadığı sorunlar) yakaladığını göstermişti. Bu sorunların birçoğu, gönderdiğimiz regresyonların temel nedeni olabilir. Bu da sonuç olarak TypeScript'in Geliştirici Araçları için uygun bir seçenek olabileceğine inanmamızı sağladı.

JavaScript modüllerine geçiş sırasında Closure Compiler'ın öncesine göre daha fazla sorunu ortaya çıkardığını fark etmiştik. Standart bir modül biçimine geçmek, Closure'un kod tabanımızı anlama becerisini ve dolayısıyla tür denetleyicilerin etkinliğini artırdı. Ancak TypeScript ekibi, Geliştirici Araçları'nın JavaScript modüllerinin taşınmasından önce temel bir sürümünü kullanıyordu. Bu nedenle, JavaScript modüllerine geçişin, TypeScript derleyicisinin yakalayacağı hata miktarını da azaltıp azaltmayacağını anlamamız gerekiyordu.

TypeScript'i Değerlendirme

On yıldan uzun süredir var olan DevTools, büyüyerek önemli ölçüde boyutlandırılmış ve çok özellik içeren bir web uygulaması haline gelmiştir. Bu blog yayınının yazıldığı tarihte, DevTools yaklaşık 150.000 birinci taraf JavaScript kodu satırı içeriyordu. Kaynak kodumuzda TypeScript derleyicisini çalıştırdığımızda çok fazla hata çıkıyordu. TypeScript derleyicisi, kod çözünürlüğüyle ilgili daha az hata (yaklaşık 2.000 hata) yayınlarken, kod tabanımızda tür uyumluluğuyla ilgili 6.000 hata daha olduğunu tespit edebildik.

Bu, TypeScript'in türleri nasıl çözeceğini anlayabildiğini, ancak kod tabanımızda önemli miktarda tür uyumsuzluğu tespit ettiğini gösterdi. Bu hataların manuel analizi, TypeScript'in (çoğu zaman) doğru olduğunu göstermiştir. TypeScript'in bunları algılayabilmesinin ve Closure'un nedeni, genellikle Closure derleyicisinin bir türü Any olarak çıkarırken TypeScript'in atamalara dayanarak tür çıkarımı yapması ve daha doğru bir tür çıkarabilmesiydi. Bu nedenle, TypeScript nesnelerimizin yapısını gerçekten daha iyi anladı ve sorunlu kullanımları keşfetti.

Bu konuda önemli bir nokta da, Closure derleyicisinin DevTools'daki kullanımına sık sık @unrestricted dahil olmasıdır. @unrestricted ile bir sınıfa ek açıklama eklemek, ilgili sınıf için Closure derleyicisinin katı özellik denetimlerini etkin bir şekilde devre dışı bırakır. Bu da, geliştiricinin herhangi bir tür güvenliği olmadan istediği zaman bir sınıf tanımını genişletebileceği anlamına gelir. DevTools kod tabanında @unrestricted kullanımının neden yaygın olarak görüldüğüne dair geçmişe dönük bir bağlam bulamadık. Ancak bu durum, Kapatma derleyicisinin kod tabanının büyük bölümlerinde daha az güvenli bir çalışma modunda çalıştırılmasına neden olmuştur.

TypeScript'in keşfettiği tür hatalarına sahip regresyonlarımızın çapraz analizi de bir çakışma gösterdi ve bu da bizi TypeScript'in (türlerin kendilerinin doğru olması şartıyla) bu sorunları engelleyebileceğine inanmamızı sağladı.

any arama yapılıyor

Bu noktada, Closure Compiler kullanımımızı iyileştirmek mi, yoksa TypeScript'e geçmek mi arasında karar vermemiz gerekiyordu. (Akış Google'da veya Chromium'da desteklenmediği için bu seçeneği iptal etmek zorunda kaldık.) JavaScript/TypeScript araçları üzerinde çalışan Google mühendisleriyle yapılan görüşmeler ve onlardan gelen öneriler doğrultusunda, TypeScript derleyicisini seçmeyi tercih ettik. (Ayrıca, kısa bir süre önce Puppeteer'ı TypeScript'e taşıma hakkında bir blog yayını yayınladık.)

TypeScript derleyicisinin başlıca nedenleri, geliştirilmiş tür doğruluğuydu. Diğer avantajlar arasında ise Google'da dahili olarak TypeScript ekiplerinden destek ve TypeScript dilinin interfaces gibi özellikleri (JSDoc'taki typedefs yerine) yer alıyordu.

TypeScript derleyicisini seçmek, DevTools kod tabanına ve dahili mimarisine önemli ölçüde yatırım yapmamız gerekeceği anlamına geliyordu. Bu nedenle, TypeScript'e (2020'nin 3. çeyreğinde) geçiş için en az bir yıla ihtiyacımız olduğunu tahmin ettik.

Taşıma işlemini gerçekleştirme

Kalan en önemli soru: TypeScript'e nasıl geçiş yapacağız? 150.000 kod satırımız var ve bunu tek seferde taşıyamıyoruz. Ayrıca,kod tabanımızda TypeScript'i çalıştırmanın binlerce hatayı ortaya çıkaracağını biliyorduk.

Birden çok seçeneği değerlendirdik:

  1. Tüm TypeScript hatalarını alın ve bunları bir "golden" çıktısıyla karşılaştırın. Bu yaklaşım TypeScript ekibinin uygulamalarına benzer. Bu yaklaşımın en büyük dezavantajı, düzinelerce mühendis aynı kod tabanında çalıştığı için birleştirme çatışmalarının çok sık yaşanmasıdır.
  2. Tüm sorunlu türleri any olarak ayarlayın. Bu da aslında TypeScript'in hataları engellemesine neden olur. Geçişle ilgili hedefimiz, gizlemenin zayıflayacağı tür doğruluğu olduğundan bu seçeneği belirlemedik.
  3. Tüm TypeScript hatalarını manuel olarak düzeltin. Bu, binlerce hatayı düzeltmeyi içerir ve çok zaman alır.

Beklenen büyük çabaya rağmen 3. seçeneği tercih ettik. Bu seçeneği tercih etmemizin başka nedenleri de vardı: Örneğin, tüm kodları denetlememize ve uygulaması da dahil olmak üzere tüm işlevleri yılda bir kez incelememize olanak tanıdı. İş açısından, yeni değer sağlamak yerine statükoyu koruduk. Bu durum, 3. seçeneğin doğru tercih olarak kabul edilmesini zorlaştırıyordu.

Bununla birlikte, TypeScript'i kullanmaya başlayarak özellikle regresyonlarla ilgili olarak gelecekte ortaya çıkabilecek sorunları önleyebileceğimize inanıyorduk. Bu nedenle, daha çok "yeni iş değerleri katıyoruz" ve daha çok "elde edilen iş değerini kaybetmememizi sağlıyoruz" şeklinde ifade edildi.

TypeScript derleyici için JavaScript desteği

Ekibin katılımını güvence altına aldıktan ve hem Closure hem de TypeScript derleyicisini aynı JavaScript kodu üzerinde çalıştırmak üzere bir plan geliştirdikten sonra, birkaç küçük dosya oluşturmaya başladık. Yaklaşımımız çoğunlukla aşağıdan yukarıyaydı: Temel kodla başlayın ve üst seviye panellere ulaşana kadar mimaride daha yukarılara taşıyın.

Geliştirici Araçları'ndaki her dosyaya önceden @ts-nocheck ekleyerek çalışmalarımızı paralel hale getirmeyi başardık. "TypeScript'i düzeltme" işlemi, @ts-nocheck ek açıklamasını kaldırmak ve TypeScript'in bulacağı hataları gidermektir. Bu, her bir dosyanın kontrol edildiğinden ve mümkün olduğunca çok tür sorununun çözüldüğünden emin olmamız anlamına geliyordu.

Genel olarak, bu yaklaşım az sayıda soruna yardımcı oldu. TypeScript derleyicisinde birkaç hata ile karşılaştık, ancak bunların çoğu belirsizdi:

  1. any döndüren bir işlev türüne sahip isteğe bağlı bir parametre gerekli olarak kabul edilir: #38551
  2. Sınıf sonu bildiriminin statik yöntemine özellik ataması: #38553
  3. No-args oluşturucuya sahip bir alt sınıfın ve bağımsız değişken oluşturucuya sahip bir süper sınıfın bildirimi, alt kurucuyu atlar: #41397

Bu hatalar, %99'luk durum için TypeScript derleyicinin temel oluşturmak üzere sağlam bir temel olduğunu vurgulamaktadır. Evet, bu anlaşılması güç hatalar bazen Geliştirici Araçları için sorunlara neden oluyordu, ancak çoğu zaman bunları kolayca çözebilmemiz için yeterince açık değillerdi.

Karışıklığa neden olan tek sorun .tsbuildinfo dosyalarının belirli olmayan çıktılarıydı: #37156. Chromium'da, aynı Chromium kaydetme işleminin iki derlemesinin de tam olarak aynı çıktıyla sonuçlanması gerekir. Maalesef Chromium derleme mühendislerimiz .tsbuildinfo çıktısının belirleyici olmadığını keşfetti: crbug.com/1054494. Bu sorunu geçici olarak çözmek için .tsbuildinfo dosyasına (esasen JSON içeren) maymun ile yama uygulamamız ve son işlemden sonra belirleyici bir çıktı döndürmemiz gerekti: https://crrev.com/c/2091448 Neyse ki TypeScript ekibi yukarı akış sorununu çözdü ve kısa süre içinde geçici çözümümüzü kaldırabildik. Hata raporlarına açık oldukları ve bu sorunları hemen düzelttikleri için TypeScript ekibine teşekkür ederiz!

Genel olarak, TypeScript derleyicisinin (tür) doğruluğundan memnunuz. Büyük bir açık kaynak JavaScript projesi olarak Devtools'un TypeScript'teki JavaScript desteğini sağlamlaştırmaya yardımcı olduğunu umuyoruz.

Sonuçları analiz etme

Bu tür hataları çözmede iyi bir ilerleme kaydedebildik ve TypeScript tarafından kontrol edilen kod miktarını yavaş yavaş artırabildik. Ancak Ağustos 2020'de (bu geçişten 9 ay sonra) kontrol ettik ve mevcut hızımızla son tarihimizi karşılayamayacağımızı fark ettik. Mühendislerimizden biri, "TypeScriptification"ın (bu taşıma işlemine verdiğimiz ad) ilerlemesini göstermek üzere bir analiz grafiği oluşturdu.

TypeScript Taşıma işleminin ilerleme durumu

TypeScript Migration ilerleme durumu - Taşınması gereken kalan kod satırlarını izleme

Temmuz 2021 ile Aralık 2021 tarihleri arasında, son tarihin neredeyse bir yıl geçmiş olmasına rağmen kalan satır sayısını 0'a çıkaracağımız tahmin ediliyordu. Yönetim ve diğer mühendislerle yaptığımız görüşmelerden sonra, TypeScript derleyici desteğine geçiş için çalışan mühendislerin sayısını artırmaya karar verdik. Taşıma işlemini paralel yapılabilir olarak tasarladığımız ve birden fazla farklı dosya üzerinde çalışan birden çok mühendisin birbiriyle çatışmayacağı şekilde tasarladığımız için bu mümkün oldu.

Bu noktada TypeScriptification süreci ekip genelinde bir çalışma haline geldi. Ek yardım sayesinde taşıma işlemini Kasım 2020'nin sonunda, başladıktan 13 ay sonra ve ilk tahminimizin tahmin edilmesinden bir yıl önce tamamlamayı başardık.

Toplamda, 18 mühendis tarafından gönderilen 771 değişiklik listesi (Çekme İsteğine benzer) vardı. İzleme hatamız (https://crbug.com/1011811) 1.200'ün üzerinde yorum içeriyor (bunların neredeyse tamamı değişiklik listelerinden gelen otomatik yayınlar). İzleme e-tablomuzda, yazılacak tüm dosyalar, atanan kişiler ve hangi değişiklik listesinde "Dize edilmiş" olarak belirtilen 500'den fazla satır bulunuyordu.

TypeScript derleyicisinin performansının etkisini azaltma

Şu anda üzerinde çalıştığımız en büyük sorun TypeScript derleyicisinin yavaş performansıdır. Chromium ve Geliştirici Araçları'nı geliştiren mühendislerin sayısı göz önünde bulundurulduğunda, bu engelin maliyeti yüksektir. Ne yazık ki taşıma işleminden önce bu riski belirleyemiyorduk ve ancak dosyaların çoğunu TypeScript'e taşıdığımız sırada Chromium yapıları genelinde harcanan sürede belirgin bir artış keşfettik: https://crbug.com/1139220

Microsoft TypeScript derleyici ekibine mevcut bu sorunu bildirdik, ancak ekip maalesef bu davranışın bilinçli olarak yapıldığını tespit etti. Bu sorunu yeniden değerlendirmelerini umuyoruz, ancak bu arada Chromium tarafındaki yavaş performans etkisini mümkün olduğunca azaltmak için çalışıyoruz.

Ne yazık ki, bugün sunduğumuz çözümler Google çalışanı olmayanlar için her zaman uygun olmayabilir. Chromium'a açık kaynaklı katkılar (özellikle Microsoft Edge ekibinden olanlar) çok önemli olduğundan tüm katkıda bulunanların işine yarayacak alternatifler arıyoruz. Ancak şu anda uygun bir alternatif çözüm bulamadık.

Geliştirici Araçları'ndaki TypeScript'in mevcut durumu

Şu an için Closure derleyici türü denetleyicisini kod tabanımızdan kaldırdık ve yalnızca TypeScript derleyicisini kullanıyoruz. TypeScript tarafından yazılmış dosyalar yazabiliyor ve günlük olarak bize yardımcı olan TypeScript'e özgü özelliklerden (arayüzler, geneller, vb.) yararlanabiliyoruz. TypeScript derleyicisinin tür hatalarını ve regresyonları yakalayacağına dair güvenimiz arttı. Bu taşıma işlemine ilk başladığımızda, olmasını umduğumuz gibi şeyler olmasını umduk. Birçok kişi gibi bu geçiş de yavaş, incelikli ve çoğu zaman zorlu bir süreçti. Ancak sağladığı faydaları getirdiğimizde buna değdiğini düşünüyoruz.

Önizleme kanallarını indirme

Varsayılan geliştirme tarayıcınız olarak Chrome Canary, Yeni geliştirilenler veya Beta'yı kullanmayı düşünün. Bu önizleme kanallarıyla Geliştirici Araçları'nın en yeni özelliklerine erişebilir, son teknoloji ürünü web platformu API'lerini test edebilir ve sitenizdeki sorunları kullanıcılarınızdan önce tespit edebilirsiniz!

Chrome Geliştirici Araçları ekibiyle iletişim kurma

Yayındaki yeni özellikler ve değişiklikler ya da Geliştirici Araçları ile ilgili diğer konular hakkında konuşmak için aşağıdaki seçenekleri kullanın.

  • crbug.com adresinden öneri veya geri bildirim gönderin.
  • Geliştirici Araçları'nda, Diğer seçenekler   Diğer > Yardım > Geliştirici Araçları sorunu bildir'i kullanarak Geliştirici Araçları sorunlarını bildirin.
  • @ChromeDevTools adresine tweet gönderin.
  • Geliştirici Araçları'ndaki YouTube videoları veya Geliştirici Araçları İpuçları YouTube videolarındaki yenilikler hakkındaki görüşlerinizi bizimle paylaşın.