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

Son modülde, web çalışanlarına genel bir bakış sunuldu. Web çalışanları, JavaScript'i ana iş parçacığından ayrı web çalışanı iş parçacıklarına taşıyarak giriş duyarlılığını iyileştirebilir. Bu da, ana iş parçacığına doğrudan erişime ihtiyaç duymayan çalışmanız olduğunda web sitenizin Next Paint'e Etkileşimi (INP) özelliğini iyileştirmeye yardımcı olabilir. Ancak genel bakış tek başına yeterli değildir ve bu modülde, bir web çalışanı için somut bir kullanım alanı sunulmaktadır.

Bu tür bir kullanım alanlarından biri, Exif meta verilerini resimden çıkarması gereken bir web sitesi olabilir. Bu, çok ileri düzey bir kavram değildir. Aslında Flickr gibi web siteleri, kullanıcılara barındırdıkları resimlerle ilgili renk derinliği, kamera markası, modeli ve diğer veriler gibi teknik ayrıntıları öğrenmek için Exif meta verilerini görüntülemenin bir yolunu sunar.

Bununla birlikte, görüntüyü getirme, ArrayBuffer biçimine dönüştürme ve EXIF meta verilerini çıkarma mantığı tamamen ana iş parçacığında yapılırsa potansiyel olarak pahalı olabilir. Neyse ki web çalışanı kapsamı bu işin ana iş parçacığının dışında gerçekleştirilmesine olanak tanıyor. Ardından, web çalışanının mesajlaşma ardışık düzeni kullanılarak EXif meta verileri ana iş parçacığına bir HTML dizesi olarak geri gönderilir ve kullanıcıya gösterilir.

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

Öncelikle, bu işi bir 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 Geliştirici Araçları'nı açın.
  2. Performans panelini açın.
  3. https://exif-worker.glitch.me/without-worker.html adresine gidin.
  4. Performans panelinde, Geliştirici Araçları bölmesinin sağ üst köşesindeki Kayıt'ı tıklayın.
  5. Bu resim bağlantısını veya EXIF meta verilerini içeren başka bir bağlantıyı alana yapıştırın ve O JPEG'i al! düğmesini tıklayın.
  6. Arayüz EXIF meta verileriyle doldurulduktan sonra kaydı durdurmak için tekrar Kaydet'i tıklayın.
Resim meta veri ayıklayıcı uygulamasının tamamen ana iş parçacığında gerçekleşen etkinliğini gösteren performans profil aracı. İki önemli uzun görev vardır: Biri istenen resmi almak ve kodunu çözmek için getirme işlemi gerçekleştirir, diğeri ise resimdeki meta verileri ayıklar.
Resim meta veri 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.

Mevcut olabilecek diğer iş parçacıklarının (ör. kafesleyici iş parçacıkları vb.) dışında, uygulamadaki her şeyin ana iş parçacığında gerçekleştiğini unutmayın. Ana iş parçacığında aşağıdakiler gerçekleşir:

  1. Form, girişi alır ve EXIF meta verilerini içeren resmin ilk bölümünü almak için bir fetch isteği gönderir.
  2. Resim verileri ArrayBuffer biçimine dönüştürülür.
  3. exif-reader komut dosyası, resimden EXIF meta verilerini ayıklamak için kullanılır.
  4. Meta veriler, bir HTML dizesi oluşturmak için kazınır ve ardından meta veri görüntüleyiciyi doldurur.

Şimdi bunu, aynı davranışın bir web çalışanı kullanılarak uygulanmasıyla karşılaştırın.

Ana iş parçacığının bir web çalışanı ile nasıl göründüğü

Ana iş parçacığında bir JPEG dosyasından EXIF meta verilerini çıkarmak için nelerin göründüğünü öğrendiğinize göre, bir web çalışanının da dahil olması durumunda nasıl göründüğüne bir göz atın:

  1. Chrome'da başka bir sekme açın ve Geliştirici Araçları'nı açın.
  2. Performans panelini açın.
  3. https://exif-worker.glitch.me/with-worker.html adresine gidin.
  4. Performans panelinde, Geliştirici Araçları bölmesinin sağ üst köşesindeki kaydet düğmesini tıklayın.
  5. Bu resim bağlantısını alana yapıştırın ve JPEG'i al! düğmesini tıklayın.
  6. Arayüz EXIF meta verileriyle doldurulduktan sonra kaydı durdurmak için tekrar kaydet düğmesini tıklayın.
Hem ana iş parçacığında hem de bir web çalışanı iş parçacığında gerçekleşen resim meta veri ayıklayıcı uygulamasının etkinliğini gösteren performans profil aracı. Ana iş parçacığında hâlâ uzun görevler olsa da resim getirme/kod çözme ve meta veri çıkarma işlemi tamamen bir web çalışanı iş parçacığında gerçekleştiğinden bu görevler önemli ölçüde daha kısadır. Ana iş parçacığı çalışması, web çalışanına ve web çalışanından veri iletmeyi içerir.
Resim meta veri ayıklayıcı uygulamasındaki ana iş parçacığı etkinliği. İşin büyük bir kısmının tamamlandığı ek bir web çalışanı iş parçacığı olduğunu unutmayın.

Bu, web çalışanının gücüdür. Ana iş parçacığında her şeyi yapmak yerine, meta veri görüntüleyicinin HTML ile doldurulması hariç her şey ayrı bir iş parçacığında gerçekleştirilir. Bu, ana iş parçacığının başka işler yapmak için serbest kaldığı anlamına gelir.

Buradaki en büyük avantaj, muhtemelen bu uygulama sürümünü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. Yani exif-reader komut dosyasını indirme, ayrıştırma ve derleme maliyeti, ana iş parçacığından alınır.

Şimdi, bunların tümünü mümkün kılan web çalışanı kodunu ele alalım.

Web çalışanı koduna bakış

Web çalışanının yaptığı farkı görmek yeterli değildir. Aynı zamanda bu kodun (en azından bu örnekte) nasıl göründüğünü anlamak için de yardımcı olur. Böylece, web çalışanı kapsamında neler yapılabileceğini bilirsiniz.

Web çalışanının resmi girmeden önce oluşturulması 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 formu, resim URL'sini web çalışanına gönderecek şekilde ayarlar. Ardından, web çalışanı kodu, harici exif-reader komut dosyasını yükleyen bir importScripts ifadesiyle başlar ve ardından mesajlaşma ardışık düzenini ana iş parçacığına ayarlar:

// 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 parçası, mesajlaşma ardışık düzenini ayarlar. Böylece, kullanıcı formu bir JPEG dosyasına URL ile gönderdiğinde, URL web çalışanına ulaşır. Ardından, sonraki kod parçası, JPEG dosyasından EXIF meta verilerini ayıklar, bir HTML dizesi oluşturur ve en sonunda kullanıcıya gösterilmek üzere bu HTML'yi window uygulamasına 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://glitch.com/edit/#!/exif-worker?path=js%2Fwith-worker%2Fexif-worker.js%3A10%3A5
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('')
      });
    });
  });
});

Okunması biraz uzun bir metin olsa da web çalışanları için oldukça yaygın bir kullanım alanıdır. Ancak elde edilen sonuçlar bu kullanım alanıyla sınırlı değil, çalışmaya değer. Web çalışanlarını, fetch çağrılarını izole etmek, yanıtları işlemek, ana iş parçacığını engellemeden büyük miktarda veri işlemek gibi her türlü işlem için kullanabilirsiniz. Bu, yalnızca başlangıç için geçerlidir.

Web uygulamalarınızın performansını iyileştirirken, web çalışanı bağlamında makul bir şekilde yapılabilecek her şeyi düşünmeye başlayın. Kazançlar önemli olabilir ve web siteniz için genel olarak daha iyi bir kullanıcı deneyimi sağlayabilir.