Chrome Geliştirici Araçları'nın HTML, CSS ve JavaScript kullanılarak yazılmış bir web uygulaması olduğunu biliyorsunuzdur. DevTools, yıllar içinde daha fazla özellik, daha akıllı ve daha geniş web platformu hakkında daha bilgili hale geldi. Geliştirici Araçları yıllar içinde genişlemiş olsa da mimarisi, hâlâ WebKit'in bir parçası olduğu zamanki orijinal mimariye büyük ölçüde benziyor.
Bu yayın, DevTools'un 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. DevTools'un geçmişte nasıl çalıştığını, avantajlarını ve sınırlamalarını ve bu sınırlamaları hafifletmek için neler yaptığımızı açıklayacağız. Bu nedenle, modül sistemleri, kod yükleme ve JavaScript modüllerini kullanmaya nasıl karar verdiğimizi ayrıntılı olarak inceleyelim.
Başlangıçta hiçbir şey yoktu
Mevcut ön uç ortamında, etrafında araçlar bulunan çeşitli modül sistemleri ve artık standartlaştırılmış JavaScript modülleri biçimi mevcut olsa da DevTools ilk oluşturulduğunda bunların hiçbiri yoktu. DevTools, ilk olarak 12 yıldan uzun bir süre önce WebKit'te kullanıma sunulan kodun üzerine inşa edilmiştir.
DevTools'ta modül sisteminden ilk kez 2012'de bahsedildi: İlişkili bir kaynak listesi içeren modül listesinin kullanıma sunulması.
Bu, o zamanlar DevTools'u derlemek ve oluşturmak için kullanılan Python altyapısının bir parçasıydı.
Bir takip değişikliği, tüm modülleri 2013'te ayrı bir frontend_modules.json
dosyasına (commit) ve ardından 2014'te ayrı module.json
dosyalarına (commit) ayırdı.
Örnek bir module.json
dosyası:
{
"dependencies": [
"common"
],
"scripts": [
"StylePane.js",
"ElementsPanel.js"
]
}
2014'ten beri DevTools'ta modüllerini ve kaynak dosyalarını belirtmek için module.json
kalıbı kullanılmaktadır.
Bu sırada web ekosistemi hızla gelişti ve UMD, CommonJS ve nihayetinde standartlaştırılmış JavaScript modülleri dahil olmak üzere birden fazla modül biçimi oluşturuldu.
Ancak Geliştirici Araçları module.json
biçimini kullanmaya devam etti.
Geliştirici Araçları çalışmaya devam etse de standartlaştırılmamış ve benzersiz bir modül sisteminin kullanılmasının bazı dezavantajları vardı:
module.json
biçimi, modern paketleyicilere benzer şekilde özel derleme araçları gerektiriyordu.- IDE entegrasyonu yoktu. Bu nedenle, modern IDE'lerin anlayabileceği dosyalar oluşturmak için özel araçlar gerekiyordu (VS Code için jsconfig.json dosyaları oluşturmaya yönelik orijinal komut dosyası).
- Modüller arasında paylaşımı mümkün kılmak için işlevler, sınıflar ve nesnelerin tümü genel kapsama alındı.
- Dosyalar sıraya bağlıydı. Yani
sources
öğelerinin listelenme sırası önemliydi. Güvendiğiniz kodun, bir insan tarafından doğrulanması dışında yüklenmesi garanti edilmez.
DevTools'daki modül sisteminin ve diğer (daha yaygın kullanılan) modül biçimlerinin mevcut durumunu değerlendirdiğimizde, module.json
kalıbının çözdüğünden daha fazla soruna yol açtığına ve bu kalıptan uzaklaşma planımızı yapmanın zamanı geldiğine karar verdik.
Standartların avantajları
Mevcut modül sistemleri arasından, taşınacak modül olarak JavaScript modüllerini seçtik. Bu karar alındığında JavaScript modülleri hâlâ Node.js'de bir işaretin arkasından yayınlanıyordu ve NPM'de bulunan çok sayıda pakette kullanabileceğimiz bir JavaScript modülü paketi yoktu. Buna rağmen, JavaScript modüllerinin en iyi seçenek olduğu sonucuna vardık.
JavaScript modüllerinin birincil avantajı, JavaScript için standartlaştırılmış modül biçimi olmasıdır.
module.json
'ün olumsuz yönlerini listelediğimizde (yukarıya bakın) bunların neredeyse tamamının standart olmayan ve benzersiz bir modül biçimi kullanılmasıyla ilgili olduğunu fark ettik.
Standart olmayan bir modül biçimi seçmek, derleme araçlarıyla ve bakım ekibimizin kullandığı araçlarla entegrasyon oluşturmak için zaman ayırmamız gerektiği anlamına gelir.
Bu entegrasyonlar genellikle kararsızdı ve özellikler için destekten yoksundu. Bu nedenle ek bakım süresi gerektiriyordu ve bazen kullanıcılara gönderilecek küçük hatalara yol açıyordu.
JavaScript modülleri standart olduğu için VS Code gibi IDE'ler, Closure Compiler/TypeScript gibi tür denetleyiciler ve Rollup/minifier'lar gibi derleme araçları, yazdığımız kaynak kodu anlayabiliyordu.
Ayrıca, DevTools ekibine yeni katılan bir geliştiricinin, özel bir module.json
biçimini öğrenmek için zaman harcaması gerekmez. Bunun yerine, muhtemelen JavaScript modülleri hakkında bilgi sahibidir.
Elbette, DevTools ilk oluşturulduğunda yukarıdaki avantajlardan hiçbiri mevcut değildi. Standartlar grupları, çalışma zamanı uygulamaları ve JavaScript modüllerini kullanan geliştiricilerin geri bildirimleriyle birlikte, bugünkü noktaya ulaşmak için yıllarca çalışma yapıldı. Ancak JavaScript modülleri kullanıma sunulduğunda iki seçenekten birini yapmamız gerekiyordu: Kendi biçimimizi korumaya devam etmek veya yeni biçime geçiş yapmaya yatırım yapmak.
Yeni cihazın maliyeti
JavaScript modüllerinin yararlanmak istediğimiz birçok avantajı olmasına rağmen standart olmayan module.json
dünyasında kaldık.
JavaScript modüllerinin avantajlarından yararlanmak için teknik borcu temizlemeye ve özellikleri bozabilecek ve geriye dönük hatalara neden olabilecek bir taşıma işlemi gerçekleştirmeye önemli ölçüde yatırım yapmamız gerekiyordu.
Bu noktada, "JavaScript modüllerini kullanmak istiyor muyuz?" değil, "JavaScript modüllerini kullanabilmek ne kadar pahalı?" sorusu gündemdeydi. Burada, gerilemelerle kullanıcılarımızın deneyimini bozma riskini, mühendislerin taşıma işlemi için harcayacağı (çok fazla) zaman maliyetini ve çalışacağımız geçici olarak daha kötü durumu dengelememiz gerekiyordu.
Son noktanın çok önemli olduğu ortaya çıktı. Teorik olarak JavaScript modüllerine ulaşabilsek de taşıma sırasında module.json
ve JavaScript modüllerini hem dikkate almamız gereken bir kod elde ederiz.
Bu, teknik açıdan zor olduğu kadar DevTools'ta çalışan tüm mühendislerin bu ortamda nasıl çalışacaklarını bilmeleri gerektiği anlamına da geliyordu.
Kendilerine sürekli şu soruyu sormaları gerekir: "Kod tabanının bu kısmı için module.json
mı yoksa JavaScript modülleri mi kullanılıyor ve nasıl değişiklik yaparım?".
Önizleme: Bakım uzmanlarımıza geçiş sürecinde rehberlik etmenin gizli maliyeti beklediğimizden daha büyüktü.
Maliyet analizinin ardından, JavaScript modüllerine geçişin yine de değerli olduğu sonucuna vardık. Bu nedenle, ana hedeflerimiz şunlardı:
- JavaScript modüllerinin kullanımından mümkün olduğunca fazla yararlandığınızdan emin olun.
- Mevcut
module.json
tabanlı sistemle entegrasyonun güvenli olduğundan ve kullanıcılar üzerinde olumsuz bir etkisi (gerileme hataları, kullanıcıların canını sıkacak durumlar) olmadığından emin olun. - Tüm DevTools geliştiricilerinin taşıma işleminde yol gösterici olması için, öncelikle yanlışlıkla yapılan hataları önlemek amacıyla yerleşik denetim ve dengeler sunar.
E-tablolar, dönüşümler ve teknik borç
Hedef net olsa da module.json
biçiminin getirdiği sınırlamalar nedeniyle geçici çözüm bulmak zor oldu.
Kendimizi rahat hissettiğimiz bir çözüm geliştirmeden önce birkaç iterasyon, prototip ve mimari değişiklik yaptık.
Elde ettiğimiz taşıma stratejisini içeren bir tasarım dokümanı yazdık.
Tasarım dokümanında ilk süre tahminimiz de (2-4 hafta) belirtilmişti.
Spoiler uyarısı: Taşıma işleminin en yoğun kısmı 4 ay sürdü ve baştan sona 7 ay sürdü.
Ancak ilk plan zamana karşı koydu: DevTools çalışma zamanında, scripts
dizisinde listelenen tüm dosyaları module.json
dosyasında eski yöntemi kullanarak, modules
dizisinde listelenen tüm dosyaları ise JavaScript modülleri dinamik içe aktarma ile yüklemeyi öğretecektik.
modules
dizisinde bulunan tüm dosyalar ES içe aktarma/dışa aktarma işlemlerini kullanabilir.
Ayrıca taşıma işlemini 2 aşamada gerçekleştiririz (son aşamayı 2 alt aşamaya ayırırız, aşağıya bakın): export
ve import
aşamaları.
Hangi modülün hangi aşamada olacağı büyük bir e-tabloda izleniyordu:
İlerleme sayfasının bir snippet'ini buradan inceleyebilirsiniz.
export
-aşama
İlk aşamada, modüller/dosyalar arasında paylaşılması gereken tüm semboller için export
-ifadeleri eklenir.
Dönüşüm, klasör başına bir komut dosyası çalıştırılarak otomatikleştirilir.
module.json
dünyasında aşağıdaki sembolün bulunduğu varsayılır:
Module.File1.exported = function() {
console.log('exported');
Module.File1.localFunctionInFile();
};
Module.File1.localFunctionInFile = function() {
console.log('Local');
};
(Burada Module
modülün adı, File1
ise dosyanın adıdır. Kaynak ağacımızda bu front_end/module/file1.js
olur.)
Bu, aşağıdaki gibi dönüştürülür:
export function exported() {
console.log('exported');
Module.File1.localFunctionInFile();
}
export function localFunctionInFile() {
console.log('Local');
}
/** Legacy export object */
Module.File1 = {
exported,
localFunctionInFile,
};
İlk planımız, bu aşamada aynı dosyadan yapılan içe aktarma işlemlerini de yeniden yazmaktı.
Örneğin, yukarıdaki örnekte Module.File1.localFunctionInFile
yerine localFunctionInFile
yazıyoruz.
Ancak bu iki dönüşümü ayırdığımızda otomasyonun daha kolay ve uygulamanın daha güvenli olacağını fark ettik.
Bu nedenle, "aynı dosyadaki tüm sembolleri taşıma" işlemi, import
aşamasının ikinci alt aşaması olur.
Bir dosyaya export
anahtar kelimesi eklendiğinde dosya "komut dosyası" olmaktan "modül"e dönüştüğü için DevTools altyapısının büyük bir kısmının buna göre güncellenmesi gerekiyordu.
Buna çalışma zamanı (dinamik içe aktarma ile) ve modül modunda çalıştırılacak ESLint
gibi araçlar da dahildir.
Bu sorunlar üzerinde çalışırken testlerimizin "sloppy" modunda çalıştığını tespit ettik.
JavaScript modülleri, dosyaların "use strict"
modunda çalıştığını ima ettiğinden bu durum testlerimizi de etkiler.
with
ifadesi kullanılan bir test de dahil olmak üzere çok sayıda testin bu dikkatsizliğe dayandığı ortaya çıktı 😱.
Sonuç olarak, ilk klasörü export
ifadeleri içerecek şekilde güncellemek yaklaşık bir hafta ve yeniden yüklemeyle birden fazla deneme aldı.
import
-aşama
Tüm simgeler hem export
-ifadeleri kullanılarak dışa aktarıldıktan hem de genel kapsamda (eski) kaldıktan sonra, ES içe aktarma işlemlerini kullanmak için tüm dosyalar arası simge referanslarını güncellememiz gerekti.
Nihai hedef, tüm "eski dışa aktarım nesnelerini" kaldırarak global kapsamı temizlemektir.
Dönüşüm, klasör başına bir komut dosyası çalıştırılarak otomatikleştirilir.
Örneğin, module.json
dünyasında bulunan aşağıdaki semboller için:
Module.File1.exported();
AnotherModule.AnotherFile.alsoExported();
SameModule.AnotherFile.moduleScoped();
Bu URL'ler şu şekilde dönüştürülür:
import * as Module from '../module/Module.js';
import * as AnotherModule from '../another_module/AnotherModule.js';
import {moduleScoped} from './AnotherFile.js';
Module.File1.exported();
AnotherModule.AnotherFile.alsoExported();
moduleScoped();
Ancak bu yaklaşımın bazı sakıncaları vardı:
- Her simge
Module.File.symbolName
olarak adlandırılmamıştır. Bazı simgeler yalnızcaModule.File
veya hattaModule.CompletelyDifferentName
olarak adlandırılıyordu. Bu tutarsızlık, eski genel nesneden içe aktarılan yeni nesneye dahili bir eşleme oluşturmamız gerektiği anlamına geliyordu. - Bazen moduleScoped adları arasında çakışmalar olabilir.
En belirgin olarak, her sembolün yalnızca
Events
olarak adlandırıldığı belirliEvents
türlerini beyan etme kalıbı kullandık. Bu, farklı dosyalarda tanımlanan birden fazla etkinlik türünü dinliyorsanız buEvents
içinimport
-ifadesinde bir ad çakışması yaşanacağı anlamına geliyordu. - Dosyalar arasında döngüsel bağımlılık olduğu ortaya çıktı.
Simgenin kullanımı tüm kod yüklendikten sonra olduğundan bu, global kapsam bağlamında sorunsuzdu.
Ancak bir
import
'e ihtiyacınız varsa döngüsel bağımlılık açıkça belirtilir. DevTools'ta da olduğu gibi, genel kapsamlı kodunuzda yan etki işlevi çağrılarınız yoksa bu hemen bir sorun oluşturmaz. Sonuç olarak, dönüşümü güvenli hale getirmek için bazı düzenlemeler ve yeniden yapılandırmalar yapmak gerekti.
JavaScript modülleri ile yepyeni bir dünya
Eylül 2019'da başlayan işlemden 6 ay sonra, Şubat 2020'de ui/
klasöründe son temizleme işlemleri gerçekleştirildi.
Bu, taşıma işleminin gayrı resmi olarak sona erdiğini işaret ediyordu.
Taşıma işleminin tamamlanmasının ardından, 5 Mart 2020 tarihinde resmi olarak tamamlandı olarak işaretledik. 🎉
Artık DevTools'daki tüm modüller kod paylaşmak için JavaScript modüllerini kullanıyor.
Eski testlerimiz için veya DevTools mimarisinin diğer bölümleriyle entegrasyon sağlamak amacıyla bazı sembolleri hâlâ global kapsama (module-legacy.js
dosyalarına) yerleştiriyoruz.
Bu özellikler zaman içinde kaldırılacak olsa da gelecekteki geliştirmeleri engellemeyecektir.
Ayrıca JavaScript modüllerini kullanmamızla ilgili bir stil kılavuzumuzu da inceleyebilirsiniz.
İstatistikler
Bu taşıma işleminde yer alan CL (değişiklik listesi kısaltması - Gerrit'te bir değişikliği temsil eden terim - GitHub çekme isteğine benzer) sayısına dair muhafazakar tahminler çoğunlukla 2 mühendis tarafından gerçekleştirilen 250 CL civarındadır. Yapılan değişikliklerin boyutu hakkında kesin istatistiklerimiz yok ancak değişen satır sayısıyla ilgili muhafazakar bir tahmin (her CL için eklemeler ve silme işlemleri arasındaki mutlak farkın toplamı olarak hesaplanır) yaklaşık 30.000'dir (tüm DevTools ön uç kodunun yaklaşık% 20'si).
export
kullanan ilk dosya, Aralık 2019'da kararlı sürüme yayınlanan Chrome 79'da kullanıma sunuldu.
import
'e geçişle ilgili son değişiklik, Mayıs 2020'de kararlı sürümde yayınlanan Chrome 83'te kullanıma sunulmuştur.
Chrome kararlı sürümünde kullanıma sunulan ve bu taşıma işleminin bir parçası olarak kullanıma sunulan bir gerileme olduğunun farkındayız.
Bilinmeyen bir default
dışa aktarma nedeniyle komut menüsündeki snippet'lerin otomatik olarak tamamlanması bozuldu.
Başka birkaç regresyon da yaşadık ancak otomatik test paketlerimiz ve Chrome Canary kullanıcıları bunları bildirdi ve Chrome Stable kullanıcılarına ulaşmadan önce düzelttik.
Yolculuğun tamamını (tüm CL'ler bu hataya eklenmemiştir ancak çoğu eklenmiştir) crbug.com/1006759 adresinde görebilirsiniz.
Öğrendiklerimiz
- Geçmişte alınan kararlar projeniz üzerinde uzun süreli bir etki yaratabilir. JavaScript modülleri (ve diğer modül biçimleri) uzun süredir kullanılsa da DevTools, taşıma işlemini haklı çıkaracak durumda değildi. Ne zaman geçiş yapacağınıza ve ne zaman yapmayacağınıza karar vermek zordur ve tahminlere dayanır.
- İlk zaman tahminlerimiz ay yerine hafta olarak yapılmıştı. Bu durum büyük oranda, ilk maliyet analizimizde beklediğimizden daha fazla beklenmedik sorun bulmamızdan kaynaklanmaktadır. Taşıma planı sağlam olsa da teknik borç, süreci engelleyen faktördü (istediğimizden daha sık).
- JavaScript modülleri taşıma işlemi, çok sayıda (ilgili görünmeyen) teknik borç temizlemesini içeriyordu. Modern ve standartlaştırılmış bir modül biçimine geçiş, kodlamayla ilgili en iyi uygulamalarımızı modern web geliştirmeyle yeniden uyumlu hale getirmemize olanak tanıdı. Örneğin, özel Python paketleyicimizi minimum bir Rollup yapılandırmasıyla değiştirebildik.
- Kod tabanımızdaki büyük etkiye rağmen (kodun yaklaşık% 20'si değişti) çok az sayıda gerileme bildirildi. İlk birkaç dosyayı taşırken çok sayıda sorun yaşadık ancak bir süre sonra sağlam ve kısmen otomatik bir iş akışına sahip olduk. Bu, bu taşıma işleminde sabit kullanıcılarımız üzerindeki olumsuz etkiyi en aza indirdiği anlamına geliyor.
- Belirli bir taşıma işleminin inceliklerini diğer geliştiricilere öğretmek zor ve bazen imkansızdır. Bu ölçekte taşıma işlemlerinin takip edilmesi zordur ve çok fazla alan bilgisi gerektirir. Bu alan bilgisini, aynı kod tabanında çalışan diğer kişilere aktarmak, yaptıkları iş açısından kendi başına istenilen bir durum değildir. Neleri paylaşacağınızı ve hangi ayrıntıları paylaşmayacağınızı bilmek bir sanattır ancak gerekli bir sanattır. Bu nedenle, büyük taşıma işlemlerinin miktarını azaltmak veya en azından aynı anda gerçekleştirmemek çok önemlidir.
Önizleme kanallarını indirme
Varsayılan geliştirme tarayıcınız olarak Chrome Canary, Yeni Geliştirilenler veya Beta sürümünü kullanabilirsiniz. Bu önizleme kanalları, en son DevTools özelliklerine erişmenize, en yeni web platformu API'lerini test etmenize ve sitenizdeki sorunları kullanıcılarınızdan önce bulmanıza yardımcı olur.
Chrome Geliştirici Araçları Ekibi ile iletişime geçme
Yeni özellikler, güncellemeler veya Geliştirici Araçları ile ilgili başka herhangi bir konu hakkında konuşmak için aşağıdaki seçenekleri kullanın.
- crbug.com adresinden bize geri bildirim ve özellik isteği gönderin.
- Geliştirici Araçları'nda Diğer seçenekler > Yardım > Geliştirici Araçları sorunu bildir'i kullanarak bir Geliştirici Araçları sorununu bildirin.
- @ChromeDevTools hesabına tweet gönderin.
- Geliştirici Araçları'ndaki yenilikler veya Geliştirici Araçları'yla ilgili ipuçları konulu YouTube videolarına yorum bırakın.