Geliştirici Araçları mimarisi yenilemesi: Geliştirici Araçları'nda CSS altyapısını modernleştirme
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. CSS'nin Geliştirici Araçları'nda geçmişte nasıl çalıştığını ve CSS'yi JavaScript dosyalarında yüklemeye yönelik standart bir web çözümüne geçmeye hazırlanırken (nihayetinde) CSS'mizi Geliştirici Araçları'nda nasıl modernleştirdiğimizi açıklayacağız.
Geliştirici Araçları'nda CSS'nin önceki durumu
Geliştirici Araçları, CSS'yi iki farklı şekilde uyguladı: biri, Geliştirici Araçları'nın eski bölümünde kullanılan CSS dosyaları, diğeri ise Geliştirici Araçları'nda kullanılan modern web bileşenleri içindi.
DevTools'taki CSS uygulaması yıllar önce tanımlanmış ve artık güncel değildir. Geliştirici Araçları, module.json
kalıbını kullanmaya devam etti ve bu dosyaları kaldırmak için büyük çaba harcadı. Bu dosyaların kaldırılmasını engelleyen son öğe, CSS dosyalarını yüklemek için kullanılan resources
bölümüdür.
Zaman ayırıp CSS modülü komut dosyalarına dönüşebilecek farklı olası çözümleri keşfetmek istedik. Amaç, eski sistemin neden olduğu teknik borcu ortadan kaldırmak ve CSS modülü komut dosyalarına geçiş sürecini kolaylaştırmaktı.
DevTools'daki CSS dosyaları, kaldırılma sürecinde olan bir module.json
dosyası kullanılarak yüklendiği için "eski" olarak kabul edildi. Tüm CSS dosyalarının, CSS dosyasıyla aynı dizindeki bir module.json
dosyasında resources
altında listelenmeleri gerekiyordu.
Kalan module.json
dosyası örneği:
{
"resources": [
"serviceWorkersView.css",
"serviceWorkerUpdateCycleView.css"
]
}
Bu CSS dosyaları daha sonra bir yol ile içeriklerinin eşlemesi olarak Root.Runtime.cachedResources
adlı bir genel nesne haritasını doldurur. Geliştirici Araçları'na stil eklemek için, yüklemek istediğiniz dosyanın tam yolunu belirterek registerRequiredCSS
çağrısını yapmanız gerekir.
Örnek registerRequiredCSS
çağrısı:
constructor() {
…
this.registerRequiredCSS('ui/legacy/components/quick_open/filteredListWidget.css');
…
}
Bu işlem, CSS dosyasının içeriğini alır ve appendStyle
işlevini kullanarak sayfaya <style>
öğesi olarak ekler:.
Satır içi stil öğesi kullanarak CSS ekleyen appendStyle
işlevi:
const content = Root.Runtime.cachedResources.get(cssFile) || '';
if (!content) {
console.error(cssFile + ' not preloaded. Check module.json');
}
const styleElement = document.createElement('style');
styleElement.textContent = content;
node.appendChild(styleElement);
Modern web bileşenlerini kullanıma sunduğumuzda (özel öğeler kullanılarak), ilk olarak bileşen dosyalarında satır içi <style>
etiketleri aracılığıyla CSS kullanmaya karar verdik. Bu durum, kendi zorluklarını da beraberinde getirdi:
- Söz dizimi vurgulama desteği yok. Satır içi CSS için söz dizimi vurgulama sağlayan eklentiler,
.css
dosyalarında yazılan CSS'deki söz dizimi vurgulama ve otomatik tamamlama özellikleri kadar iyi değildir. - Performans yükü oluşturma Satır içi CSS, linting için iki geçiş yapılması gerektiği anlamına da geliyordu: biri CSS dosyaları, diğeri satır içi CSS için. Tüm CSS'ler bağımsız CSS dosyalarında yazılmış olsaydı bu performans yükü kaldırılabilirdi.
- Küçültmeyle ilgili zorluk. Satır içi CSS kolayca küçültülemediğinden CSS'nin hiçbiri küçültülmedi. DevTools'un sürüm derlemesinin dosya boyutu, aynı web bileşeninin birden fazla örneği tarafından tanıtılan yinelenen CSS nedeniyle de artmıştı.
Staj projemin amacı, CSS altyapısı için hem eski altyapı hem de DevTools'da kullanılan yeni web bileşenleriyle çalışan bir çözüm bulmaktı.
Potansiyel çözümleri araştırma
Sorun iki farklı bölüme ayrılabilir:
- Derleme sisteminin CSS dosyalarıyla nasıl çalıştığına karar verme.
- CSS dosyalarının nasıl içe aktarıldığını ve Geliştirici Araçları tarafından nasıl kullanıldığını anlama
Her bir parça için farklı olası çözümleri inceledik ve bunlar aşağıda özetlenmiştir.
CSS dosyalarını içe aktarma
TypeScript dosyalarına CSS'yi içe aktarıp kullanmanın amacı, web standartlarına olabildiğince sadık kalmak, DevTools'da tutarlılık sağlamak ve HTML'mizde yinelenen CSS'den kaçınmaktı. Ayrıca, değişikliklerimizi CSS Modül Komut Dosyaları gibi yeni web platformu standartlarına taşımamızı sağlayacak bir çözüm seçebilmek istedik.
Bu nedenlerden dolayı @import ifadeleri ve etiketleri, DevTools için uygun bir seçenek olarak görünmüyordu. Bu öğeler, DevTools'un geri kalanındaki içe aktarma işlemleriyle uyumlu olmaz ve stil uygulanmamış içeriğin gösterilmesine (FOUC) neden olur. İçe aktarma işlemlerinin <link>
etiketleriyle olduğundan farklı şekilde açıkça eklenmesi ve işlenmesi gerektiğinden CSS modülü komut dosyalarına geçiş daha zor olur.
const output = LitHtml.html`
<style> @import "css/styles.css"; </style>
<button> Hello world </button>`
const output = LitHtml.html`
<link rel="stylesheet" href="styles.css">
<button> Hello World </button>`
@import
veya <link>
kullanan olası çözümler.
Bunun yerine, CSS dosyasını adoptedStyleSheets
özelliğini kullanarak Shadow Dom'a (Geliştirici Araçları birkaç yıldır Gölge DOM'u kullanıyor) ekleyebilmek için CSSStyleSheet
nesnesi olarak içe aktarmanın bir yolunu bulmaya karar verdik.
Paketleyici seçenekleri
TypeScript dosyasında kolayca değiştirebilmemiz için CSS dosyalarını CSSStyleSheet
nesnesine dönüştürmenin bir yoluna ihtiyacımız vardı. Bu dönüşümü bizim için yapacak potansiyel paketleyiciler olarak hem Rollup hem de webpack'ı değerlendirdik. DevTools, üretim derlemesinde zaten Rollup'u kullanıyor ancak üretim derlemesine bu paketleyicilerden birini eklemek, mevcut derleme sistemimizle çalışırken olası performans sorunlarına neden olabilir. Chromium'un GN derleme sistemi ile entegrasyonumuz, paketlemeyi daha zor hale getiriyor. Bu nedenle, paketleyiciler mevcut Chromium derleme sistemiyle iyi entegre olmuyor.
Bunun yerine, bu dönüşümü bizim için yapmak üzere mevcut GN derleme sistemini kullanma seçeneğini araştırdık.
Geliştirici Araçları'nda CSS'yi kullanmanın yeni altyapısı
Yeni çözüm, belirli bir gölge DOM'a stil eklemek için adoptedStyleSheets
'ü, document
veya ShadowRoot
tarafından benimsenebilecek CSSStyleSheet nesneleri oluşturmak için GN derleme sistemini kullanmayı içerir.
// CustomButton.ts
// Import the CSS style sheet contents from a JS file generated from CSS
import customButtonStyles from './customButton.css.js';
import otherStyles from './otherStyles.css.js';
export class CustomButton extends HTMLElement{
…
connectedCallback(): void {
// Add the styles to the shadow root scope
this.shadow.adoptedStyleSheets = [customButtonStyles, otherStyles];
}
}
adoptedStyleSheets
kullanmanın aşağıdakiler gibi birçok avantajı vardır:
- Modern bir web standardı olma yolunda ilerliyor
- Yinelenen CSS'yi önler
- Stilleri yalnızca Gölge DOM'a uygular. Bu sayede, CSS dosyalarındaki yinelenen sınıf adları veya kimlik seçicilerden kaynaklanan sorunlar önlenir.
- CSS Modülü Komut Dosyaları ve İçe Aktarma Onaylarını gibi gelecekteki web standartlarına kolay geçiş
Çözümün tek sakıncası, import
ifadelerinin .css.js
dosyasının içe aktarılmasını gerektirmesiydi. GN'nin derleme sırasında bir CSS dosyası oluşturmasına izin vermek için generate_css_js_files.js
komut dosyasını yazdık. Derleme sistemi artık her CSS dosyasını işler ve varsayılan olarak bir CSSStyleSheet
nesnesini dışa aktaran bir JavaScript dosyasına dönüştürür. CSS dosyasını içe aktarıp kolayca kullanabileceğimiz için bu çok iyi. Ayrıca, artık üretim derlemesini kolayca küçülterek dosya boyutunda tasarruf sağlayabiliyoruz:
const styles = new CSSStyleSheet();
styles.replaceSync(
// In production, we also minify our CSS styles
/`${isDebug ? output : cleanCSS.minify(output).styles}
/*# sourceURL=${fileName} */`/
);
export default styles;
Komut dosyasından iconButton.css.js
oluşturulan örnek.
Eski kodu ESLint kurallarını kullanarak taşıma
Web bileşenleri manuel olarak kolayca taşınabilirken registerRequiredCSS
'ün eski kullanımlarının taşınması daha karmaşık bir süreçti. Eski stilleri kaydeden iki ana işlev registerRequiredCSS
ve createShadowRootWithCoreStyles
idi. Bu çağrıları taşımayla ilgili adımlar oldukça mekanik olduğundan, düzeltmeleri uygulamak ve eski kodu otomatik olarak taşımak için ESLint kurallarını kullanabileceğimize karar verdik. Geliştirici Araçları, halihazırda Geliştirici Araçları kod tabanına özgü bir dizi özel kural kullanmaktadır. ESLint zaten kodu bir Soyut Söz Dizimi Ağacı'na (kısaltması AST) ayrıştırdığı için bu faydalı oldu. AST) ve CSS kaydetme çağrıları olan belirli çağrı düğümlerini sorgulayabiliriz.
Taşıma ESLint Kurallarını yazarken karşılaştığımız en büyük sorun, uç durumları tespit etmekti. Hangi uç durumların yakalanmaya değer olduğunu ve hangilerinin manuel olarak taşınması gerektiğini bilmek arasında doğru dengeyi sağladığımızdan emin olmak istedik. Ayrıca, içe aktarılan bir .css.js
dosyası derleme sistemi tarafından otomatik olarak oluşturulmadığında kullanıcıya bunu bildirebilmeyi de istedik. Bu sayede, çalışma zamanında dosya bulunamadı hatalarını önleyebiliriz.
Taşıma işlemi için ESLint kurallarının kullanılmasının bir dezavantajı, sistemdeki gerekli GN derleme dosyasını değiştiremememizdi. Bu değişikliklerin her dizinde kullanıcı tarafından manuel olarak yapılması gerekiyordu. Daha fazla çalışma gerekse de bu, içe aktarılan her .css.js
dosyasının aslında derleme sistemi tarafından oluşturulduğunu doğrulamak için iyi bir yöntem oldu.
Eski kodu yeni altyapıya hızlıca taşıyabildiğimiz ve AST'nin hazır olması sayesinde kural içindeki birden fazla uç durumu da ele alabildiğimiz ve ESLint'in fixer API'sini kullanarak bunları otomatik olarak güvenilir bir şekilde düzeltebileceğimiz için bu taşıma işlemi için ESLint kurallarını kullanmak genel olarak çok faydalı oldu.
Sonra ne olur?
Şu ana kadar Chromium Geliştirici Araçları'ndaki tüm web bileşenleri, satır içi stiller kullanmak yerine yeni CSS altyapısını kullanacak şekilde taşındı. registerRequiredCSS
'ün eski kullanımlarının çoğu da yeni sisteme taşındı. Tek yapmanız gereken, mümkün olduğunca fazla module.json
dosyasını kaldırmak ve ardından gelecekte CSS Modülü Komut Dosyalarını uygulamak üzere bu mevcut altyapıyı taşımaktır.
Ö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şmenizi sağlar, en yeni web platformu API'lerini test etmenize olanak tanır 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.
- Geri bildirimlerinizi ve özellik isteklerinizi crbug.com adresinden bize iletebilirsiniz.
- 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.