# ブラウザ拡張プロジェクト パート3: バックグラウンドタスクとパフォーマンスについて学ぶ 一部のブラウザ拡張機能が軽快で反応が良いのに対し、他のものが遅く感じる理由を考えたことはありますか?その秘密は、裏で何が起きているかにあります。ユーザーが拡張機能のインターフェースをクリックしている間、データ取得、アイコンの更新、システムリソースの管理などを静かに行うバックグラウンドプロセスの世界が存在します。 これがブラウザ拡張シリーズの最終レッスンであり、あなたのカーボンフットプリントトラッカーをスムーズに動作させる方法を学びます。動的なアイコン更新を追加し、問題が発生する前にパフォーマンスの問題を見つける方法を学びます。まるでレーシングカーを調整するように、小さな最適化が全体の動作に大きな違いをもたらします。 このレッスンが終わる頃には、洗練された拡張機能を手に入れ、優れたウェブアプリと素晴らしいウェブアプリを分けるパフォーマンスの原則を理解できるようになります。それでは、ブラウザ最適化の世界に飛び込みましょう。 ## レクチャー前のクイズ [レクチャー前のクイズ](https://ff-quizzes.netlify.app/web/quiz/27) ### はじめに 前回のレッスンでは、フォームを作成し、それをAPIに接続し、非同期データ取得に取り組みました。あなたの拡張機能は順調に形になっています。 次は仕上げです。例えば、拡張機能のアイコンがカーボンデータに基づいて色を変えるようにすることです。これは、NASAがアポロ宇宙船のすべてのシステムを最適化しなければならなかったことを思い出させます。彼らはサイクルやメモリを無駄にする余裕がありませんでした。命がパフォーマンスに依存していたからです。私たちのブラウザ拡張機能はそこまで重要ではありませんが、同じ原則が適用されます。効率的なコードはより良いユーザー体験を生み出します。 ## ウェブパフォーマンスの基本 コードが効率的に動作すると、人々はその違いを実際に「感じる」ことができます。ページが瞬時に読み込まれたり、アニメーションがスムーズに流れる瞬間を知っていますか?それが良いパフォーマンスの働きです。 パフォーマンスは単に速度の問題ではありません。ウェブ体験を自然で快適なものにすることが目的です。コンピューティングの初期には、グレース・ホッパーがナノ秒(約1フィートの長さのワイヤー)を机に置いて、光が1秒の10億分の1でどれだけ進むかを示していました。彼女はコンピューティングにおいて毎マイクロ秒が重要である理由を説明するためにこれを使っていました。何が遅くしているのかを見つけるための探偵ツールを見てみましょう。 > 「ウェブサイトのパフォーマンスは2つのことに関するものです:ページがどれだけ速く読み込まれるか、そしてその上でコードがどれだけ速く動作するか。」 -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/) ウェブサイトをあらゆるデバイス、あらゆるユーザー、あらゆる状況で驚くほど速くする方法についての話題は、当然ながら広範です。標準的なウェブプロジェクトやブラウザ拡張機能を構築する際に覚えておくべきポイントを以下に示します。 サイトを最適化する最初のステップは、実際に裏で何が起きているかを理解することです。幸いなことに、ブラウザには強力な探偵ツールが組み込まれています。 Edgeで開発者ツールを開くには、右上の3つのドットをクリックし、「その他のツール > 開発者ツール」に進みます。または、キーボードショートカットを使用します:Windowsでは`Ctrl` + `Shift` + `I`、Macでは`Option` + `Command` + `I`。そこに到達したら、「パフォーマンス」タブをクリックしてください。ここで調査を行います。 **パフォーマンス探偵ツールキット:** - **開く** 開発者ツール(開発者として常に使用します!) - **移動する** パフォーマンスタブへ - ウェブアプリのフィットネストラッカーのようなものです - **記録する** ボタンを押してページの動作を観察 - **結果を分析する** 何が遅くしているかを見つける これを試してみましょう。ウェブサイト(Microsoft.comが適しています)を開き、「記録」ボタンをクリックします。次にページをリフレッシュして、プロファイラーが何が起きているかをキャプチャするのを見てください。記録を停止すると、ブラウザがサイトを「スクリプト化」、「レンダリング」、「ペイント」する方法の詳細な内訳が表示されます。これは、ロケット打ち上げ中にミッションコントロールがすべてのシステムを監視する方法を思い出させます。リアルタイムで何が起きているか、いつ起きているかのデータを得ることができます。 ![Edgeプロファイラー](../../../../translated_images/profiler.5a4a62479c5df01cfec9aab74173dba13f91d2c968e1a1ae434c26165792df15.ja.png) ✅ [Microsoft Documentation](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon)には、さらに詳しい情報が掲載されています。 > プロのヒント:ブラウザキャッシュをクリアしてからテストを行い、初めて訪問するユーザーにとってのサイトのパフォーマンスを確認してください。リピート訪問とは通常かなり異なります! プロファイルタイムラインの要素を選択して、ページが読み込まれる間に発生するイベントをズームインして確認します。 プロファイルタイムラインの一部を選択して、ページのパフォーマンスのスナップショットを取得し、サマリーパネルを確認してください: ![Edgeプロファイラーのスナップショット](../../../../translated_images/snapshot.97750180ebcad73794a3594b36925eb5c8dbaac9e03fec7f9b974188c9ac63c7.ja.png) イベントログパネルを確認して、15ms以上かかったイベントがあるかどうかを確認してください: ![Edgeイベントログ](../../../../translated_images/log.804026979f3707e00eebcfa028b2b5a88cec6292f858767bb6703afba65a7d9c.ja.png) ✅ プロファイラーを使いこなしてください!このサイトで開発者ツールを開き、ボトルネックがあるかどうかを確認してください。最も遅く読み込まれるアセットは何ですか?最も速いものは? ## プロファイリング時に見るべきポイント プロファイラーを実行するのは始まりに過ぎません。本当のスキルは、これらのカラフルなチャートが実際に何を伝えているかを理解することです。心配しないでください、すぐに読み方に慣れるでしょう。経験豊富な開発者は、問題が完全に発生する前に警告サインを見つける方法を学んでいます。 では、ウェブプロジェクトに潜り込む傾向があるパフォーマンスのトラブルメーカーについて話しましょう。マリー・キュリーが実験室で放射線レベルを慎重に監視しなければならなかったように、私たちは問題が発生していることを示す特定のパターンを監視する必要があります。これらを早期に発見することで、あなた(そしてユーザー)の多くのフラストレーションを防ぐことができます。 **アセットサイズ**: ウェブサイトは年々「重く」なってきており、その余分な重量の多くは画像から来ています。まるでデジタルスーツケースにどんどん詰め込んでいるようなものです。 ✅ [Internet Archive](https://httparchive.org/reports/page-weight)をチェックして、ページサイズがどのように増加してきたかを確認してください。非常に興味深いです。 **アセットを最適化する方法:** - **画像を圧縮する**!WebPのような最新フォーマットはファイルサイズを劇的に削減できます - **デバイスに適した画像サイズを提供する** - 大きなデスクトップ画像をスマートフォンに送る必要はありません - **CSSやJavaScriptを最小化する** - 1バイトでも重要です - **遅延読み込みを使用する** 画像がユーザーが実際にスクロールしたときにのみダウンロードされるようにする **DOMトラバーサル**: ブラウザはあなたが書いたコードに基づいてドキュメントオブジェクトモデルを構築する必要があるため、タグを最小限に抑え、ページが必要とするものだけを使用してスタイリングすることで、良好なページパフォーマンスを維持することができます。この点で、ページに関連する余分なCSSは最適化することができます。例えば、1ページでのみ使用されるスタイルは、メインスタイルシートに含める必要はありません。 **DOM最適化の主要戦略:** - **HTML要素とネストレベルを最小化する** - **未使用のCSSルールを削除し、効率的にスタイルシートを統合する** - **各ページに必要なものだけをロードするようにCSSを整理する** - **HTMLをセマンティックに構造化してブラウザの解析を向上させる** **JavaScript**: すべてのJavaScript開発者は、DOMがトラバースされてブラウザにペイントされる前にロードされなければならない「レンダーブロッキング」スクリプトに注意する必要があります。Terrariumモジュールで行われているように、インラインスクリプトに`defer`を使用することを検討してください。 **最新のJavaScript最適化技術:** - **`defer`属性を使用してDOM解析後にスクリプトをロードする** - **コード分割を実装して必要なJavaScriptのみをロードする** - **非重要な機能に対して遅延読み込みを適用する** - **可能な限り重いライブラリやフレームワークの使用を最小化する** ✅ [Site Speed Test website](https://www.webpagetest.org/)でいくつかのサイトを試して、サイトパフォーマンスを判断するために行われる一般的なチェックについて学びましょう。 ブラウザが送信されたアセットをレンダリングする方法についてのアイデアが得られたので、拡張機能を完成させるために必要な最後のいくつかのことを見てみましょう: ### 色を計算する関数を作成する 次に、数値データを意味のある色に変換する関数を作成します。これは、信号機システムのようなもので、クリーンエネルギーの場合は緑、高炭素強度の場合は赤です。 この関数は、APIから取得したCO2データを使用して、環境への影響を最もよく表す色を決定します。科学者が海洋温度から星の形成まで、複雑なデータパターンを視覚化するためにヒートマップで色分けを使用する方法に似ています。これを`/src/index.js`に追加します。以前設定した`const`変数のすぐ後に追加してください: ```javascript function calculateColor(value) { // Define CO2 intensity scale (grams per kWh) const co2Scale = [0, 150, 600, 750, 800]; // Corresponding colors from green (clean) to dark brown (high carbon) const colors = ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02']; // Find the closest scale value to our input const closestNum = co2Scale.sort((a, b) => { return Math.abs(a - value) - Math.abs(b - value); })[0]; console.log(`${value} is closest to ${closestNum}`); // Find the index for color mapping const num = (element) => element > closestNum; const scaleIndex = co2Scale.findIndex(num); const closestColor = colors[scaleIndex]; console.log(scaleIndex, closestColor); // Send color update message to background script chrome.runtime.sendMessage({ action: 'updateIcon', value: { color: closestColor } }); } ``` **この巧妙な関数の内訳:** - **2つの配列を設定する** - 1つはCO2レベル用、もう1つは色用(緑=クリーン、茶色=汚れた!) - **実際のCO2値に最も近い一致を見つける** 配列ソートを使用して - **findIndex()メソッドを使用して一致する色を取得する** - **選択した色をChromeのバックグラウンドスクリプトにメッセージとして送信する** - **テンプレートリテラル(バックティック)を使用してクリーンな文字列フォーマットを実現する** - **すべてをconst宣言で整理する** `chrome.runtime` [API](https://developer.chrome.com/extensions/runtime)は、拡張機能の神経系のようなもので、すべての裏方の通信やタスクを処理します: > 「chrome.runtime APIを使用してバックグラウンドページを取得し、マニフェストの詳細を返し、アプリや拡張機能のライフサイクルイベントをリッスンして応答します。また、このAPIを使用してURLの相対パスを完全修飾URLに変換することもできます。」 **Chrome Runtime APIが便利な理由:** - **拡張機能の異なる部分が互いに通信できるようにする** - **ユーザーインターフェースをフリーズさせずにバックグラウンド作業を処理する** - **拡張機能のライフサイクルイベントを管理する** - **スクリプト間のメッセージ送信を非常に簡単にする** ✅ Edge用にこのブラウザ拡張機能を開発している場合、Chrome APIを使用していることに驚くかもしれません。新しいEdgeブラウザバージョンはChromiumブラウザエンジン上で動作しているため、これらのツールを活用できます。 > **プロのヒント**: ブラウザ拡張機能をプロファイリングしたい場合、拡張機能自体の中から開発者ツールを起動してください。拡張機能は独自のブラウザインスタンスとして動作するため、拡張機能固有のパフォーマンスメトリクスにアクセスできます。 ### デフォルトのアイコン色を設定する 実際のデータを取得する前に、拡張機能に初期状態を設定しましょう。誰も空白や壊れたように見えるアイコンを見たくありません。インストールした瞬間から拡張機能が動作していることをユーザーに知らせるために、緑色を初期状態として設定します。 `init()`関数内で、デフォルトの緑色アイコンを設定しましょう: ```javascript chrome.runtime.sendMessage({ action: 'updateIcon', value: { color: 'green', }, }); ``` **この初期化が達成すること:** - **ニュートラルな緑色をデフォルト状態として設定する** - **拡張機能がロードされたときに即座に視覚的なフィードバックを提供する** - **バックグラウンドスクリプトとの通信パターンを確立する** - **データがロードされる前にユーザーが機能する拡張機能を確認できるようにする** ### 関数を呼び出し、実行する 次に、新しいCO2データが入ってきたときにアイコンが自動的に適切な色で更新されるように、すべてを接続します。これは電子デバイスの最終回路を接続するようなもので、突然すべての個々のコンポーネントが1つのシステムとして機能します。 APIからCO2データを取得した直後にこの行を追加してください: ```javascript // After retrieving CO2 data from the API // let CO2 = data.data[0].intensity.actual; calculateColor(CO2); ``` **この統合が達成すること:** - **APIデータフローを視覚的なインジケーターシステムに接続する** - **新しいデータが到着したときにアイコン更新を自動的にトリガーする** - **現在の炭素強度に基づいてリアルタイムの視覚的フィードバックを提供する** - **データ取得と表示ロジックの間の関心の分離を維持する** 最後に、`/dist/background.js`でこれらのバックグラウンドアクションコールのリスナーを追加します: ```javascript // Listen for messages from the content script chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { if (msg.action === 'updateIcon') { chrome.action.setIcon({ imageData: drawIcon(msg.value) }); } }); // Draw dynamic icon using Canvas API // Borrowed from energy lollipop extension - nice feature! function drawIcon(value) { // Create an offscreen canvas for better performance const canvas = new OffscreenCanvas(200, 200); const context = canvas.getContext('2d'); // Draw a colored circle representing carbon intensity context.beginPath(); context.fillStyle = value.color; context.arc(100, 100, 50, 0, 2 * Math.PI); context.fill(); // Return the image data for the browser icon return context.getImageData(50, 50, 100, 100); } ``` **このバックグラウンドスクリプトが行うこと:** - **メインスクリプトからのメッセージをリッスンする(受付係が電話を受けるように)** - **ツールバーアイコンを変更する「updateIcon」リクエストを処理する** - **Canvas APIを使用して新しいアイコンを動的に作成する** - **現在の炭 ここに面白い探偵ミッションがあります:Wikipedia、GitHub、Stack Overflowのような、長年運営されているオープンソースのウェブサイトをいくつか選び、そのコミット履歴を調査してみましょう。どこでパフォーマンス改善が行われたか見つけられますか?繰り返し発生している問題は何でしょうか? **調査のアプローチ:** - **検索** コミットメッセージで「optimize」「performance」「faster」といった言葉を探す - **観察** パターンを見つける - 同じ種類の問題を何度も修正しているか? - **特定** ウェブサイトを遅くする一般的な原因を見つける - **共有** 発見したことを共有する - 他の開発者が実際の例から学べるように ## 講義後のクイズ [講義後のクイズ](https://ff-quizzes.netlify.app/web/quiz/28) ## 復習と自己学習 [パフォーマンスニュースレター](https://perf.email)に登録することを検討してください。 ブラウザがウェブパフォーマンスを評価する方法を調査するために、ウェブツールのパフォーマンスタブを確認してみましょう。大きな違いを見つけられますか? ## 課題 [サイトのパフォーマンスを分析する](assignment.md) --- **免責事項**: この文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書を正式な情報源としてご参照ください。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤認について、当方は一切の責任を負いません。