Dalam modul terakhir, telah diberikan ringkasan pekerja web. Pekerja web dapat meningkatkan responsivitas input dengan memindahkan JavaScript dari thread utama untuk thread pekerja web terpisah, yang dapat membantu meningkatkan Interaksi situs Anda ke Next Paint (INP) jika Anda memiliki pekerjaan yang tidak memerlukan akses langsung ke thread utama. Namun, ringkasan saja tidaklah cukup, dan dalam modul ini, kasus penggunaan konkret untuk pekerja web ditawarkan.
Salah satu kasus penggunaan tersebut adalah situs web yang perlu menghapus metadata Exif dari gambar — ini bukan konsep yang tidak masuk akal. Faktanya, situs web seperti Flickr menawarkan cara melihat metadata Exif untuk mempelajari detail teknis tentang gambar yang dihosting, seperti kedalaman warna, merek dan model kamera, serta layanan otomatis dan data skalabel.
Namun, logika untuk mengambil gambar dengan mengonversinya menjadi ArrayBuffer
,
dan mengekstrak {i>metadata<i} Exif bisa berpotensi
mahal jika dilakukan sepenuhnya
di thread utama. Untungnya, ruang lingkup pekerja web
memungkinkan pekerjaan ini dilakukan
keluar dari thread utama. Kemudian, dengan menggunakan
pipeline pesan pekerja web,
Metadata Exif dikirimkan kembali ke thread utama sebagai string HTML, dan
yang ditampilkan kepada pengguna.
Seperti apa 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 Rekam di sudut kanan atas panel DevTools.
- Tempel link gambar ini—atau link lain pilihan Anda yang berisi Exif metadata—di kolom, lalu klik tombol Get that JPEG!.
- Setelah antarmuka diisi dengan metadata Exif, klik Record lagi untuk berhenti merekam.
Perlu diingat bahwa—selain thread lain yang mungkin ada, seperti rasterizer thread dan seterusnya—semua yang ada dalam aplikasi terjadi di thread utama. Di halaman utama , hal berikut akan terjadi:
- Formulir ini mengambil input dan mengirimkan permintaan
fetch
untuk mendapatkan input awal gambar yang berisi metadata Exif. - Data gambar dikonversi menjadi
ArrayBuffer
. - Skrip
exif-reader
digunakan untuk mengekstrak metadata Exif dari gambar. - Metadata disalin untuk membentuk {i>string<i} HTML, yang kemudian mengisi penampil metadata.
Sekarang bandingkan dengan penerapan perilaku yang sama—tetapi menggunakan pekerja!
Tampilan thread utama dengan pekerja web
Sekarang Anda telah melihat seperti apa yang terlihat untuk mengekstrak {i>metadata<i} Exif dari file JPEG di thread utama, lihat bagaimana tampilannya pekerja adalah kombinasi dari:
- 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 rekam di kanan atas pojok panel DevTools.
- Tempel link gambar ini di kolom, lalu klik tombol Get that JPEG!.
- Setelah antarmuka diisi dengan metadata Exif, klik tombol rekam lagi untuk berhenti merekam.
Ini adalah kekuatan pekerja web. Daripada melakukan semuanya di bagian utama utas, semuanya kecuali mengisi penampil metadata dengan HTML dilakukan pada thread terpisah. Ini berarti thread utama dibebaskan untuk melakukan pekerjaan lain.
Mungkin keuntungan terbesarnya adalah, tidak seperti versi aplikasi ini yang
tidak menggunakan pekerja web, skrip exif-reader
tidak dimuat di halaman
tetapi lebih ke thread pekerja web. Ini berarti bahwa biaya
mendownload, mengurai, dan mengompilasi skrip exif-reader
berlangsung dari
thread utama.
Sekarang, mari pelajari kode pekerja web yang membuat semua ini dapat dilakukan!
Memahami kode pekerja web
Tidaklah cukup untuk melihat perbedaan yang dibuat oleh pekerja web, tetapi juga membantu memahami — setidaknya dalam hal ini — seperti apa kode itu terlihat sehingga Anda tahu apa yang mungkin dalam cakupan pekerja web.
Mulai dengan kode thread utama yang perlu terjadi sebelum pekerja web bisa masukkan 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 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);
});
});
Bagian kecil JavaScript ini menyiapkan pipeline pesan
sehingga saat pengguna
mengirimkan formulir dengan URL ke file JPEG, URL tersebut masuk di pekerja web.
Dari sana, bit kode berikutnya mengekstrak {i>metadata<i} Exif dari file JPEG,
membuat string HTML, dan mengirimkan HTML tersebut kembali ke window
agar pada akhirnya menjadi
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 mudah untuk dibaca, tetapi ini juga merupakan kasus penggunaan yang cukup rumit untuk pekerja web.
Namun, hasilnya sepadan dengan pekerjaan yang dilakukan, dan tidak hanya terbatas pada kasus penggunaan ini.
Anda dapat menggunakan pekerja web untuk berbagai hal, seperti mengisolasi panggilan fetch
dan memproses respons, memproses data dalam jumlah besar tanpa memblokir
di thread utama—dan itu hanya permulaan.
Saat meningkatkan kinerja aplikasi web Anda, mulailah berpikir tentang apa pun yang dapat dilakukan secara wajar dalam konteks pekerja web. Keuntungan dapat berupa signifikan, dan dapat menghasilkan pengalaman pengguna yang lebih baik secara keseluruhan untuk {i>website<i} Anda.