JavaScript ile Etkileşim Ekleme

Ilya Grigorik
Ilya Grigorik

Yayınlanma tarihi: 31 Aralık 2013

JavaScript’le sayfanın neredeyse her özelliğini, örneğin içerik, ve kullanıcı etkileşimine verdiği tepkidir. Ancak JavaScript, DOM oluşturulmasını engeller ve sayfa oluşturulmasını geciktirir. Optimum içerik sunmak için JavaScript'inizi eşzamansız hale getirin ve gereksiz JavaScript'leri ortadan kaldırın kritik oluşturma yolundan kaldırabilirsiniz.

Özet

  • JavaScript, DOM ve CSSOM'u sorgulayabilir ve değiştirebilir.
  • CSSOM'daki JavaScript yürütme blokları.
  • JavaScript, açıkça async olarak tanımlanmadığı sürece DOM oluşturmayı engeller.

JavaScript, tarayıcıda çalışan dinamik bir dildir ve sayfanın davranışını neredeyse her açıdan değiştirmemize olanak tanır. DOM ağacından öğeler ekleyip kaldırarak içeriği değiştirebiliriz. her bir öğenin CSSOM özelliklerini değiştirebiliriz. kullanıcı girişlerini işleme alabiliriz. ve çok daha fazlası. Bunu açıklamak için, önceki "Hello World" örnek, kısa bir satır içi komut dosyası ekleyecek şekilde değiştirildi:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script>
      var span = document.getElementsByTagName('span')[0];
      span.textContent = 'interactive'; // change DOM text content
      span.style.display = 'inline'; // change CSSOM property
      // create a new element, style it, and append it to the DOM
      var loadTime = document.createElement('div');
      loadTime.textContent = 'You loaded this page on: ' + new Date();
      loadTime.style.color = 'blue';
      document.body.appendChild(loadTime);
    </script>
  </body>
</html>

Deneyin

  • JavaScript, DOM'a ulaşmamıza ve gizli span düğümüne referans çekmemize olanak tanır. Düğüm, oluşturma ağacında görünmeyebilir ancak DOM'da hâlâ mevcuttur. Daha sonra, referans aldığımızda metnini değiştirebilir (.textContent aracılığıyla) ve hatta hesaplanan görüntüleme stili özelliğini "none" yerine geçersiz kılabiliriz "satır içi" duruma getirin. Sayfamızda artık "Merhaba etkileşimli öğrenciler!" ifadesi gösteriliyor.

  • JavaScript ayrıca DOM'de yeni öğeler oluşturma, stil ekleme, ekleme ve kaldırma işlemlerini gerçekleştirmemize de olanak tanır. Teknik olarak, sayfamızın tamamı, öğeleri tek tek oluşturan ve stilize eden büyük bir JavaScript dosyası olabilir. Bu işe yarar ancak uygulamada HTML ve CSS kullanmak çok daha kolaydır. JavaScript işlevimizin ikinci bölümünde, yeni bir div öğesi oluşturur, metin içeriğini ayarlar, stilini belirler ve gövdeye ekleriz.

Mobil cihazda oluşturulan bir sayfanın önizlemesi.

Bununla, mevcut bir DOM düğümünün içeriğini ve CSS stilini değiştirdik ve belgeye tamamen yeni bir düğüm ekledik. Sayfamız tasarım ödülü kazanmayacak olsa da JavaScript'in bize sağladığı gücü ve esnekliği gösteriyor.

Bununla birlikte, JavaScript bize oldukça fazla güç sağlasa da, sayfanın nasıl ve ne zaman oluşturulacağıyla ilgili birçok ek sınırlama oluşturur.

Öncelikle, önceki örnekte satır içi komut dosyamızın sayfanın alt kısmına yakın olduğunu fark edin. Neden? Bu komutu kendiniz denemelisiniz, ancak komut dosyasını <span> öğesinin üzerine taşırsak komut dosyasının başarısız olduğunu görürsünüz ve dokümanın herhangi bir <span> öğesine referans bulamadığından şikayet edersiniz; yani getElementsByTagName('span'), null değerini döndürür. Bu, önemli bir özelliği gösterir: Komut dosyamız tam olarak dokümana eklendiği noktada yürütülür. HTML ayrıştırıcısı bir komut dosyası etiketiyle karşılaştığında, DOM oluşturma işlemini duraklatır ve kontrolü JavaScript motoruna bırakır; JavaScript motorunun çalışması bittikten sonra, tarayıcı kaldığı yerden devam eder ve DOM oluşturma işlemine devam eder.

Diğer bir deyişle, komut dosyası bloğumuz henüz işlenmediği için sayfanın sonraki bölümlerindeki öğeleri bulamıyor. Daha farklı bir ifadeyle: Satır içi komut dosyamızın yürütülmesi DOM oluşturmayı engeller ve bu da ilk oluşturmayı geciktirir.

Sayfamıza komut dosyaları eklemenin bir diğer ince özelliği, komut dosyalarının yalnızca DOM'u değil, CSSOM özelliklerini de okuyup değiştirebilmesidir. Aslında, span öğesinin görüntüleme özelliğini "hiçbiri" yerine satır içi olarak değiştirdiğimizde bunu yaparız. Peki nasıl bir sonuç alacaksınız? Artık bir yarış koşulumuz var.

Komut dosyamızı çalıştırmak istediğimizde tarayıcı CSSOM'u indirip oluşturmayı tamamlamamışsa ne olur? Yanıt, performans açısından pek iyi değil: Tarayıcı, CSSOM'u indirip oluşturmayı tamamlayana kadar komut dosyası yürütme ve DOM oluşturma işlemlerini geciktirir.

Özetle, JavaScript; DOM, CSSOM ve JavaScript yürütme arasında birçok yeni bağımlılık sunar. Bu durum, tarayıcının sayfayı işleme ve ekranda oluşturma konusunda önemli gecikmelere neden olabilir:

  • Dokümandaki komut dosyasının konumu önemli olmalıdır.
  • Tarayıcı bir komut dosyası etiketiyle karşılaştığında, komut dosyası yürütülmeyi tamamlayana kadar DOM oluşturma duraklatılır.
  • JavaScript, DOM ve CSSOM'u sorgulayabilir ve değiştirebilir.
  • CSSOM hazır olana kadar JavaScript yürütme işlemi duraklatılır.

"Kritik oluşturma yolunu optimize etme", büyük ölçüde HTML, CSS ve JavaScript arasındaki bağımlılık grafiğini anlama ve optimize etmeyi ifade eder.

Ayrıştırıcı engelleme ve eşzamansız JavaScript

Varsayılan olarak, JavaScript çalıştırma işlemi "ayırıcı engelleme"dir: Tarayıcı, dokümanda bir komut dosyasıyla karşılaştığında DOM oluşturma işlemini duraklatmalı, kontrolü JavaScript çalışma zamanına teslim etmeli ve DOM oluşturma işlemine devam etmeden önce komut dosyasının yürütülmesine izin vermelidir. Bu yöntemi, önceki örneğimizde bir satır içi komut dosyasında gördük. Aslında, satır içi komut dosyaları, yürütmelerini ertelemek için ek kod yazmadığınız sürece her zaman ayrıştırıcıyı engeller.

Komut dosyası etiketi kullanılarak eklenen komut dosyaları ne olacak? Önceki örneği ele alalım ve kodu ayrı bir dosyaya ayıklayalım:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script External</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js"></script>
  </body>
</html>

app.js

var span = document.getElementsByTagName('span')[0];
span.textContent = 'interactive'; // change DOM text content
span.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);

Deneyin

<script> etiketi veya satır içi JavaScript snippet'i aynı şekilde davranmasını bekleyebilir. Her iki durumda da, tarayıcı duraklatılır ve dokümanın geri kalanını işleyemeden önce komut dosyasını yürütür. Ancak harici bir JavaScript dosyası söz konusu olduğunda, komut dosyasının diskten, önbellekten veya uzak bir sunucudan getirilmesini beklemek için tarayıcı duraklatılmalıdır. Bu da kritik oluşturma yoluna on ila binlerce milisaniyelik gecikme ekleyebilir.

Varsayılan olarak tüm JavaScript'ler ayrıştırıcı tarafından engellenir. Tarayıcı, komut dosyasının sayfada ne yapmayı planladığını bilmediği için en kötü durum senaryosunun geçerli olduğunu varsayar ve ayrıştırıcıyı engeller. Tarayıcıya, komut dosyasının tam olarak başvuruda bulunulan noktada yürütülmesine gerek olmadığını belirten bir sinyal, tarayıcının DOM'yi oluşturmaya devam etmesine ve hazır olduğunda komut dosyasının yürütülmesine izin verir; Örneğin, dosya önbellekten veya uzak sunucudan getirildikten sonra.

Bunu yapmak için async özelliği <script> öğesine eklenir:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path: Script Async</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
    <script src="app.js" async></script>
  </body>
</html>

Deneyin

Komut dosyası etiketine async anahtar kelimesini eklemek, tarayıcıya komut dosyasının kullanılabilir hale gelmesini beklerken DOM oluşturmayı engellememesini söyler. Bu da performansı önemli ölçüde artırabilir.

Geri bildirim