前のモジュールでは、ウェブ ワーカーの概要について説明しました。ウェブワーカーは 入力の応答性を改善するには、JavaScript をメインスレッドから ウェブワーカー スレッドが分離されるため、ウェブサイトのインタラクションが Next Paint(INP)に移動します。 できます。しかし、概要だけでは十分ではありません。このモジュールでは、 ウェブワーカー向けの具体的なユースケースが 提示されています
そのようなユースケースの 1 つとして、ウェブサイトから Exif メタデータを取り除く必要がある これはありえないコンセプトではありません。実際、Flickr などのウェブサイトでは Exif のメタデータを表示する方法を ユーザーに提示して 画像(色深度、カメラのメーカーとモデル、その他の画像など)が 分析できます
ただし、画像を取得して ArrayBuffer
に変換するロジックは、
Exif のメタデータの抽出を
完全に行った場合
呼び出すことができます。幸いウェブワーカーのスコープを使用すると
実行することもできます。次に、ウェブワーカーのメッセージング パイプラインを使用して、
EXIF メタデータが HTML 文字列としてメインスレッドに返送され、
表示されます。
ウェブワーカーを使用しない場合のメインスレッド
まず、この作業を行う際にメインスレッドが 使用します。これを行う方法は次のとおりです。
- Chrome で新しいタブを開き、DevTools を開きます。
- パフォーマンス パネルを開きます。
- https://exif-worker.glitch.me/without-worker.html に移動します。
- パフォーマンス パネルで、右上にある [録画] をクリックします。 [DevTools] ペインです。
- この画像リンク、または Exif を含む別の画像を貼り付けます。 [Get that JPEG!] ボタンをクリックします。
- インターフェースに Exif メタデータが表示されたら、もう一度 [Record] をクリックして 録画を停止します。
ただし、ラスタライザ アプリのすべてがメインスレッドで発生します。メイン 次のことが起こります。
- フォームは入力を受け取り、
fetch
リクエストをディスパッチして最初の Exif メタデータを含む画像の部分です - 画像データは
ArrayBuffer
に変換されます。 exif-reader
スクリプトを使用して、EXIF メタデータを 説明します。- メタデータがスクレイピングされて HTML 文字列が作成され、それが メタデータ閲覧者
次に、同じ動作を実装します。ただし、ウェブ アプリケーション コードを使用して 労働者!
ウェブ ワーカーを含むメインスレッド
ここまで、ブラウザから EXIF のメタデータを抽出する方法を JPEG ファイルがメインスレッドにある場合、 次のワーカーが混在しています
- Chrome で別のタブを開き、その DevTools を開きます。
- パフォーマンス パネルを開きます。
- https://exif-worker.glitch.me/with-worker.html に移動します。
- パフォーマンス パネルで、右上にある録画ボタンをクリックします。 [DevTools] ペインの隅にあります。
- フィールドにこちらの画像リンクを貼り付けて、[Get that JPEG!] ボタンをクリックします。
- インターフェースに Exif メタデータが表示されたら、記録ボタンをクリックします。 録画を停止します。
これはウェブワーカーの機能です。メインのインフラストラクチャですべて行うのではなく、 メタデータ ビューアに HTML を入力すること以外はすべて、 表示されます。つまり、メインスレッドは他の処理を行うために解放されます。
おそらく最大の利点は
このアプリのバージョンとは異なり
ウェブワーカーを使用していない場合、exif-reader
スクリプトはメインに読み込まれません。
ウェブワーカー スレッドで処理します。つまり
exif-reader
スクリプトのダウンロード、解析、コンパイルは、
できます。
それでは、これらすべてを可能にするウェブワーカーのコードを詳しく見ていきます。
ウェブワーカーのコードを見る
ウェブワーカーによる違いを確認するだけでは十分ではありません。また、 (少なくともこのケースでは)コードの内容を理解することで、コードの内容を 処理できます
<ph type="x-smartling-placeholder">ウェブワーカーが処理を完了する前に実行する必要があるメインスレッド コードから始める 画像を入力します。
// 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';
});
このコードはメインスレッドで実行され、画像の URL を送信するフォームを設定します。
使用します。そこから、ウェブワーカーのコードは importScripts
で始まります。
外部 exif-reader
スクリプトを読み込み、
メインスレッドに追加します。
// 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);
});
});
この JavaScript により、メッセージ パイプラインがセットアップされ、ユーザーが
JPEG ファイルへの URL を含むフォームを送信すると、URL は Web ワーカーに送られます。
次に、JPEG ファイルから EXIF メタデータを抽出します。
は HTML 文字列を作成し、その HTML を window
に送り返して、最終的に
次の情報が表示されます。
// 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('')
});
});
});
});
少し読みにくいかもしれませんが、これはウェブワーカーにとってかなり複雑なユースケースでもあります。
とはいえ、このユースケースに限定されるものではなく、労力に見合った結果が得られます。
ウェブワーカーは、fetch
呼び出しの分離など、あらゆる種類の処理に使用できます。
レスポンスの処理、ブロックすることなく大量のデータを
これはほんの手始めにすぎません。
ウェブ アプリケーションのパフォーマンスを向上させるには ウェブワーカーのコンテキストで合理的に実行できる あらゆるものを指します次のようなメリットがあります。 ウェブサイトの全体的なユーザー エクスペリエンスの向上につながる可能性があります。