Chrome Geliştirici Araçları'nın Stiller sekmesindeki CSS özelliklerinin son zamanlarda daha şık göründüğünü fark ettiniz mi? Chrome 121 ile 128 arasında kullanıma sunulan bu güncellemeler, CSS değerlerini ayrıştırma ve sunma şeklimizde yaptığımız önemli bir iyileştirmenin sonucudur. Bu makalede, normal ifade eşleştirme sisteminden daha güçlü bir ayrıştırıcıya geçişin teknik ayrıntıları ele alınmaktadır.
Mevcut DevTools'u önceki sürümle karşılaştıralım:
Oldukça farklı, değil mi? Temel iyileştirmelerin dökümü aşağıda verilmiştir:
color-mix
.color-mix
işlevindeki iki renk bağımsız değişkenini görsel olarak temsil eden kullanışlı bir önizleme.pink
.pink
adlı renk için tıklanabilir bir renk önizlemesi. Kolay ayarlamalar yapmak üzere bir renk seçici açmak için bu simgeyi tıklayın.var(--undefined, [fallback value])
. Tanımlanmamış değişken gri renkte ve tıklanabilir bir renk önizlemesiyle birlikte etkin yedek değer (bu durumda HSL rengi) görüntülenerek tanımlanmamış değişkenlerin işlenmesi iyileştirildi.hsl(…)
:hsl
renk işlevi için, renk seçiciye hızlı erişim sağlayan başka bir tıklanabilir renk önizlemesi.177deg
: Açıyı etkileşimli olarak sürükleyip değiştirmenize olanak tanıyan tıklanabilir bir açı saati.var(--saturation, …)
: Özel mülk tanımına ait, ilgili beyana kolayca geçilmesini sağlayan tıklanabilir bağlantı.
Aralarındaki fark çarpıcıdır. Bunu başarmak için DevTools'a CSS mülk değerlerini daha önce olduğundan çok daha iyi anlamasını öğretmemiz gerekiyordu.
Bu önizlemeler zaten mevcut değil miydi?
Bu önizleme simgeleri tanıdık görünse de özellikle yukarıdaki örnekteki gibi karmaşık CSS söz diziminde her zaman tutarlı bir şekilde gösterilmemiştir. Çalıştığı durumlarda bile, doğru şekilde çalışması için genellikle önemli miktarda çaba gerekiyordu.
Bunun nedeni, değerleri analiz etme sisteminin DevTools'un ilk günlerinden beri organik olarak büyümesidir. Ancak CSS'den aldığımız son muhteşem yeni özelliklere ve dil karmaşıklığındaki artışa ayak uyduramadı. Sistem, evrime ayak uydurabilmek için baştan sona yeni bir tasarıma ihtiyaç duydu. Biz de bunu yaptık.
CSS mülk değerleri nasıl işlenir?
Geliştirici Araçları'nda, Stiller sekmesindeki mülk bildirimlerini oluşturma ve süsleme işlemi iki farklı aşamadan oluşur:
- Yapısal analiz. Bu ilk aşamada, temel bileşenleri ve bunların ilişkilerini belirlemek için mülk beyanı incelenir. Örneğin,
border: 1px solid red
beyanında1px
uzunluğu,solid
dize,red
ise renk olarak tanınır. - Oluşturma. Oluşturma aşaması, yapısal analizden yararlanarak bu bileşenleri HTML temsiline dönüştürür. Bu sayede, gösterilen mülk metni etkileşimli öğelerle ve görsel ipuçlarıyla zenginleştirilir. Örneğin,
red
renk değeri, tıklandığında kolayca değişiklik yapmanızı sağlayan bir renk seçici gösteren tıklanabilir bir renk simgesiyle oluşturulur.
Normal ifadeler
Daha önce, yapısal analizde özellik değerlerini incelemek için normal ifadelerden (normal ifadeler) yararlanıyorduk. Dekorasyon yapmayı düşündüğümüz özellik değerlerinin parçalarına uygun bir normal ifade listesi düzenledik. Örneğin, CSS renkleri, uzunlukları, açılar ve var
işlev çağrıları gibi daha karmaşık alt ifadelerle eşleşen ifadeler vardı. Değer analizi yapmak için metni soldan sağa taradık ve listedeki ilk ifadenin metnin bir sonraki parçasıyla eşleşip eşleşmediğini sürekli olarak kontrol ettik.
Bu yöntem çoğu zaman işe yaramasına rağmen, işe yaramadığı durumlar da giderek artıyordu. Yıllar içinde, eşleştirmenin tam olarak doğru olmadığı çok sayıda hata raporu aldık. Bu sorunları düzeltirken (bazı düzeltmeler basit, bazıları oldukça ayrıntılıydı) teknik borcumuzu kontrol altında tutmak için yaklaşımımızı yeniden düşünmemiz gerekti. Bazı sorunlara göz atalım.
Eşleşen color-mix()
color-mix()
işlevi için kullandığımız normal ifade şundu:
/color-mix\(.*,\s*(?<firstColor>.+)\s*,\s*(?<secondColor>.+)\s*\)/g
Söz dizimi şu şekildedir:
color-mix(<color-interpolation-method>, [<color> && <percentage [0,100]>?]#{2})
Eşleşmeleri görselleştirmek için aşağıdaki örneği çalıştırmayı deneyin.
const re = /color-mix\(.*,\s*(?<firstColor>.+)\s*,\s*(?<secondColor>.+)\s*\)/g;
// it works - simpler example
const simpler = re.exec('color-mix(in srgb, pink, hsl(127deg 100% 50%))');
console.table(simpler.groups);
re.exec('');
// it doesn't work - complex example
const complex = re.exec('color-mix(in srgb, pink, var(--undefined, hsl(127deg var(--saturation, 100%) 50%)))');
console.table(complex.groups);
Basit örnek iyi çalışır. Ancak daha karmaşık örnekte <firstColor>
eşleşmesi hsl(177deg var(--saturation
, <secondColor>
eşleşmesi ise 100%) 50%))
şeklindedir. Bu da tamamen anlamsızdır.
Bunun bir sorun olduğunun farkındayız. Sonuçta, resmi bir dil olarak CSS normal değildir. Bu nedenle, var
işlevleri gibi daha karmaşık işlev bağımsız değişkenleriyle başa çıkmak için özel işleme zaten dahil ettik. Ancak ilk ekran görüntüsünde göreceğiniz gibi bu yöntem her durumda işe yaramadı.
Eşleşen tan()
Bildirilen en komik hatalardan biri trigonometrik tan()
işleviyle ilgiliydi . Renkleri eşleştirmek için kullandığımız normal ifade, red
anahtar kelimesi gibi adlandırılmış renkleri eşleştirmek için bir alt ifade \b[a-zA-Z]+\b(?!-)
içeriyordu. Daha sonra, eşleşen bölümün gerçekten adlandırılmış bir renk olup olmadığını kontrol ettik ve tan
öğesinin de adlandırılmış bir renk olduğunu tahmin ettik! Bu nedenle tan()
ifadeleri yanlış bir şekilde renkler olarak yorumladık.
Eşleşen var()
Başka bir örneğe bakalım. Diğer var()
referansları içeren yedek var()
işlevleri: var(--non-existent, var(--margin-vertical))
.
var()
için normal ifademiz bu değeri kolayca eşleştirir. Ancak ilk kapanan parantezde eşleştirme durur. Bu nedenle, yukarıdaki metin var(--non-existent, var(--margin-vertical)
olarak eşleştirilir. Bu, normal ifade eşleştirmenin temel bir sınırlamasıdır. Eşleşen parantez gerektiren diller temel olarak normal değildir.
CSS ayrıştırıcıya geçiş
Normal ifadeler kullanarak yapılan metin analizi çalışmadığında (analiz edilen dil normal olmadığı için) bir sonraki adım olan standart bir adım vardır: Daha yüksek tür dil bilgisi için ayrıştırıcı kullanma. CSS için bu, bağlam içermeyen diller için bir ayrıştırıcı anlamına gelir. Aslında DevTools kod tabanında zaten böyle bir ayrıştırıcı sistemi mevcuttu: CodeMirror'ın Lezer'i. Bu ayrıştırıcı, Kaynaklar panelinde bulunan düzenleyici olan CodeMirror'da söz dizimi vurgulamanın temelini oluşturur. Lezer'ın CSS ayrıştırıcısı, CSS kuralları için (soyut olmayan) söz dizimi ağaçları üretmemizi sağladı ve bizim için kullanıma hazırdı. Zafer.
Ancak, normal ifade tabanlı eşleştirmeden ayrıştırıcı tabanlı eşleştirmeye doğrudan geçişin kullanıma hazır olarak mümkün olmadığını tespit ettik: İki yaklaşım da zıt yönlerden çalışır. DevTools, değer parçalarını normal ifadelerle eşleştirirken girişi soldan sağa tarar ve sıralı bir kalıp listesinden en erken eşleşmeyi bulmaya çalışır. Söz dizimi ağacında eşleştirme, aşağıdan yukarıya doğru başlar (örneğin, işlev çağrısını eşleştirmeye çalışmadan önce ilk olarak bir çağrının bağımsız değişkenlerinin analiz edilmesi). Bunu, önce parantez içine alınmış ifadeleri, ardından çarpma operatörlerini ve daha sonra toplama operatörlerini dikkate aldığınız bir aritmetik ifadeyi değerlendirmek gibi düşünebilirsiniz. Bu çerçevede, normal ifade tabanlı eşleme, aritmetik ifadenin soldan sağa doğru değerlendirilmesine karşılık gelir. Eşleştirme sisteminin tamamını sıfırdan yeniden yazmak istemedik. Binlerce satır kod içeren 15 farklı eşleştirici ve oluşturma çifti vardı. Bu da tek bir aşamada kullanıma sunma ihtimalimizi azaltıyordu.
Bu nedenle, kademeli değişiklikler yapmamıza olanak tanıyan bir çözüm bulduk. Bu çözümü, aşağıda daha ayrıntılı olarak açıklayacağız. Kısacası, iki aşamalı yaklaşımı koruduk, ancak ilk aşamada alt ifadeleri aşağıdan yukarıya eşleştirmeye çalışıyoruz (böylece normal ifade akışı bozuluyor) ve ikinci aşamada yukarıdan aşağıya yeniden oluşturuyoruz. Her iki aşamada da mevcut normal ifade tabanlı eşleştiricileri ve oluşturmaları neredeyse değiştirmeden kullanabilir ve böylece bunları tek tek taşıyabildik.
1. Aşama: Aşağıdan yukarıya eşleme
İlk aşama, kapakta yazanla neredeyse aynı şekilde ve yalnızca bu şekilde çalışır. Ağacı aşağıdan yukarıya doğru sırayla katediyoruz ve ziyaret ettiğimiz her söz dizimi ağacı düğümünde alt ifadeleri eşleştirmeye çalışıyoruz. Eşleyici, belirli bir alt ifadeyi eşlemek için mevcut sistemde olduğu gibi normal ifadeyi kullanabilir. 128 sürümü itibarıyla, örneğin eşleşen uzunluklar için hâlâ birkaç durumda bunu yapıyoruz. Alternatif olarak, eşleyici, mevcut düğümde köklenen alt ağacın yapısını analiz edebilir. Bu sayede söz dizimi hatalarını yakalayabilir ve aynı zamanda yapısal bilgileri kaydedebilir.
Yukarıdaki söz dizimi ağacı örneğini inceleyin:
Bu ağaç için eşleştiricilerimiz aşağıdaki sırayla uygulanır:
hsl(
177deg
var(--saturation, 100%) 50%)
: İlk olarak,hsl
işlev çağrısının ilk bağımsız değişkeni olan ton açısını keşfediyoruz. Açı değerini açı simgesiyle süsleyebilmek için bir açı eşleyiciyle eşleştiririz.hsl(177deg
var(--saturation, 100%)
50%)
: İkinci olarak, var eşleştirici içerenvar
işlev çağrısını keşfediyoruz. Bu tür aramalarda temel olarak iki şey yapmak isteriz:- Değişkenin tanımını bulun ve değerini hesaplayın. Ardından, değişken adına sırasıyla bağlantı ve pop-up ekleyin.
- Hesaplanan değer bir renkse çağrıyı renk simgesiyle süsleyin. Üçüncü bir konu da var ama bunu daha sonra konuşacağız.
hsl(177deg var(--saturation, 100%) 50%)
: Son olarak,hsl
işlevinin çağrı ifadesini eşleştirerek renk simgesiyle süsleyebiliriz.
Süslemek istediğimiz alt ifadeleri aramanın yanı sıra eşleme işleminin bir parçası olarak çalıştırdığımız ikinci bir özellik de var. 2. adımda, bir değişken adı için hesaplanan değeri aradığımızı belirttiğimizi unutmayın. Hatta bunu bir adım daha ileri götürüp sonuçları ağaca yayarız. Yalnızca değişken için değil, yedek değer için de geçerlidir. Bir var
işlev düğümü ziyaret edildiğinde, alt öğelerinin önceden ziyaret edildiği garanti edilir. Bu nedenle, yedek değerde görünebilecek tüm var
işlevlerinin sonuçlarını zaten biliyoruz. Bu nedenle, var
işlevlerini kolay ve ucuz bir şekilde anında sonuçlarıyla değiştirebiliriz. Bu da 2. adımda yaptığımız gibi "Bu var
çağrısının sonucu bir renk mi?" gibi soruları kolayca yanıtlamamızı sağlar.
2. Aşama: Yukarıdan aşağıya oluşturma
İkinci aşama için yönü tersine çeviririz. 1. aşamadaki eşleşme sonuçlarını kullanarak ağacı yukarıdan aşağıya doğru sırayla dolaşarak HTML olarak oluşturuyoruz. Ziyaret edilen her düğüm için eşleşip eşleşmediğini kontrol ederiz. Eşleşirse eşleştiricinin ilgili oluşturucusunu çağırırız. Metin düğümleri için varsayılan bir eşleyici ve oluşturucu ekleyerek yalnızca metin içeren düğümler (NumberLiteral
"%50" gibi) için özel işleme gerek kalmamasını sağlarız. Oluşturucular, bir araya getirildiğinde süslemeleri de dahil olmak üzere mülk değerinin temsilini oluşturan HTML düğümleri oluşturur.
Örnek ağaçta, mülk değerinin oluşturulma sırası şu şekildedir:
hsl
işlev çağrısını ziyaret edin. Eşleşme olduğu için renk işlevi oluşturucusunu çağırın. İki işlevi vardır:- Herhangi bir
var
bağımsız değişkeni için anında değiştirme mekanizmasını kullanarak gerçek renk değerini hesaplar, ardından bir renk simgesi çizer. CallExpression
öğesinin alt öğelerini yinelemeli olarak oluşturur. Bu işlem, işlev adını, parantezleri ve virgülleri (yalnızca metin olan) otomatik olarak oluşturur.
- Herhangi bir
hsl
çağrısının ilk bağımsız değişkenini ziyaret edin. Eşleşme olduğu için açı simgesini ve açı metnini çizen açı oluşturucuyu çağırın.var
çağrısı olan ikinci bağımsız değişkeni ziyaret edin. Eşleştiğinden var renderer öğesini çağırın. Bu işlem şu sonucu verir:- Başında
var(
metni. - Değişken adını, değişkenin tanımının bağlantısıyla veya tanımlanmadığını belirtmek için gri metin rengiyle süsler. Ayrıca, değişkene değeri hakkında bilgi göstermek için bir pop-up ekler.
- Virgülle ayrılan yedek değer, yinelemeli olarak oluşturulur.
- Kapanış parantezi.
- Başında
hsl
çağrısının son bağımsız değişkenini ziyaret edin. Eşleşme olmadığı için yalnızca metin içeriğini döndürür.
Bu algoritmada, eşleşen bir düğümün alt öğelerinin nasıl oluşturulacağının tamamen bir oluşturma işlemi tarafından kontrol edildiğini fark ettiniz mi? Alt öğeleri yinelemeli olarak oluşturmak proaktiftir. Normal ifade tabanlı oluşturmadan söz dizimi ağacı tabanlı oluşturmaya adım adım geçişi sağlayan şey bu hiledir. Eski bir normal ifade eşleştiriciyle eşleşen düğümler için karşılık gelen oluşturucu orijinal biçiminde kullanılabilir. Söz dizimi ağacı terimleriyle, alt ağacın tamamını oluşturmaktan sorumlu olacaktı ve sonucu (bir HTML düğümü) etrafındaki oluşturma işlemine temiz bir şekilde eklenebilir. Bu sayede eşleştiricileri ve oluşturma araçlarını çiftler halinde taşıma ve tek tek değiştirme seçeneği elde ettik.
Eşleşen düğümün çocuklarının oluşturulmasını kontrol eden oluşturma araçlarının bir diğer harika özelliği, eklediğimiz simgeler arasındaki bağımlılıklarla ilgili çıkarım yapmamızı sağlamasıdır. Yukarıdaki örnekte, hsl
işlevi tarafından üretilen renk, ton değerine bağlıdır. Yani renk simgesinin gösterdiği renk, açı simgesinin gösterdiği açıya bağlıdır. Kullanıcı bu simge aracılığıyla açı düzenleyiciyi açıp açıyı değiştirirse artık renk simgesinin rengini gerçek zamanlı olarak güncelleyebiliriz:
Yukarıdaki örnekte de görebileceğiniz gibi, bu mekanizmayı diğer simge eşlemelerinde de kullanırız. Örneğin, color-mix()
ve iki renk kanalı veya yedek kaynağından bir renk döndüren var
işlevleri.
Performansa olan etkisi
Güvenilirliği artırmak ve uzun süredir devam eden sorunları düzeltmek için bu soruna derinlemesine baktığımızda, tam teşekküllü bir ayrıştırıcıyı kullanmaya başladığımız için performansta bir miktar gerileme bekledik. Bunu test etmek için yaklaşık 3.500 mülk beyanını oluşturan ve M1 makinesinde 6 kat azaltma oranıyla hem normal ifade tabanlı hem de ayrıştırıcı tabanlı sürümleri profilleyen bir karşılaştırma testi oluşturduk.
Beklediğimiz gibi, bu durumda ayrıştırmaya dayalı yaklaşımın normal ifadeye dayalı yaklaşımdan% 27 daha yavaş olduğu ortaya çıktı. Normal ifade tabanlı yaklaşımın oluşturulması 11 sn, ayrıştırıcı tabanlı yaklaşımın oluşturulması 15 saniye sürdü.
Yeni yaklaşımdan elde ettiğimiz kazanımları göz önünde bulundurarak bu yaklaşımda ilerlemeye karar verdik.
Teşekkür ederiz
Bu gönderiyi düzenleme konusunda verdikleri paha biçilmez yardımları için Sofia Emelianova ve Jecelyn Yeen'e minnettarız.
Ö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ı YouTube videolarındaki yenilikler veya Geliştirici Araçları İpuçları YouTube videolarına yorum yazın.