昨今ではWebサイトやWebアプリケーションに対し「適切にページが表示されるか」だけでなく、ロード時間の早さやアクセシビリティといった使い勝手の良さも求められるようになっている。これらは利用者の満足度向上だけでなくGoogle検索の表示結果にも影響するため、できる限り対応しておきたい。そこで今回は、Googleが提供するWebサイト/Webアプリのパフォーマンスやアクセシビリティ診断ツール「Lighthouse」を紹介する。

さまざまな指標による診断を手軽に実行可能できるツール「Lighthouse」

WebサイトやWebアプリケーションを構築する際には、かつてはどんなWebブラウザでも同じように表示され同じように動作することや、検索エンジンによって高く評価されるようなマークアップを行うことが求められていた。これらは現在でももちろん重要ではあるのだが、昨今ではそれに加えて使い勝手の良さも求められるようになっている。

使い勝手の悪いサイトやアプリケーションは単に利用者のストレスとなるだけでなく、検索エンジン対策(SEO)の観点でも不利益がある。たとえばGoogleは検索結果の表示順序を決定する際にページがどれだけ素早く表示されるかや、アクセシビリティへの対応度などもチェックして評価基準として使用している。

ただ、ページが表示されるまでの時間の高速化やアクセシビリティの改善はそれらを意識して実装を行わないと難しい。そこで今回紹介したいのが、Googleがオープンソースで開発・公開しているWeb開発向けの診断ツール「Lighthouse」だ。

Lighthouseの特徴としては、まずさまざまな指標でWebページの分析ができる点がある。分析できる指標は「パフォーマンス」「アクセシビリティ」「ベストプラクティス」「SEO」「Progressive Web App」の5つに分類されており、さらに各項目毎に多数のチェック項目が用意されている。PC上のWebブラウザだけでなく、モバイル環境での利用を想定した診断も可能だ。診断結果では具体的に問題点が指摘されるようになっており、どのような処置を行えば各指標の評価(100点満点)が向上するのか分かりやすく提示される。

LighthouseはGoogle Chromeのデベロッパーツール(DevTools)と統合されており、Google Chromeもしくはそのオープンソース版であるChromiumが利用できる環境であれば特に追加でツール等をインストールすることなしにすぐに診断を実行できる。また、Node.js環境からプログラマティックに診断を実行できるモジュールも提供されているほか、コマンドラインから利用できるフロントエンドなども用意されている。これらを利用することで、CIツールなどと組み合わせて自動的にテストを実行することも可能だ。

以下では、まずGoogle ChromeのDevToolsからLighthouseを利用して診断を行う例を紹介し、続いてコマンドラインツールやNode.jsを使ったテストの自動化について解説する。

Google Chromeから利用する

LighthouseはGoogle Chromeに統合されており、DevToolsから簡単に診断を実行できる。DevToolsはChromeのツールバー内にある「Google Chromeの設定」ボタンをクリックし、「その他のツール」-「デベロッパーツール」を選択すると表示される(図1)。

図1 デベロッパーツールはGoogle Chromeの設定ボタンから表示できる
図1 デベロッパーツールはGoogle Chromeの設定ボタンから表示できる

Lighthouseによる診断は、デベロッパーツール内の「Audits」タブで実行できる(図2)。ここで診断条件を設定し、「Run audits」をクリックすると診断が実行される。

図2 「Audits」タブでLighthouseによる診断を実行できる
図2 「Audits」タブでLighthouseによる診断を実行できる

なお、ここで設定できる条件は以下の通りだ。

「Device」設定

「Device」項目では想定する端末を指定できる。「Mobile」はスマートフォンなどのモバイル端末、「Desktop」はいわゆるPCだ。どちらも基本的な診断項目は変わらないが、「Mobile」での診断の場合、モバイル端末を想定した環境でテストが実行される(図3)。

図3 「Device」で「Mobile」を選択した場合、モバイル端末を想定した環境でテストが実行される
図3 「Device」で「Mobile」を選択した場合、モバイル端末を想定した環境でテストが実行される

「Audits」設定

「Audits」では実行する診断内容を指定できる(表1)。

表1 Lighthouseで実行できる診断内容
項目名 説明
Performance ページ読み込み速度や描画負荷、ユーザーからの反応速度といった、パフォーマンスに関連する診断
Accessibility 言語設定や色の設定、視覚障害者向けスクリーンリーダー対応といった、アクセスのしやすさ(アクセシビリティ)に関連する診断
Best Practices HTTPSやHTTP/2といった推奨されている技術を使っているか、推奨されていないAPIやライブラリを使っていないかなど、適切な実装を行っているかどうかの診断
SEO SEOに関する診断

特に理由の無い限りは、すべてを対象に診断を行うのが良いだろう。

「Throttling」設定

「Throttling」項目では、低速なネットワーク回線やCPUが非力な端末での閲覧をシミュレートするかどうかを指定する。「Simulated Fast 3G, 4x CPU Slowdown」を選択した場合、診断実行時には回線やCPU速度の制限を行わず、その結果から3G回線、低CPU環境での閲覧を想定したスコアを計算する。「Applied Fast 3G, 4x CPU Slowdown」ではChrome側で実行回線やCPU速度を実際に制限し、その結果を表示する。「No throttling」ではこういった制限やシミュレートを一切行わない。

また、「Clear storage」にチェックを入れた場合、localStorageをクリアしてから診断が実行される。ただし、筆者がテストを行った環境では、これにチェックを入れて診断を実行した場合エラーとなって診断が完了しないことがあった。そういった場合、このチェックを外して診断を実行して見ると良いだろう。

診断を実行すると、Webページ作成におけるヒントメッセージとともにその進行状況が表示される(図4)。

図4 診断中にはWebページ作成におけるヒントが表示される
図4 診断中にはWebページ作成におけるヒントが表示される

診断が完了すると、各項目のスコアとともにその結果をまとめたレポートが表示される(図5)。

図5 スコアとともに診断結果が表示される
図5 スコアとともに診断結果が表示される

Lighthouseで実行される診断内容

それでは、出力されたレポートを見ながら、Lighthouseではどのような診断が実行されるかを具体的に見ていこう。なお、ChromeもしくはChromiumのバージョンによって搭載されているLighthouseのバージョンも若干ではあるが異なる。本記事ではChrome 73(Lighthouseのバージョンは4.0)で診断を行なっているが、これ以外のバージョンでは診断項目が異なる場合があるので注意したい。

「Performance」診断項目

「Performance」診断では、ページ読み込み速度やレンダリング速度、ユーザーによる操作に対する反応速度などに関する診断が行われる。まず注目したいのは、「Metrics」項目だ。ここでは、表2のような指標が表示される。これらの項目は、いずれも値が小さい方が高いスコアとなる。

表2 「Metrics」で表示される6の速度指標
指標名 説明
First Contentful Paint ページにアクセスしてからページ内の文字もしくは画像が最初に描画されるまでの時間
Speed Index ページの描画速度を示す指標
Time to Interactive ページが操作可能になるまでの時間
First Meaningful Paint ページ内の主要なコンテンツが表示されるまでの時間
First CPU Idle ページ描画を行うスレッドが最初にアイドル状態になるまでの時間
Estimated Input Latency ユーザーからの入力に対する遅延

「Speed Index」についてはやや曖昧な説明になっているが、GoogleによるSpeed Indexについての解説ページによると、正確な定義は図6のようになっているようだ。

図6 Speed Indexの定義
図6 Speed Indexの定義

ここで、「end」は描画が完了した時刻、「Vc(t)」は時刻tにおける描画完了率(パーセント)だ。なお、時刻はすべて描画開始時刻を0とした相対時刻である。簡単に言えば、描画完了時刻が早いほどこの値は小さくなり、また描画完了時刻が遅くとも、早期に多くのコンテンツが描画されればこの値は小さくなる。

また、「View Trace」をクリックすると「Performance」タブでページのローディング状況を詳しく確認できる(図7)。

図7 どのタイミングでどのような処理が行われているかを「Performance」タブで確認できる
図7 どのタイミングでどのような処理が行われているかを「Performance」タブで確認できる

ここでは画面上のグラフ上でマウスポインタを動かすことで、ページのローディング状況を具体的に時系列で確認することもできる(図8)。

図8 ページのレンダリング状況の確認も可能
図8 ページのレンダリング状況の確認も可能

「Diagnostics」欄ではパフォーマンスに関する問題点が列挙される。Performance診断では表3のような診断が行われ、ここではそのうち問題が確認されたものが表示される。

表3 Performance診断での診断項目
診断名 説明
Avoid an excessive DOM size DOMサイズが過度に大きくないか
Avoids enormous network payloads 多大なネットワーク負荷を要求していないか
Avoid multiple page redirects ページのリダイレクトを複数回行っていないか
Defer offscreen images 表示領域外に配置されている画像を遅延ロードさせているか
Defer unused CSS 使用していないCSSルールを削除もしくは遅延ロードさせているか
Efficiently encode images 画像を効率的な形式でエンコードしているか
Eliminate render-blocking resources レンダリングをブロックするようなリソースが存在しないか
Enable text compression テキストベースのコンテンツの転送時にgzipなどの圧縮転送を利用しているか
Ensure text remains visible during webfont load Webフォントのローディング中でもテキストを表示できるようにしているか
JavaScript execution time JavaScriptコードのパース/コンパイル/実行時間は適切か
Minify CSS CSSファイルを圧縮(minify)しているか
Minify JavaScript JavaScriptファイルを圧縮(minify)しているか
Minimize Critical Requests Depth レンダリングをブロックさせるようなリクエストは最小限となっているか
Minimizes main-thread work JavaScriptコードのうちメインスレッドで実行されるものを最小に抑えているか
Preconnect to required origins サードパーティのリソースをリクエストする際にpreconnect機能を利用しているか
Preload key requests 「<link rel=reload>」のような事前ロードのためのヒントを設定しているか
Properly size images 使用されている画像のサイズが適切か
Serve images in next-gen formats JPEG 2000やJPEG XR、WebPといったより高圧縮率の画像フォーマットを使用しているか
Server response times are low (TTFB) サーバーがリクエストに対しレスポンスを返すまでの時間(TTFB)は十分に短いか
User Timing marks and measures User Timing APIを使用してJavaScriptコードの実行時間を計測している場合、この項目でその結果が表示される
Use video formats for animated content アニメーションするコンテンツでアニメーションGIFなどの非効率的なフォーマットではなくMPEG4やWebMといったフォーマットを利用しているか
Uses efficient cache policy on static assets 静的なコンテンツに対し適切なキャッシュ設定を行っているか

たとえば今回の例では、「Ensure text remains visible during webfont load」(Webフォントのローディング中でもテキストが表示されるようにする)、「Avoid an excessive DOM size」(DOMサイズを過度に大きくしない)、「Minimize Critical Requests Depth」(画面描画に必要なリクエストを最小化する)について問題点があることが指摘されている(図9)。

図9 問題が確認された診断項目については詳しい診断内容が表示される
図9 問題が確認された診断項目については詳しい診断内容が表示される

それに加えて、「User Timing marks and measures」ではUser Timing APIを使ったJavaScriptのパフォーマンス測定結果が表示されている。今回テスト対象としたサイトでは「Vue.js」というJavaScriptライブラリを使用しているが、このライブラリ中でUser Timing APIを使った測定コードが含まれており、ここでその結果が出力されている(図10)。

図10 JavaScriptコード中でUser Timing APIを使用していた場合、それによる測定結果が表示される
図10 JavaScriptコード中でUser Timing APIを使用していた場合、それによる測定結果が表示される

特に問題が確認されなかった項目については「Passed audits」以下に表示される。問題がない場合でも「Avoids enormous network payloads」(多大なネットワーク負荷を要求していないか)や、「Uses efficient cache policy on static assets」(静的なコンテンツに対し適切なキャッシュ設定を行っているか)ではロードしているリソースやキャッシュ設定といった情報を確認できるほか、「JavaScript execution time」(JavaScriptコードのパース/コンパイル/実行時間は適切か)や「Minimizes main-thread work」(JavaScriptコードのうちメインスレッド実行されるものを最小に抑えているか)ではJavaScriptコードの実行時間を確認できるので、チェックしておくと良いだろう(図11、12)。

図11 「Avoids enormous network payloads」項目や「Uses efficient cache policy on static assets」ではページがロードしたリソースのサイズやキャッシュ状況を確認できる
図11 「Avoids enormous network payloads」項目や「Uses efficient cache policy on static assets」ではページがロードしたリソースのサイズやキャッシュ状況を確認できる
図12 「JavaScript execution time」や「Minimizes main-thread work」ではJavaScriptコードの実行時間を確認できる
図12 「JavaScript execution time」や「Minimizes main-thread work」ではJavaScriptコードの実行時間を確認できる

「Accessibility」診断項目

「Acessibility」診断項目では、視覚障害者向けのスクリーンリーダーを利用するためのマークアップや色弱者向けの配色といったアクセシビリティに関する診断結果が表示される。ここでの診断項目は表4のようなものがある。

表4 Accessibility診断項目
診断名 説明
Background and foreground colors do not have a sufficient contrast ratio. 背景色と文字色で十分なコントラスト差があるか
Buttons have an accessible name ボタンに対し適切な名前が設定されているか
Cells in a <table> element that use the [headers] attribute only refer to other cells of that same table. 「header」属性が付けられたセルはヘッダとしてのみ使用しているか
Definition list items are wrapped in <dl> elements dt、dd要素がdl要素内にあるか
Document has a <title> element titleタグでタイトルが指定されているか
Elements with [role] that require specific children [role]s, are present 「role」属性が設定された要素の子要素に適切な「role」属性が設定されているか
Form elements do not have associated labels 入力フォーム内の要素に適切なラベルが設定されているか
Image elements do not have [alt] attributes 画像要素に適切な「alt」属性が設定されているか
Links have a discernible name リンクに十分識別可能な名前が設定されているか
Lists contain only <li> elements and script supporting elements (<script> and <template>). リスト(ul、ol)内にはli要素とscript要素、template要素のみが含まれているか
List items (<li>) are contained within <ul> or <ol> parent elements li要素がulもしくはol要素内に含まれているか
No element has a [tabindex] value greater than 0 tabindexの値として1以上が設定された要素はないか(tabindex属性で「0」と「-1」以外を指定することは推奨されない)
Presentational <table> elements avoid using <th>, <caption> or the [summary] attribute. 段組のためにtable要素を利用している場合にthやcaption、summaryといった要素を使用していないか
The document does not use <meta http-equiv=”refresh”> <meta http-equiv=”refresh”>タグを利用していないか
The page contains a heading, skip link, or landmark region ページ内に見出しやナビゲーションのためのスキップリンクなどが含まれているか
[aria-*] attributes are valid and not misspelled 有効な「aria-*」属性が使われておりスペルミスはないか
[aria-*] attributes have valid values 「aria-*」属性で適切な値が設定されているか
[aria-*] attributes match their roles 役割に適合した「aria-*」属性が設定されているか
[id] attributes on the page are unique ページ内で重複するid属性が使われていないか
[lang] attributes have a valid value lang属性の値は適切か
[role]s are contained by their required parent element 「role」属性が設定された要素が適切な親要素内に存在するか
[role]s have all required [aria-*] attributes 「role」属性に適切な値が設定されているか
[role] values are not valid 「role」属性に適切な値が設定されているか
[user-scalable=”no”] is not used in the <meta name=”viewport”> element and the [maximum-scale] attribute is not less than 5. ビューポートやスケーリング設定は適切か
<audio> elements contain a <track> element with [kind=”captions”] audio要素に「kind=”captions”」属性付きのtrack要素が含まれているか
<dl>’s contain only properly-ordered <dt> and <dd> groups, <script> or <template> elements. audio要素がtrack要素を適切に含んでいるか
<frame> or <iframe> elements do not have a title frameタグやiframeタグ内で適切にタイトルが設定されているか
<html> element has a valid value for its [lang] attribute html要素のlang属性に適切な値が設定されているか
<input type=”image”> elements have [alt] text <input type=”image”>タグでalt属性が設定されているか
<object> elements have [alt] text object要素にalt属性が設定されているか
<th> elements and elements with [role=”columnheader”/”rowheader”] have data cells they describe. th要素や「role=”columnheader”」「role=”rowheader”」が指定された要素はヘッダとしてのみ使用しているか
<video> elements contain a <track> element with [kind=”captions”] video要素に「kind=”captions”」属性付きのtrack要素が含まれているか
<video> elements contain a <track> element with [kind=”description”] video要素に「kind=”description”」属性付きのtrack要素が含まれているか

また、自動では検出できず、手動で確認するよう求められる項目もある(表5)。

表5 手動での確認が推奨されるAccessibility診断項目
診断名 説明
[accesskey] values are unique 「accesskey」属性の値がページ内で重複していないか
Custom controls have ARIA roles カスタムコントロール要素に適切なARIAロールを設定しているか
Custom controls have associated labels カスタムコントロール要素に適切なラベルを設定しているか
Headings don’t skip levels 適切な順序で見出しレベルを使用し、途中の見出しレベルをスキップしていないか
HTML5 landmark elements are used to improve navigation ランドマーク指定をナビゲーションの改善に使用しているか
Interactive controls are keyboard focusable インタラクティブに操作できる要素をキーボード操作でフォーカスできるか
Interactive elements indicate their purpose and state インタラクティブに操作できる要素は適切にその目的や状態を示しているか
Offscreen content is hidden from assistive technology 画面表示領域外にあるコンテンツは支援技術/機能の操作対象外となっているか
The user’s focus is directed to new content added to the page ダイアログなどユーザーによる操作で表示されるコンテンツに対し適切にフォーカスを移動させているか
The page has a logical tab order タブキーでの要素選択順序が論理的に正しく設定されているか
User focus is not accidentally trapped in a region 意図しないフォーカス移動でユーザー操作を阻害しないか
Visual order on the page follows DOM order 画面表示順がDOM上での順序に一致しているか

なお、これら診断内で言及されている「ARIA(Accessible Rich Internet Applications)」はスクリーンリーダーやそのほかアクセス支援機能のために情報を定義するための規格だ。詳しくはMDNのドキュメントなどを参照してほしいが、たとえばHTMLの要素に「role」や「aria-」で始まる属性を追加することで、その要素がドキュメント内でどのような意味を持っているのかという情報を付け加えることができる。

さて、今回診断対象としたサイトでは診断の結果いくつか問題点が指摘された。まず、「role」属性に不適切な値が設定されていたため「[role] values are not valid」との診断が出ている。ここでは問題のある要素名(タグ名)やIDなどが表示されるので、どこが問題かは比較的容易に確認できる(図13)。

図13 要素に問題点が見つかった場合、その要素名やIDなどが表示される。この例では「organization-navigation」というIDが付けられた「nav」タグが問題となっている
図13 要素に問題点が見つかった場合、その要素名やIDなどが表示される。この例では「organization-navigation」というIDが付けられた「nav」タグが問題となっている

実際に確認してみると、このタグにはARIAでは定義されていない「role=”footer”」という属性が指定されていた。HTMLではWebブラウザなどがサポートしていない属性は無視されるためブラウザ側ではエラーにならないが、アクセシビリティの観点では適切ではない。

また、背景色と文字色に十分なコントラスト差がないため「Background and foreground colors do not have a sufficient contrast ratio.」という指摘も出ている。こちらも問題のある要素が一覧表示されるため、どこが問題かすぐに把握できるだろう(図14)。

図14 「Background and foreground colors do not have a sufficient contrast ratio.」という診断項目でも問題のある要素がリストアップされる
図14 「Background and foreground colors do not have a sufficient contrast ratio.」という診断項目でも問題のある要素がリストアップされる

そのほか、iframeタグでタイトルが設定されていない(「<frame> or <iframe> elements do not have a title」)、フォーム要素でラベルが設定されていない(「Form elements do not have associated labels」)、htmlタグのlang属性に適切な値が設定されていない(「<html> element has a valid value for its [lang] attribute」)、画像要素(imgタグ)にalt属性が設定されていない(「Image elements do not have [alt] attributes」)という指摘についても、具体的に問題のある要素が提示されている(図15)。

図15 多くの診断結果では問題のあった要素が提示される
図15 多くの診断結果では問題のあった要素が提示される

「Best Practices」診断項目

「Best Practices」診断項目では、現状具体的に問題となる可能性は少ないものの、使い勝手やユーザビリティ、セキュリティなどの観点で問題となる可能性があるような項目についての診断が行われる。具体的な診断内容は表6を確認して欲しいが、いくつか分かりにくいものもあるのでそれらについても解説しておこう。

表6 「Best Practices」診断で用意されている項目
項目名 説明
Allows users to paste into password fields パスワード欄へのペーストを禁止していないか
Avoids Application Cache すでに廃止予定となっている、オフラインでWebアプリケーションを利用するためのキャッシュ機構を使用していないか
Avoids deprecated APIs 廃止予定のAPIを使用していないか
Avoids requesting the geolocation permission on page load ユーザーからのアクションなしにページロード中に位置情報(geolocation)の利用を求めていないか
Avoids requesting the notification permission on page load ユーザーからのアクションなしにページロード中に通知の許可を求めていないか
Detected JavaScript libraries 使用しているJavaScriptライブラリを検出して表示する
Displays images with correct aspect ratio 画像を適切なアスペクト比(縦横比)で表示しているか
Does not use HTTP/2 for all of its resources すべてのリソース配信においてHTTP/2を使用しているか
Includes front-end JavaScript libraries with known security vulnerabilities 脆弱性のあるJavaSriptライブラリを使用していないか
Links to cross-origin destinations are safe セキュリティ対策として異なるドメインのページを対象とした「target=”_blank”」付きリンクに「rel=”noopener”」や「rel=”noreferrer”」属性を付けているか
No browser errors logged to the console コンソールにエラーを出力していないか
Page has the HTML doctype HTMLのdoctype指定を行っているか
Uses document.write() JavaScript内でページのロードを低下させるdocument.write()メソッドを使っていないか
Uses HTTPS HTTPSを使用しているか
Uses passive listeners to improve scrolling performance スクロールを妨げないようPassive Event Listenersを使用しているか

まず「Uses passive listeners to improve scrolling performance」(スクロールを妨げないPassive Event Listenersを使用しているか)だが、通常スクロールに関連するイベントリスナが登録されている場合、その処理が完了するまでスクロール処理が中断されてしまい、スクロール速度の低下といった問題が発生する可能性がある。この診断項目はこの問題を検出するもので、対策としてはイベントリスナを登録するaddEventListener()メソッドのオプションとして「{passive: true}」を指定すれば良い。これを指定すると、イベントリスナ内でpreventDefault()メソッドを実行することによるスクロールのキャンセルができなくなる一方、イベントリスナの処理が完了する前にスクロール処理を行えるようになるためパフォーマンスが改善する。

また、「Links to cross-origin destinations are safe」(セキュリティ対策として異なるドメインのページを対象とした「target=”_blank”」付きリンクに「rel=”noopener”」や「rel=”noreferrer”」属性を付けているか)だが、これらの属性は「target=”_blank”」が指定されたリンクをユーザーがクリックした際の挙動を変更するものだ。「rel=”noopener”」を指定すると、新たに開いたウィンドウやタブから元のウィンドウやタブにアクセスする「window.opener」プロパティへのアクセスができなくなる。また、「rel=”noreferrer”」属性を指定するとそのURLへのアクセス時にリファラを送信しなくなる。

「Allows users to paste into password fields」(パスワード欄へのペーストを禁止していないか)については、ペーストを禁止するとパスワードをコピー&ペーストで貼り付けるようなパスワードマネージャが利用できないという問題が発生するためだ。

さて、Best Practices診断においても、いくつかの項目では問題点が具体的にリストアップされるようになっている。たとえば「Does not use HTTP/2 for all of its resources」(すべてのリソース配信においてHTTP/2を使用しているか)では、読み込んだリソースそれぞれで使用されているプロトコルが確認できる(図16)。

図16 「Does not use HTTP/2 for all of its resources」では読み込んだそれぞれのリソースで使われているプロトコルを確認できる
図16 「Does not use HTTP/2 for all of its resources」では読み込んだそれぞれのリソースで使われているプロトコルを確認できる

また、「Includes front-end JavaScript libraries with known security vulnerabilities」では脆弱性が確認されているJavaScriptライブラリを使用している場合、それがリストアップされる(図17)。

図17 脆弱性のあるJavaScriptライブラリを使用している場合、「Includes front-end JavaScript libraries with known security vulnerabilities」でそのライブラリが表示される
図17 脆弱性のあるJavaScriptライブラリを使用している場合、「Includes front-end JavaScript libraries with known security vulnerabilities」でそのライブラリが表示される

「SEO」診断項目

「SEO」診断項目は、その名の通りSEOに影響のある問題点がないかを診断するものだ(表7)。

表7 「SEO」診断で用意されている項目
項目名 説明
Document avoids plugins プラグインが必要なコンテンツを利用していないか
Document does not have a meta description <meta name=”description”>タグでページ内容の要約を指定しているか
Document has a <title> element <title>タグでタイトルを指定しているか
Document has a valid hreflang 言語毎に異なるページを用意している場合、適切にそれらページのURLを示すための「<link rel=”alternate” hreflang=”<言語>”>」タグを設置しているか
Document has a valid rel=canonical 「<link rel=”canonical”>」タグの設定は適切か
Document uses legible font sizes フォントサイズの指定は適切か
Has a <meta name=”viewport”> tag with width or initial-scale モバイル端末での表示を最適化するための<meta name=”viewport”>タグを設定しているか
Links have descriptive text リンクには適切な文字列を設定しているか
Page has successful HTTP status code 適切なHTTPステータスコードを返しているか
Page is blocked from indexing robots.txtや<meta name=”robots”>タグで検索エンジンを拒否していないか
robots.txt is valid 適切なrobots.txtファイルを用意しているか

これらはページの見やすさや分かりやすさに関わるものだが、Googleの検索エンジンではこれらのいくつかを検索結果での表示順を決定する要素としても使用しており、問題点は適切に修正することをおすすめする。

また、一部の項目については自動テストでは検出できないため、手動でのチェックが推奨されている(表8)。

表8 「Best Practices」診断で手動でのチェックが推奨されている項目
項目名 説明
Page is mobile friendly モバイル端末でも利用しやすいページ(Mobile-Friendly)になっているか
Structured data is valid ページ内に埋め込まれている構造化データは適切か

このうち、「Mobile-Friendly」かどうかはGoogleが提供するmobile-friendlyテストというテストで、構造化データが適切かどうかは構造化データテストツールStructured Data Linerでチェックできるので、これらで別途確認すると良いだろう。

「Progressive Web App」診断項目

最後の「Progressive Web App」診断項目は、「Service Worker」といった技術を利用することでネイティブアプリのように利用できるWebアプリケーションを実現する「Progressive Web App(PWA)」をサポートするための診断だ。

PWAでは独自設定ファイルが必要なほか、それに向けたJavaScriptコードの用意も必要など、一般的なWebページとは多少異なる設定が必要となる。この診断項目では、これらの設定ファイルや設定内容が適切かどうかを検証できる(図18)。

図18 「Progressive Web App」の診断項目
図18 「Progressive Web App」の診断項目

ただ、PWAは現在Googleが利用を推奨しているものの、必ずしもPWAとしてWebページ/Webサイトを構築しなければならないというわけではない。これらの診断項目を理解するにはPWAの機能についての理解も必要であるため、本記事ではこれら診断項目についての詳細は割愛する。

コマンドラインからLighthouseを利用する

前述の通り、LighthouseはChromeのGUIから診断を実行するだけでなく、コマンドラインやNode.jsプログラムから診断を実行することもできる。まずコマンドラインからの実行についてだが、コマンドラインツールはNode.jsで実装されており、利用にはNode.js(バージョン10.13以降)のインストールが必要だ。また、このコマンドラインツールはChromeを起動して遠隔操作によりChrome内でLighthouseを実行するという処理を行うため、別途ChromeもしくはChromiumのインストールも必要となる。

Lighthouseをコマンドラインで利用するためのlighthouseコマンドは、Node.jsのパッケージマネージャであるnpm経由で次のようにしてインストールできる。

$ npm install --global-style lighthouse

このように実行すると、npmコマンドを実行したディレクトリ以下の./node_modules/.bin/ディレクトリ内にlighthouseコマンドがインストールされる。

lighthouseコマンドは、次のようにURLとオプションを引数として受け付ける。オプションよりも先にURLを指定する必要がある点に注意したい。

$ ./node_modules/.bin/lighthouse <URL> [<オプション>...]

たとえば「https://test.srad.jp/」を対象に診断を実行する場合、次のようになる。

$ ./node_modules/.bin/lighthouse https://test.srad.jp/

なお、初回実行時にはエラー発生時にその情報を匿名化してGoogleに送信するかどうか尋ねられるので、「Y」(許可)もしくは「N」(不許可)を選択しておこう。

? We're constantly trying to improve Lighthouse and its reliability.
  Learn more: https://github.com/GoogleChrome/lighthouse/blob/master/docs/error-reporting.md
  May we anonymously report runtime exceptions to improve the tool over time?  No

また、GUIが利用できない環境では、そのままではChrome(もしくはChromium)が起動できずにエラーとなる。その場合、「–chrome-flags=”–headless”」オプションを追加すれば良い。

$ ./node_modules/.bin/lighthouse https://test.srad.jp/ --chrome-flags="--headless"

lighthouseコマンドを実行すると、次のようにその途中結果がコンソールに出力され、診断が完了するとその結果がHTMLファイルとしてカレントディレクトリ内に出力される。

$ ./node_modules/.bin/lighthouse https://test.srad.jp/ --chrome-flags="--headless"
  ChromeLauncher Waiting for browser. +0ms
  ChromeLauncher Waiting for browser... +1ms
  ChromeLauncher Waiting for browser..... +520ms
  ChromeLauncher Waiting for browser....... +501ms
  ChromeLauncher Waiting for browser......... +501ms
  ChromeLauncher Waiting for browser.........? +2ms
  status Connecting to browser +192ms
  status Resetting state with about:blank +25ms
  status Benchmarking machine +18ms
  status Initializing… +506ms


  status Generating results... +0ms
  Printer html output written to /home/hylom/test/test.srad.jp_2019-04-12_18-51-54.report.html +86ms
  CLI Protip: Run lighthouse with `--view` to immediately open the HTML report in your browser +0ms
  ChromeLauncher Killing Chrome instance 2425 +1ms

このレポートをWebブラウザで開くと、ChromeのDevTools内で表示されたものと同じような形式でレポートが表示される(図19)。

図19 出力されたレポート
図19 出力されたレポート

ちなみに、診断結果はCSVやJSON形式でも出力できる。CSV形式で出力するには「–output csv」オプションを、JSON形式で出力するには「–output json」オプションを指定すれば良い。この場合、デフォルトでは標準出力(stdout)に診断結果が出力されるので、必要に応じて出力ファイルのパス名を指定する「–output-path <パス名>」を指定して出力先を指定しよう。たとえばCSV形式での出力の場合、図20のようにカテゴリと診断項目名、タイトル、出力形式、スコアが出力される。

図20 CSV形式で出力した診断結果を表計算ソフトで開いた場合の例
図20 CSV形式で出力した診断結果を表計算ソフトで開いた場合の例

また、JSON形式で出力した場合、診断結果だけでなくスクリーンショットなど、DevTools上でLighthouseを実行した場合とほぼ同一の情報が出力される。このファイルに記録された情報をWebブラウザ上で簡単に閲覧できる「Lighthouse Report Viewer」も公開されており、このページに出力されたJSONファイルをドラッグ&ドロップすることで、その内容をWebブラウザ上で確認できる(図21、22)。

図21 JSON形式で出力した診断結果をWebブラウザ上で確認できる「Lighthouse Report Viewer」
図21 JSON形式で出力した診断結果をWebブラウザ上で確認できる「Lighthouse Report Viewer」
図22 Lighthouse Report Viewer上での診断結果閲覧画面
図22 Lighthouse Report Viewer上での診断結果閲覧画面

そのほか、診断環境(「mobile」もしくは「desktop」)は「–emulated-form-factor」オプションで、ネットワーク/CPU環境の指定は「–throttling-method」オプションで指定可能だ。「–throttling-method」オプションでは表9が指定できる。

表9 「–throttling-method」オプションで指定可能な値
説明
simulate CPU速度や回線の制限を行わず、得られた結果から仮想的に3G回線/低CPU速度での閲覧を想定したスコアを計算する
devtools 回線やCPU速度を3G回線/低CPU速度なみに制限して診断を実行しその結果を表示する
provided 制限やシミュレートを行わない

Node.jsからの利用

LighthouseをNode.jsから利用する場合は、「lighthouse」および「chrome-launcher」モジュールが必要となる。これらはどちらもnpmコマンドでインストールが可能だ。

npm install lighthouse chrome-launcher

詳しくはGitHubで公開されているドキュメントを参照して欲しいが、たとえばURLを指定してコマンドを実行し、その結果を出力するプログラムは次のようになる。

const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

// 診断対象とするURLを指定
const url = "https://test.srad.jp/";

// Chrome/Chroumiumの起動オプションなどを指定
const opts = {
  chromeFlags: ['--headless']
};
const config = null;

chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
  opts.port = chrome.port;
  return lighthouse(url, opts, config).then(results => {
    return chrome.kill().then(() => results.lhr)
  });
}).then(results => {
  // results変数に診断結果が格納される
  console.log(results);
});

ちなみに、前述の「Lighthouse Report Viewer」のソースコードも公開されているので、こちらと組み合わせることでたとえばコミットに合わせて自動的に診断を実行してその結果をHTMLで出力する、といったプログラムも作成可能だ。

サイト構築時にはLighthouseを使ってぜひ一度診断を実行してみよう

このようにLighthouseは簡単に利用できるツールでありながら、多岐にわたる診断を実行できる。診断の実行時間も数十秒〜1、2分程度で完了するので、サイトを新規に構築したり、サイトの改善を行ったりしている際には一度これによる診断を実行してみると良いだろう。

なお、アクセシビリティ関連の診断項目などについては意識しないと高いスコアを取ることは難しい。また、Lighthouseによる診断結果に応じて修正を行う場合に、HTTP/2対応など、改善のためにはHTMLやJavaScript、CSSといった各種リソースレベルでの修正では難しい診断項目もある。一方でHTMLレベルの修正で簡単にスコアを上げられる項目もあるので、最終的には100点に近いスコアを目指しつつも、まずは簡単にできそうな修正から手を付けていくと良いだろう。