Dalam modul terakhir, diberikan ringkasan tentang pekerja web. Pekerja web dapat meningkatkan responsivitas input dengan memindahkan JavaScript dari thread utama ke thread pekerja web terpisah, yang dapat membantu meningkatkan Interaction to Next Paint (INP) situs Anda saat Anda memiliki pekerjaan yang tidak memerlukan akses langsung ke thread utama. Namun, ringkasan saja tidak cukup, dan dalam modul ini, kasus penggunaan konkret untuk pekerja web ditawarkan.
Salah satu kasus penggunaan tersebut dapat berupa situs yang perlu menghapus metadata Exif dari gambar. Ini bukanlah konsep yang terlalu kaku. Bahkan, situs seperti Flickr menawarkan cara kepada pengguna untuk melihat metadata Exif guna mempelajari detail teknis tentang gambar yang mereka host, seperti kedalaman warna, merek dan model kamera, serta data lainnya.
Namun, logika untuk mengambil gambar, mengonversinya menjadi ArrayBuffer
, dan mengekstrak metadata Exif dapat berpotensi mahal jika dilakukan sepenuhnya di thread utama. Untungnya, cakupan pekerja web memungkinkan pekerjaan ini yang dilakukan
dari thread utama. Kemudian, dengan menggunakan pipeline pesan pekerja web, metadata Exif akan ditransmisikan kembali ke thread utama sebagai string HTML, dan ditampilkan kepada pengguna.
Tampilan thread utama tanpa pekerja web
Pertama, amati tampilan thread utama saat kita melakukan pekerjaan ini tanpa pekerja web. Caranya, lakukan langkah-langkah berikut:
- Buka tab baru di Chrome, dan buka DevTools.
- Buka panel performa.
- Buka https://exif-worker.glitch.me/without-worker.html.
- Di panel performa, klik Record di sudut kanan atas panel DevTools.
- Tempel link gambar ini—atau link lain pilihan Anda yang berisi metadata Exif—di kolom, lalu klik tombol Dapatkan JPEG!.
- Setelah antarmuka diisi dengan metadata Exif, klik Record lagi untuk berhenti merekam.
Perlu diperhatikan bahwa—selain thread lain yang mungkin ada, seperti thread rasterizer dan sebagainya—semua yang ada dalam aplikasi terjadi di thread utama. Di thread utama, hal berikut akan terjadi:
- Formulir ini akan mengambil input dan mengirimkan permintaan
fetch
untuk mendapatkan bagian awal dari gambar yang berisi metadata Exif. - Data gambar dikonversi menjadi
ArrayBuffer
. - Skrip
exif-reader
digunakan untuk mengekstrak metadata Exif dari gambar. - Metadata disalin untuk membuat string HTML, yang kemudian mengisi penampil metadata.
Sekarang, bandingkan dengan penerapan perilaku yang sama—tetapi menggunakan pekerja web.
Tampilan thread utama dengan pekerja web
Setelah Anda melihat proses mengekstrak metadata Exif dari file JPEG di thread utama, lihat tampilan saat pekerja web digabungkan:
- Buka tab lain di Chrome, dan buka DevTools.
- Buka panel performa.
- Buka https://exif-worker.glitch.me/with-worker.html.
- Di panel performa, klik tombol record di sudut kanan atas panel DevTools.
- Tempel link gambar ini di kolom, lalu klik tombol Dapatkan JPEG!.
- Setelah antarmuka diisi dengan metadata Exif, klik tombol record lagi untuk berhenti merekam.
Ini adalah kekuatan pekerja web. Alih-alih melakukan semuanya di thread utama, semuanya kecuali mengisi penampil metadata dengan HTML dilakukan pada thread terpisah. Ini berarti thread utama dibebaskan untuk melakukan tugas lain.
Mungkin keuntungan terbesar di sini adalah, tidak seperti versi aplikasi ini yang
tidak menggunakan pekerja web, skrip exif-reader
tidak dimuat di thread
utama, melainkan di thread pekerja web. Artinya, biaya untuk mendownload, mengurai, dan mengompilasi skrip exif-reader
akan dibebankan di luar thread utama.
Sekarang untuk mendalami kode pekerja web yang memungkinkan semua ini.
Melihat kode pekerja web
Melihat perbedaan yang dibuat pekerja web tidaklah cukup, tetapi juga membantu memahami—setidaknya dalam kasus ini—seperti apa kode tersebut sehingga Anda tahu apa yang mungkin dilakukan dalam cakupan pekerja web.
Mulailah dengan kode thread utama yang perlu terjadi sebelum pekerja web dapat memasukkan gambar:
// 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';
});
Kode ini berjalan pada thread utama, dan menyiapkan formulir untuk mengirim URL gambar ke
pekerja web. Dari sana, kode pekerja web dimulai dengan pernyataan importScripts
yang memuat skrip exif-reader
eksternal, lalu menyiapkan
pipeline pesan ke thread utama:
// 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);
});
});
Bit JavaScript ini menyiapkan pipeline pesan sehingga saat pengguna
mengirimkan formulir dengan URL ke file JPEG, URL tersebut tiba di pekerja web.
Dari sana, bit kode berikutnya ini mengekstrak metadata Exif dari file JPEG,
membuat string HTML, dan mengirimkan HTML tersebut kembali ke window
untuk akhirnya
ditampilkan kepada pengguna:
// 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('')
});
});
});
});
Agak sulit dibaca, tetapi ini juga merupakan kasus penggunaan yang cukup rumit bagi pekerja web.
Namun, hasilnya sepadan dengan hasil kerja, dan tidak hanya terbatas pada kasus penggunaan ini.
Anda dapat menggunakan pekerja web untuk segala macam hal, seperti mengisolasi panggilan fetch
dan memproses respons, memproses data dalam jumlah besar tanpa memblokir
thread utama—dan itu hanya sebagai pemicu.
Saat meningkatkan performa aplikasi web Anda, mulailah memikirkan apa pun yang dapat dilakukan secara wajar dalam konteks pekerja web. Peningkatannya bisa signifikan, dan dapat menghasilkan pengalaman pengguna yang lebih baik secara keseluruhan untuk situs Anda.