Komut dosyası değerlendirmesi ve uzun görevler

Komut dosyaları yüklenirken, tarayıcının bunları yürütmeden önce değerlendirmesi zaman alır. Bu da görevlerin uzun sürmesine neden olabilir. Komut dosyası değerlendirmesinin işleyiş şeklini ve sayfa yükleme sırasında uzun görevlere neden olmaması için neler yapabileceğinizi öğrenin.

Interaction to Next Paint (INP) metriğini optimize etme konusunda karşılaşacağınız çoğu tavsiye, etkileşimleri optimize etmektir. Örneğin, uzun görevleri optimize etme kılavuzunda setTimeout ile verim sağlama gibi teknikler ele alınmaktadır. Bu teknikler, uzun görevlerden kaçınarak ana iş parçacığına nefes alma alanı tanıdığı için yararlıdır. Bu sayede, tek bir uzun görev için beklemek yerine daha fazla etkileşim ve diğer etkinliğin daha erken çalışmasına olanak tanıyabilir.

Ancak komut dosyalarının yüklenmesinden kaynaklanan uzun görevler ne olacak? Bu görevler kullanıcı etkileşimlerini engelleyebilir ve sayfanın yükleme sırasındaki INP'sini etkileyebilir. Bu kılavuzda, tarayıcıların komut dosyası değerlendirmesi tarafından başlatılan görevleri nasıl işlediği incelenecek ve sayfa yüklenirken ana iş parçacığınızın kullanıcı girişine daha duyarlı olabilmesi için komut dosyası değerlendirme çalışmasını bölmek üzere neler yapabileceğiniz ele alınacaktır.

Komut dosyası değerlendirmesi nedir?

Çok fazla JavaScript yayınlayan bir uygulamanın profilini oluşturduysanız sorunun kaynağının Komutu Değerlendir olarak etiketlendiği uzun görevler görmüş olabilirsiniz.

Komut dosyası değerlendirmesi, Chrome Geliştirici Araçları'nın performans profilleyicisinde görselleştirildiği şekilde çalışır. Bu işlem, başlangıç sırasında uzun bir görev oluşturur ve ana iş parçacığının kullanıcı etkileşimlerine yanıt verme özelliğini engeller.
Chrome Geliştirici Araçları'ndaki performans profil aracı bölümünde gösterildiği gibi komut dosyası değerlendirme işlemi Bu durumda, iş, ana iş parçacığının kullanıcı etkileşimlerini artıran görevler de dahil olmak üzere başka işler almasını engelleyen uzun bir göreve neden olacak kadar fazladır.

JavaScript yürütmeden hemen önce derlendiğinden komut dosyası değerlendirmesi, JavaScript'in tarayıcıda yürütülmesinin gerekli bir parçasıdır. Bir komut dosyası değerlendirilirken önce hatalar için ayrıştırılır. Ayrıştırıcı hata bulamazsa komut dosyası bayt kodu olarak derlenir ve ardından yürütmeye devam edebilir.

Gerekli olsa da kullanıcılar sayfa ilk oluşturulduktan kısa bir süre sonra sayfayla etkileşim kurmaya çalışabileceğinden komut dosyası değerlendirmesi sorunlu olabilir. Ancak bir sayfanın oluşturulmuş olması, sayfanın yüklenmesi işleminin tamamlandığı anlamına gelmez. Sayfa komut dosyalarını değerlendirirken meşgul olduğu için yükleme sırasında gerçekleşen etkileşimler gecikebilir. Etkileşimin, söz konusu noktada (ilgili komut dosyası henüz yüklenmemiş olabileceği için) gerçekleşebileceğine dair bir garanti yoktur, ancak hazır olan JavaScript'e bağlı etkileşimler olabilir veya etkileşimlilik JavaScript'e bağlı olmayabilir.

Senaryolar ve bunları değerlendiren görevler arasındaki ilişki

Komut dosyası değerlendirmesinden sorumlu görevlerin nasıl başlatılacağı, yüklediğiniz komut dosyasının tipik bir <script> öğesiyle mi yoksa type=module ile yüklenen bir modülle mi yüklenmesine bağlıdır. Tarayıcılar her şeyi farklı şekilde ele alma eğiliminde olduğundan, büyük tarayıcı motorlarının komut dosyası değerlendirmesini nasıl ele aldığına değinilecek ve komut dosyası değerlendirme davranışları arasında farklılıklar olduğunda bunlara değinilecektir.

<script> öğesiyle yüklenen komut dosyaları

Komut dosyalarını değerlendirmek için gönderilen görevlerin sayısı genellikle bir sayfadaki <script> öğelerinin sayısıyla doğrudan ilişkilidir. Her <script> öğesi, istenen komut dosyasının ayrıştırılması, derlenmesi ve yürütülmesi için değerlendirilmesini sağlayan bir görev başlatır. Bu durum Chromium tabanlı tarayıcılar, Safari ve Firefox için de geçerlidir.

Bu neden önemli? Üretim komut dosyalarınızı yönetmek için bir paketleyici kullandığınızı ve bu paketleyiciyi, sayfanızın çalışması için ihtiyaç duyduğu her şeyi tek bir komut dosyasında paketleyecek şekilde yapılandırdığınızı varsayalım. Web siteniz için durum böyleyse söz konusu komut dosyasını değerlendirmek üzere tek bir görev gönderilir. Bu kötü bir durum mu? Bu komut dosyası çok büyük olmadığı sürece bu durum söz konusu değildir.

Büyük JavaScript parçaları yüklemekten kaçınarak komut dosyası değerlendirme çalışmasını bölebilir ve ek <script> öğeleri kullanarak daha fazla sayıda ayrı, küçük komut dosyası yükleyebilirsiniz.

Sayfa yükleme sırasında her zaman mümkün olduğunca az JavaScript yüklemeye çalışmalısınız. Ancak komut dosyalarınızı bölmek, ana iş parçacığını engelleyebilecek tek bir büyük görev yerine, ana iş parçacığını hiç engellemeyecek veya en azından başladığınızdan daha az sayıda küçük görev elde etmenizi sağlar.

Chrome Geliştirici Araçları&#39;nın performans profil aracında görselleştirildiği şekilde komut dosyası değerlendirmesini içeren birden çok görev. Daha az sayıda büyük komut dosyası yerine birden fazla küçük komut dosyası yüklendiğinde görevlerin uzun görev haline gelme olasılığı azalır. Bu da ana iş parçacığının kullanıcı girişlerine daha hızlı yanıt vermesine olanak tanır.
Sayfanın HTML'sinde bulunan birden fazla <script> öğesi nedeniyle komut dosyalarını değerlendirmek için birden fazla görev oluşturuldu. Bu, kullanıcılara tek bir büyük komut dosyası paketi göndermekten daha iyidir. Ana iş parçacığının tıkanması daha olasıdır.

Komut dosyası değerlendirmesi için görevleri bölmeyi, etkileşim sırasında çalışan etkinlik geri çağırmalarında veriye geçmeye biraz benzer olarak düşünebilirsiniz. Ancak komut dosyası değerlendirmesinde, asıl iş parçasını engelleme olasılığı daha yüksek olan daha az sayıda büyük komut dosyası yerine, yüklediğiniz JavaScript'i birden çok küçük komut dosyasına bölen verme mekanizması kullanılır.

<script> öğesi ve type=module özelliğiyle yüklenen komut dosyaları

Artık <script> öğesindeki type=module özelliği ile ES modüllerini tarayıcıya yerel olarak yükleyebilirsiniz. Komut dosyası yüklemeyle ilgili bu yaklaşım, özellikle harita içe aktarma ile birlikte kullanıldığında, kodları üretim kullanımı için dönüştürmek zorunda kalmamak gibi bazı geliştirici deneyimi avantajları sunar. Ancak komut dosyalarını bu şekilde yüklemek, tarayıcıdan tarayıcıya değişen görevler planlar.

Chromium tabanlı tarayıcılar

Chrome gibi tarayıcılarda veya bu tarayıcılardan türetilen tarayıcılarda type=module özelliğini kullanarak ES modüllerini yüklemek, normalde type=module kullanmadığınızda gördüğünüzden farklı türde görevler oluşturur. Örneğin, her modül komut dosyası için Modülü derle olarak etiketlenmiş etkinliği içeren bir görev çalıştırılır.

Modül derleme, Chrome Geliştirici Araçları&#39;nda görselleştirildiği gibi birden çok görevde çalışır.
Chromium tabanlı tarayıcılarda modül yükleme davranışı. Her modül komut dosyası, içeriğini değerlendirmeden önce derlemek için bir Derle modülü çağrısı oluşturur.

Modüller derlendikten sonra, bu modüllerde daha sonra çalıştırılan tüm kodlar Modülü değerlendir olarak etiketlenen etkinliği başlatır.

Chrome Geliştirici Araçları&#39;nın performans panelinde görselleştirilen bir modülün tam zamanında değerlendirmesi.
Bir modüldeki kod çalıştırıldığında söz konusu modül tam zamanında değerlendirilir.

Bu durumda, en azından Chrome ve ilgili tarayıcılarda, ES modülleri kullanıldığında derleme adımlarının bölünmesi söz konusudur. Bu, uzun görevleri yönetme açısından net bir kazançtır. Ancak bunun sonucunda ortaya çıkan modül değerlendirme çalışması, kaçınılmaz bazı maliyetlere katlanmanız anlamına gelir. Mümkün olduğunca az JavaScript göndermeye çalışmalısınız. Ancak tarayıcıdan bağımsız olarak ES modüllerini kullanmak aşağıdaki avantajları sağlar:

  • Tüm modül kodları otomatik olarak katı modda çalıştırılır. Bu, JavaScript motorlarının katı olmayan bir bağlamda yapılamayan olası optimizasyonlar yapmasına olanak tanır.
  • type=module kullanılarak yüklenen komut dosyaları, varsayılan olarak ertelenmiş gibi kabul edilir. Bu davranışı değiştirmek için type=module ile yüklenen komut dosyalarında async özelliğini kullanabilirsiniz.

Safari ve Firefox

Safari ve Firefox'ta yüklenen modüllerin her biri ayrı bir görevde değerlendirilir. Bu, diğer modüllere teorik olarak yalnızca statik import ifadelerinden oluşan tek bir üst düzey modül yükleyebileceğiniz ve yüklenen her modülün ayrı bir ağ isteği ve değerlendirme görevi gerektireceği anlamına gelir.

Dinamik import() ile yüklenen komut dosyaları

Dinamik import(), komut dosyalarını yüklemenin başka bir yöntemidir. Bir ES modülünün en üstünde olması gereken statik import ifadelerin aksine dinamik import() çağrısı, bir JavaScript parçasını isteğe bağlı olarak yüklemek için komut dosyasının herhangi bir yerinde görünebilir. Bu tekniğe kod bölme denir.

Dinamik import(), INP'yi iyileştirme konusunda iki avantaja sahiptir:

  1. Daha sonra yüklenmek üzere ertelenen modüller, o sırada yüklenen JavaScript miktarını azaltarak başlangıç sırasında ana iş parçacığı çekişmesini azaltır. Böylece ana ileti dizisi serbest bırakılır ve kullanıcı etkileşimlerine daha duyarlı olabilir.
  2. Dinamik import() çağrıları yapıldığında her çağrı, her modülün derlenmesini ve değerlendirilmesini kendi görevine etkili bir şekilde ayırır. Elbette, çok büyük bir modül yükleyen dinamik bir import(), oldukça büyük bir komut dosyası değerlendirme görevi başlatır. Bu da etkileşim dinamik import() çağrısıyla aynı anda gerçekleşirse ana iş parçacığının kullanıcı girişine yanıt verme özelliğini etkileyebilir. Bu nedenle, mümkün olduğunca az JavaScript yüklemeniz çok önemlidir.

Dinamik import() çağrıları tüm büyük tarayıcı motorlarında benzer şekilde çalışır: Sonuç olarak ortaya çıkan komut dosyası değerlendirme görevleri, dinamik olarak içe aktarılan modül sayısıyla aynı olur.

Web çalışanına yüklenen komut dosyaları

Web çalışanları, özel bir JavaScript kullanım alanıdır. Web çalışanları ana iş parçacığına kaydedilir ve çalışan içindeki kod kendi iş parçacığında çalışır. Bu, web işçisini kaydeden kodun ana iş parçacığında çalışmasına rağmen web işçisindeki kodun çalışmaması açısından son derece faydalıdır. Bu, ana ileti dizisi sıkışıklığını azaltır ve ana ileti dizisinin kullanıcı etkileşimlerinde daha duyarlı olmasına yardımcı olabilir.

Web çalışanları, ana iş parçacığı çalışmasını azaltmanın yanı sıra modül çalışanlarını destekleyen tarayıcılarda importScripts veya statik import ifadeleri aracılığıyla çalışan bağlamında kullanılacak harici komut dosyaları da kendileri yükleyebilir. Sonuç olarak, bir web çalışanı tarafından istenen tüm komut dosyaları ana iş parçacığının dışında değerlendirilir.

Detaylar ve dikkat edilmesi gereken noktalar

Komut dosyalarınızı ayrı ve daha küçük dosyalara bölmek, daha az sayıda çok daha büyük dosya yüklemek yerine uzun görevleri sınırlandırmaya yardımcı olsa da komut dosyalarını nasıl böleceğinize karar verirken bazı noktaları göz önünde bulundurmanız önemlidir.

Sıkıştırma verimliliği

Komut dosyalarını bölme konusunda sıkıştırma da bir faktördür. Komut dosyaları daha küçük olduğunda, sıkıştırma biraz daha az verimli hale gelir. Daha büyük komut dosyaları sıkıştırmadan çok daha fazla yararlanır. Sıkıştırma verimliliğini artırmak, komut dosyalarının yükleme sürelerini mümkün olduğunca düşük tutmaya yardımcı olsa da komut dosyalarını, başlatma sırasında daha iyi etkileşimi sağlamak için yeterince küçük parçalara ayırmanız gerekir.

Paketleyiciler, web sitenizin bağlı olduğu komut dosyalarının çıkış boyutunu yönetmek için ideal araçlardır:

  • Webpack söz konusu olduğunda SplitChunksPlugin eklentisi yardımcı olabilir. Öğe boyutlarını yönetmeye yardımcı olacak seçenekleri belirlemek için SplitChunksPlugin belgelerini inceleyin.
  • Rollup ve esbuild gibi diğer paketleyiciler için kodunuzda dinamik import() çağrıları kullanarak komut dosyası dosya boyutlarını yönetebilirsiniz. Web paketinin yanı sıra bu paketleyiciler, dinamik olarak içe aktarılan öğeyi otomatik olarak kendi dosyasına ayırır. Böylece ilk paket boyutlarının daha büyük olmasını önlersiniz.

Önbelleği geçersiz kılma

Önbelleği geçersiz kılma, yinelenen ziyaretlerde bir sayfanın ne kadar hızlı yüklendiğini belirlemede büyük bir rol oynar. Büyük, tek parça komut dosyası paketleri yayınladığınızda tarayıcı önbelleğe alma konusunda dezavantajlı olursunuz. Bunun nedeni, birinci taraf kodunuzu güncellediğinizde (paketleri güncelleyerek veya hata düzeltmelerini göndererek) paketin tamamının geçersiz hale gelmesi ve yeniden indirilmesi gerekmesidir.

Komut dosyalarınızı bölerek yalnızca komut dosyası değerlendirme çalışmasını daha küçük görevlere bölemezsiniz, aynı zamanda geri gelen ziyaretçilerin ağ yerine tarayıcı önbelleğinden daha fazla komut dosyası alma olasılığını da artırırsınız. Bu da sayfanın genel olarak daha hızlı yüklenmesine yol açar.

İç içe yerleştirilmiş modüller ve yükleme performansı

ES modüllerini üretimde gönderiyor ve type=module özelliğiyle yüklüyorsanız modül iç içe yerleştirmenin başlatma süresini nasıl etkileyebileceğini bilmeniz gerekir. Modül iç içe yerleştirme, bir ES modülünün statik olarak başka bir ES modülünü içe aktarması ve bu modülün de statik olarak başka bir ES modülünü içe aktarması anlamına gelir:

// a.js
import {b} from './b.js';

// b.js
import {c} from './c.js';

ES modülleriniz birlikte gruplandırılmamışsa önceki kod bir ağ isteği zincirine neden olur: <script> öğesinden a.js istendiğinde b.js için başka bir ağ isteği gönderilir. Bu istek daha sonra c.js için başka bir istek içerir. Bunu önlemenin bir yolu, bir paketleyici kullanmaktır. Ancak paketleyicinizi, komut dosyası değerlendirme çalışmalarını dağıtmak için komut dosyalarını bölecek şekilde yapılandırdığınızdan emin olun.

Paketleyici kullanmak istemiyorsanız iç içe yerleştirilmiş modül çağrılarını atlatmanın bir başka yolu da modulepreload kaynak ipucunu kullanmaktır. Bu ipucu, ağ istek zincirlerini önlemek için ES modüllerini önceden yükler.

Sonuç

Tarayıcıda komut dosyalarının değerlendirmesini optimize etmek hiç şüphesiz zor bir iş. Yaklaşım, web sitenizin gereksinimlerine ve kısıtlamalarına bağlıdır. Ancak komut dosyalarını bölerek komut dosyası değerlendirme çalışmasını çok sayıda küçük göreve dağıtırsınız. Böylece ana iş parçacığının engellenmesini önler ve ana iş parçacığına kullanıcı etkileşimlerini daha verimli bir şekilde yönetme olanağı tanırsınız.

Özetlemek gerekirse, büyük komut dosyası değerlendirme görevlerini bölmek için yapabileceğiniz bazı işlemler şunlardır:

  • type=module özelliği olmadan <script> öğesini kullanarak komut dosyalarını yüklerken, çok büyük olan komut dosyalarını yüklemekten kaçının. Bunlar, ana iş parçacığını engelleyen ve kaynakları yoğun olarak kullanan komut dosyası değerlendirme görevlerini başlatır. Bu işi bölmek için komut dosyalarınızı daha fazla <script> öğesine dağıtın.
  • ES modüllerini tarayıcıya yerel olarak yüklemek için type=module özelliğini kullandığınızda her bir modül komut dosyası için ayrı değerlendirme görevleri başlatılır.
  • Dinamik import() çağrıları kullanarak ilk paketlerinizin boyutunu küçültün. Bu, paketleyiciler üzerinde de çalışır. Çünkü paketleyiciler dinamik olarak içe aktarılan her bir modülü bir "bölünme noktası" olarak işler ve bunun sonucunda, dinamik olarak içe aktarılan her modül için ayrı bir komut dosyası oluşturulur.
  • Sıkıştırma verimliliği ve önbelleğin geçersiz kılınması gibi ödünleşimleri hesaba kattığınızdan emin olun. Daha büyük komut dosyaları daha iyi sıkıştırılır ancak daha az sayıda görevde daha pahalı komut dosyası değerlendirme çalışması içerme olasılığı daha yüksektir ve tarayıcı önbelleğini geçersiz kılar. Bu da genel olarak daha düşük önbelleğe alma verimliliğine yol açar.
  • ES modüllerini paketlenmemiş olarak kullanıyorsanız başlangıç sırasında yüklemelerini optimize etmek için modulepreload kaynak ipucunu kullanın.
  • Her zaman olduğu gibi, mümkün olduğunca az JavaScript gönderin.

Bu kesinlikle bir dengeleme işidir. Ancak komut dosyalarını bölerek ve dinamik import() ile ilk yükleyicileri azaltarak daha iyi bir başlatma performansı elde edebilir ve bu önemli başlatma döneminde kullanıcı etkileşimlerini daha iyi karşılayabilirsiniz. Bu, INP metriğinde daha iyi puan almanıza ve dolayısıyla daha iyi bir kullanıcı deneyimi sunmanıza yardımcı olacaktır.