Web çalışanının somut kullanım alanı

Son modülde web çalışanlarına genel bir bakış sunulmuştu. Web çalışanları, JavaScript'i ana iş parçacığından ayrı web çalışanı iş parçacıklarına taşıyarak giriş yanıt hızını artırabilir. Bu, ana iş parçacığına doğrudan erişim gerektirmeyen işleriniz olduğunda web sitenizin Sonraki Boyamaya Kadar Etkileşim (INP) metriğini iyileştirmeye yardımcı olabilir. Ancak yalnızca bir genel bakış yeterli değildir ve bu modülde, web çalışanı için somut bir kullanım alanı sunulmaktadır.

Böyle bir kullanım alanına örnek olarak, bir resimden Exif meta verilerini kaldırması gereken bir web sitesi verilebilir. Bu, çok da uzak bir ihtimal değildir. Hatta Flickr gibi web siteleri, kullanıcıların barındırdıkları resimlerle ilgili teknik ayrıntıları (ör. renk derinliği, kamera markası ve modeli) ve diğer verileri öğrenmek için Exif meta verilerini görüntülemelerine olanak tanır.

Ancak bir resmi getirme, ArrayBuffer biçimine dönüştürme ve Exif meta verilerini ayıklama mantığı tamamen ana iş parçacığında yapılırsa maliyetli olabilir. Neyse ki web çalışanı kapsamı, bu çalışmanın ana iş parçacığı dışında yapılmasını sağlar. Ardından, web worker'ın mesajlaşma hattı kullanılarak Exif meta verileri, HTML dizesi olarak ana iş parçacığına geri iletilir ve kullanıcıya gösterilir.

Ana iş parçacığının web çalışanı olmadan görünümü

İlk olarak, bu işi web çalışanı olmadan yaptığımızda ana iş parçacığının nasıl göründüğünü gözlemleyin. Bunun için aşağıdaki adımları uygulayın:

  1. Chrome'da yeni bir sekme açın ve bu sekmenin Geliştirici Araçları'nı açın.
  2. Performans panelini açın.
  3. https://chrome.dev/learn-performance-exif-worker/without-worker.html adresine gidin.
  4. Performans panelinde, Geliştirici Araçları bölmesinin sağ üst köşesindeki Kaydet'i tıklayın.
  5. Alana bu resim bağlantısını veya Exif meta verileri içeren başka bir bağlantıyı yapıştırın ve Get that JPEG! (Bu JPEG'i Al!) düğmesini tıklayın.
  6. Arayüz Exif meta verileriyle dolduktan sonra kaydı durdurmak için Kaydet'i tekrar tıklayın.
Görüntü meta veri ayıklayıcı uygulamasının etkinliğinin tamamen ana iş parçacığında gerçekleştiğini gösteren performans profil oluşturucu. İki önemli uzun görev vardır: Biri istenen resmi almak ve kodunu çözmek için getirme işlemi çalıştırır, diğeri ise resimden meta verileri çıkarır.
Resim meta verisi ayıklayıcı uygulamasındaki ana iş parçacığı etkinliği. Tüm etkinliğin ana iş parçacığında gerçekleştiğini unutmayın.

Uygulamadaki her şeyin ana iş parçacığında gerçekleştiğini unutmayın. Diğer iş parçacıklarının (ör. rasterleştirici iş parçacıkları) varlığı bu durumu değiştirmez. Ana iş parçacığında şunlar olur:

  1. Form, girişi alır ve Exif meta verilerini içeren görüntünün ilk bölümünü almak için fetch isteği gönderir.
  2. Resim verileri ArrayBuffer biçimine dönüştürülür.
  3. exif-reader komut dosyası, Exif meta verilerini resimden çıkarmak için kullanılır.
  4. Üst veriler, bir HTML dizesi oluşturmak için ayrıştırılır ve ardından üst veri görüntüleyiciye aktarılır.

Şimdi de aynı davranışın web worker kullanılarak uygulandığı durumu karşılaştırın.

Web çalışanı ile ana iş parçacığının görünümü

Ana iş parçacığında bir JPEG dosyasından Exif meta verilerini ayıklamanın nasıl göründüğünü gördüğünüze göre, bir web çalışanı işin içine girdiğinde nasıl göründüğüne bir göz atalım:

  1. Chrome'da başka bir sekme açın ve bu sekmenin Geliştirici Araçları'nı açın.
  2. Performans panelini açın.
  3. https://chrome.dev/learn-performance-exif-worker/with-worker.html adresine gidin.
  4. Performans panelinde, Geliştirici Araçları bölmesinin sağ üst köşesindeki kayıt düğmesini tıklayın.
  5. Alana bu resim bağlantısını yapıştırın ve Get that JPEG! (JPEG'i al!) düğmesini tıklayın.
  6. Arayüz Exif meta verileriyle doldurulduktan sonra kaydı durdurmak için kayıt düğmesini tekrar tıklayın.
Hem ana iş parçacığında hem de web çalışanı iş parçacığında gerçekleşen görüntü meta verileri ayıklayıcı uygulamasının etkinliğini gösteren performans profil oluşturucu. Ana iş parçacığında hâlâ uzun görevler olsa da bunlar önemli ölçüde daha kısadır. Resim getirme/kod çözme ve meta veri ayıklama işlemleri tamamen bir web çalışanı iş parçacığında gerçekleşir. Ana iş parçacığıyla ilgili tek işlem, verileri web çalışanıyla aktarmaktır.
Resim meta verileri ayıklayıcı uygulamasındaki ana iş parçacığı etkinliği. İşin büyük bir kısmının yapıldığı ek bir web çalışanı iş parçacığı olduğunu unutmayın.

Bu, web worker'ın gücüdür. Ana iş parçacığında her şeyi yapmak yerine, meta veri görüntüleyicinin HTML ile doldurulması dışında her şey ayrı bir iş parçacığında yapılır. Bu, ana iş parçacığının diğer işleri yapabilmesi için serbest bırakıldığı anlamına gelir.

Buradaki en büyük avantaj, bu uygulamanın web çalışanı kullanmayan sürümünün aksine exif-reader komut dosyasının ana iş parçacığına değil, web çalışanı iş parçacığına yüklenmesidir. Bu, exif-reader komut dosyasının indirilmesi, ayrıştırılması ve derlenmesi maliyetinin ana iş parçacığı dışında gerçekleştiği anlamına gelir.

Şimdi de tüm bunları mümkün kılan web çalışanı koduna geçelim.

Web çalışanı koduna bakış

Web worker'ın ne gibi bir fark yarattığını görmek yeterli değildir. Bu durumda, web worker kapsamı içinde neler yapılabileceğini anlamak için kodun nasıl göründüğünü de bilmek gerekir.

Web çalışanı devreye girmeden önce gerçekleşmesi gereken ana iş parçacığı koduyla başlayın:

// scripts.js

// Register the Exif reader web worker:
const exifWorker = new Worker('/js/with-worker/exif-worker.js');

// We have to send image requests through this proxy due to CORS limitations:
const imageFetchPrefix = 'https://res.cloudinary.com/demo/image/fetch/';

// Necessary elements we need to select:
const imageFetchPanel = document.getElementById('image-fetch');
const imageExifDataPanel = document.getElementById('image-exif-data');
const exifDataPanel = document.getElementById('exif-data');
const imageInput = document.getElementById('image-url');

// What to do when the form is submitted.
document.getElementById('image-form').addEventListener('submit', event => {
  // Don't let the form submit by default:
  event.preventDefault();

  // Send the image URL to the web worker on submit:
  exifWorker.postMessage(`${imageFetchPrefix}${imageInput.value}`);
});

// This listens for the Exif metadata to come back from the web worker:
exifWorker.addEventListener('message', ({ data }) => {
  // This populates the Exif metadata viewer:
  exifDataPanel.innerHTML = data.message;
  imageFetchPanel.style.display = 'none';
  imageExifDataPanel.style.display = 'block';
});

Bu kod, ana iş parçacığında çalışır ve resmi URL'sini web worker'a göndermek için formu ayarlar. Buradan itibaren web çalışanı kodu, harici importScripts betiğini yükleyen bir exif-reader ifadesiyle başlar ve ardından ana ileti dizisiyle mesajlaşma hattını oluşturur:

// exif-worker.js

// Import the exif-reader script:
importScripts('/js/with-worker/exifreader.js');

// Set up a messaging pipeline to send the Exif data to the `window`:
self.addEventListener('message', ({ data }) => {
  getExifDataFromImage(data).then(status => {
    self.postMessage(status);
  });
});

Bu JavaScript kodu, kullanıcının JPEG dosyasına ait bir URL içeren formu göndermesi durumunda URL'nin web worker'a ulaşması için mesajlaşma ardışık düzenini ayarlar. Bu noktadan sonra, aşağıdaki kod parçası JPEG dosyasından Exif meta verilerini çıkarır, bir HTML dizesi oluşturur ve bu HTML'yi sonunda kullanıcıya gösterilmek üzere window'ya geri gönderir:

// Takes a blob to transform the image data into an `ArrayBuffer`:
// NOTE: these promises are simplified for readability, and don't include
// rejections on failures. Check out the complete web worker code:
// https://chrome.dev/learn-performance-exif-worker/js/with-worker/exif-worker.js
const readBlobAsArrayBuffer = blob => new Promise(resolve => {
  const reader = new FileReader();

  reader.onload = () => {
    resolve(reader.result);
  };

  reader.readAsArrayBuffer(blob);
});

// Takes the Exif metadata and converts it to a markup string to
// display in the Exif metadata viewer in the DOM:
const exifToMarkup = exif => Object.entries(exif).map(([exifNode, exifData]) => {
  return `
    <details>
      <summary>
        <h2>${exifNode}</h2>
      </summary>
      <p>${exifNode === 'base64' ? `<img src="data:image/jpeg;base64,${exifData}">` : typeof exifData.value === 'undefined' ? exifData : exifData.description || exifData.value}</p>
    </details>
  `;
}).join('');

// Fetches a partial image and gets its Exif data
const getExifDataFromImage = imageUrl => new Promise(resolve => {
  fetch(imageUrl, {
    headers: {
      // Use a range request to only download the first 64 KiB of an image.
      // This ensures bandwidth isn't wasted by downloading what may be a huge
      // JPEG file when all that's needed is the metadata.
      'Range': `bytes=0-${2 ** 10 * 64}`
    }
  }).then(response => {
    if (response.ok) {
      return response.clone().blob();
    }
  }).then(responseBlob => {
    readBlobAsArrayBuffer(responseBlob).then(arrayBuffer => {
      const tags = ExifReader.load(arrayBuffer, {
        expanded: true
      });

      resolve({
        status: true,
        message: Object.values(tags).map(tag => exifToMarkup(tag)).join('')
      });
    });
  });
});

Okuması biraz uzun olsa da bu, web çalışanları için oldukça karmaşık bir kullanım alanıdır. Ancak sonuçlar, bu kullanım alanıyla sınırlı olmamak üzere çabaya değer. Web worker'ları, fetch çağrılarını yalıtma ve yanıtları işleme, ana iş parçacığını engellemeden büyük miktarda veriyi işleme gibi birçok farklı amaçla kullanabilirsiniz.

Web uygulamalarınızın performansını artırırken web çalışanı bağlamında makul bir şekilde yapılabilecek her şeyi düşünmeye başlayın. Bu iyileştirmeler önemli kazançlar sağlayabilir ve web sitenizde genel olarak daha iyi bir kullanıcı deneyimi sunabilir.