sitespeed.io の Coach を使って Webページのパフォーマンスを評価する


Browsertime にカスタム javascript を指定して独自の指標を取得する | Monotalk に引き続き、sitespeed.io の、 Coachをインストールして、Webページのパフォーマンス評価したいと思います。

  • 補足
    sitespeed.io の測定項目の一部になっているため、sitespeed.io をインストールするとCoachもインストールされます。
    今回はCoachを単独実行して、メトリクスを取得しています。

参考


インストール と 実行

Coach には、npm を直接実行するインストール手順のみが記載されています。
Docker 上で実行を行いたかったので、Web検索したところ、sitespeedio/coach - Docker Hub を見つけましたので、そちらを参考に実行します。
コマンド1発で実行結果の取得ができます。

  • ブラウザにFirefoxを使用して実行

    docker run sitespeedio/coach \
    https://www.sitespeed.io -b firefox
    

  • ブラウザにChromeを使用して実行

    docker run --privileged --shm-size=512m \
    sitespeedio/coach https://www.sitespeed.io
    
    Chrome を使用する際は、--privileged を指定して、docker コマンドを実行する必要があるようです。
    --privileged については以下が参考になりました。
    Docker privileged オプションについて - Qiita

  • レポートをjson形式で出力する

    docker run --rm -v "$(pwd)":/coach \
    sitespeedio/coach https://www.sitespeed.io -b firefox -o advice.json -f json
    

  • OUTPUT
    browserをfirefox で実行した場合、以下のようなOUTPUTが取得できます。
    console出力が見やすいです。
    実際の出力は結構長いため割愛してます。

    ........
    │                                       Score per type                                       │
    ├─────────────────────────┬──────────────────────────────────────────────────────────────────┤
    │ Advice                  │ Score                                                            │
    ├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
    │ Performance             │ 98                                                               │
    ├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
    │ Best practice           │ 85                                                               │
    ├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
    │ Accessibility           │ 94                                                               │
    ├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
    │ Total average           │ 95                                                               │
    └─────────────────────────┴──────────────────────────────────────────────────────────────────┘
    


指定可能なオプション

Documentが見つけられなかったので、コマンドHELPから、何が指定できるか確認します。

HELP出力

  • COMMAND

    docker run sitespeedio/coach -h
    

  • OUTPUT

    Google Chrome 60.0.3112.78 
    Mozilla Firefox 54.0
    Starting Xvfb ...
    /usr/src/app/bin/webcoach.js [options] <url>/<file.har>
    
    Options:
      -h, --help     Show help                                             [boolean]
      -b, --browser  Browser to run (only applicable when testing a URL).
                                                                 [default: "chrome"]
      -f, --format   Output format.    [choices: "table", "json"] [default: "table"]
      -o, --output   File to write output to.
      --details      Show offending request/responses in table output
                                                          [boolean] [default: false]
      --description  Show advice description in table output
                                                          [boolean] [default: false]
      -l, --limit    Show advice with score lower than the limit      [default: 100]
      --mobile       Access the page as mobile a mobile device. Set UA and
                     width/height. For Chrome it will use device Apple iPhone 6.
                                                          [boolean] [default: false]
      --screenshot   Take a screenshot of the tested page saved as screenshot.png
                                                          [boolean] [default: false]
      --noColor      Do not print color information.      [boolean] [default: false]
      --preScript    Task(s) to run before you test your URL (use it for login etc).
                     Note that --preScript can be passed multiple times.
      --viewPort     Set the browser viewport to WIDTHxHEIGHT.
      --sortBy       Define sort option for advices.
                                        [choices: "name", "score"] [default: "name"]
      -V, --version  Show version number                                   [boolean]
    

Table形式に整形

Option情報をTable形式に整形しました。

OPTION名説明デフォルト値
-h, –helpHELPを表示する-
-b, –browser起動するブラウザchrome
-f, –format出力フォーマット テーブル形式かJson形式を指定(table,json)table形式
-o, –outputファイル出力する際のファイル名-
–detailsAdviceの対象になったresource名を出力するか/否かfalse
–descriptionAdviceの説明を表示するか/否かfalse
-l, –limitアドバイスを表示するの得点の下限(デフォルトだと100点未満を表示)100
–mobileMobileデバイスとしてページにアクセスするか否かfalse
–screenshotスクリーンショット(png形式)を取得するか否かfalse
–noColorカラー付きで情報を表示しないfalse
–preScriptページ表示前に実行するscript-
–viewPortWIDTHxHEIGHTでviewportを設定する-
–sortByアドバイスの表示順序のソート方法(name,score)nameでソート
-V, –versionversion情報を表示する-

自サイトに対して、コマンドを実行して修正可能な部分を修正する

コマンドの実行

サマリー表示用、詳細表示用で2つコマンドは実行します。

  • サマリー表示用(blogに載せる用)
    ブラウザ firefoxスコアでソートを指定して実行。

    docker run sitespeedio/coach \
    http://www.monotalk.xyz -b firefox \
    --sortBy score
    

  • 詳細表示用
    ブラウザ firefoxスコアでソートリソース名の表示アドバイスの説明を表示
    を指定して実行。こちらで指定すると実際にアドバイスを受けた箇所が詳細に出力されます。

    docker run sitespeedio/coach \
    http://www.monotalk.xyz -b firefox \
    --details \
    --description \
    --sortBy score
    

サマリー表示のアウトプット(抜粋)

レポートの上部は、エレメント数や、AMPページか否か等、ページのメトリクスなので、レポートの下部のみ抜粋して記載します。
現状だと以下のようなスコアでした。
Total average は、78点で、0点とかあるので、改善できそうなものはしていきます。

├─────────────────────────┴──────────────────────────────────────────────────────────────────┤
│                                   Best practice advice                                     │
├─────────────────────────┬───────────────────────────────────────────────────────┬──────────┤
│ httpsH2                 │ The page is using HTTPS but not HTTP/2. Change to     │ 0        │
│                         │ HTTP/2 to follow new best practice and make the site  │          │
│                         │ faster.                                               │          │
├─────────────────────────┴───────────────────────────────────────────────────────┴──────────┤
│                                    Accessibility advice                                    │
├─────────────────────────┬───────────────────────────────────────────────────────┬──────────┤
│ labelOnInput            │ There are 2 input(s) that are missing labels on a     │ 80       │
│                         │ form.                                                 │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ headings                │ The page is missing a h2 and has heading(s) with      │ 90       │
│                         │ lower priority.                                       │          │
├─────────────────────────┴───────────────────────────────────────────────────────┴──────────┤
│                                     Performance advice                                     │
├─────────────────────────┬───────────────────────────────────────────────────────┬──────────┤
│ cacheHeaders            │ The page has 11 request(s) that are missing a cache   │ 0        │
│                         │ time. Configure a cache time so the browser doesn't   │          │
│                         │ need to download them every time. It will save 746.5  │          │
│                         │ kB the next access.                                   │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ privateAssets           │ The page has 8 request(s) with private headers. The   │ 30       │
│                         │ main page has a private header. It could be right in  │          │
│                         │ some cases where the user can be logged in and served │          │
│                         │ specific content. But if your is static it should     │          │
│                         │ never be private. Make sure that the assets really    │          │
│                         │ should be private and only used by one user. Else     │          │
│                         │ make it cacheable for everyone.                       │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ javascriptSize          │ The total JavaScript transfer size is 218.2 kB. This  │ 50       │
│                         │ is too much. You need to remove as much as possible.  │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ compressAssets          │ The page has 4 request(s) that are served             │ 60       │
│                         │ uncompressed. You could save a lot of bytes by        │          │
│                         │ sending them compressed instead.                      │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ assetsRedirects         │ The page has 2 redirect(s). 2 request(s) are from     │ 80       │
│                         │ other domains, it could be 3rd-party assets that do   │          │
│                         │ redirects that they really don't need :(              │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ cacheHeadersLong        │ The page has 14 request(s) that have a shorter cache  │ 86       │
│                         │ time than 30 days (but still a cache time).           │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ avoidScalingImages      │ The page has 1 image(s) that are scaled more than 100 │ 90       │
│                         │ pixels. It would be better if those images are sent   │          │
│                         │ so the browser don't need to scale them.              │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ fastRender              │ The page has 1 render blocking CSS request(s) and 1   │ 90       │
│                         │ blocking JavaScript request(s) inside of head.        │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ inlineCss               │ The page loads 1 CSS request(s) inside of head, try   │ 90       │
│                         │ to inline the CSS for first render and lazy load the  │          │
│                         │ rest.                                                 │          │
├─────────────────────────┼───────────────────────────────────────────────────────┼──────────┤
│ optimalCssSize          │ https://www.monotalk.xyz/static/CACHE/css/5ebef948ce… │ 90       │
│                         │ size is 27.8 kB (27816) and that is bigger than the   │          │
│                         │ limit of 14.5 kB. Try to make the CSS files fit into  │          │
│                         │ 14.5 kB.                                              │          │
├─────────────────────────┴───────────────────────────────────────────────────────┴──────────┤
│                                       Score per type                                       │
├─────────────────────────┬──────────────────────────────────────────────────────────────────┤
│ Advice                  │ Score                                                            │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Performance             │ 70                                                               │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Best practice           │ 94                                                               │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Accessibility           │ 97                                                               │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Total average           │ 78                                                               │
└─────────────────────────┴──────────────────────────────────────────────────────────────────┘

各アドバイスに対する 対応する/無視の判断と対応方法

アドバイスは、PerformanceBest practiceAccessibility にカテゴリ分けされています。
各アドバイスを個人的な、無視する後で対応する対応を検討する対応するに分類していきます。

Best practice advice > httpsH2

HTTPS を使っているが、HTTP/2 を使っていないので、使ったほうがいいという警告です。
HTTP/2を実際に使用するためのサーバー設定 - さくらのナレッジを読む限り、使ったほうがいいことはわかりました。HTTPサーバーの都合上設定に時間がかかりそうなので、後で対応するとします。

Accessibility advice > labelOnInput

Form の INPUTタグにラベルを付与したほうがいいという警告になります。
以下のような意見があり確かに、そうかもしれないと思いました。
プレースホルダとHTML5のplaceholder属性
入力フォームのプレースホルダを使ってはいけない – U-Site
しかしながら、どうラベルを配置するかがパッと浮かばなかったので、対応を検討する とします。

Accessibility advice > headings

h2 タグがないという警告です。
対象ページは、h1タグ、h3タグが存在していますが、h2タグが存在しません。文書構造として正しくないというアドバイスです。
対応するとします。
HTML5 ドキュメントのセクションとアウトライン - HTML | MDN
文書構造を意識しながらHTMLマークアップしよう! | Webクリエイターボックス

Performance advice > cacheHeaders

Cache-Control の属性に、Cache-Control: no-cache, no-store, must-revalidate 等付与されているリソースがあるので、外せるのものは外したほうがいいというアドバイスです。
過去に、Django製の Mezzanine で構築されたブログに対して、脆弱性を検証してみる | Monotalk でOWASP ZAP の警告が出ていたので、page自体には付与しています。
その他のリソースで、つけ忘れているものがないか確認したところ、外部ドメイン以外で、font関連につけ忘れていました。
対応するとします。

  • 対応方法
    HTTPサーバーは、Apache で、mod_expires - Apache HTTP サーバ バージョン 2.4 を使用しています。
    対象のfontはwoffなので以下をhttpd.confに付与しました。
    #
    # Add MIME-types for Font
    #
    AddType application/vnd.ms-fontobject .eot
    AddType application/x-font-ttf .ttf
    AddType application/x-font-opentype .otf
    AddType application/x-font-woff .woff .woff2
    AddType image/svg+xml .svg
    
    <ifModule mod_expires.c>
        ExpiresActive On
        ...
        # Font
        ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
        ExpiresByType application/x-font-ttf "access plus 1 year"
        ExpiresByType application/x-font-opentype "access plus 1 year"
        ExpiresByType application/x-font-woff "access plus 1 year"
        ExpiresByType image/svg+xml "access plus 1 year"
        ...
    </ifModule>
    

Performance advice > privateAssets

Cache-Controlprivate ヘッダーが付与されている。
Mainページはしょうがないが、静的なコンテンツ類は、つけたほうがいいというアドバイスになります。
これは、外部ドメインリソースと、ページに対しての警告だったため、無視するとします。

Performance advice > assetsRedirects

外部のドメインの静的コンテンツ参照でリダイレクトが行われているので、リダイレクトしないほうがよいというアドバイスです。
現在リダイレクトが行われているところは対応は難しそうなので、無視するとします。

Performance advice > javascriptSize

javascript の サイズが大きいので、可能であれば小さくしたほうがいいいというアドバイスです。
圧縮と結合をしており、これ以上減らすのは難しいので、無視するとします。

Performance advice > compressAssets

静的コンテンツをgzip圧縮して、配信したほうがいいというアドバイスです。
fontのgzip圧縮設定が漏れていたので対応するとします。

  • 対応方法
    Fontの圧縮指定をhttpd.confに付与しました。
    <IfModule mod_deflate.c>
         # Webフォントの圧縮
         AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
         AddOutputFilterByType DEFLATE application/x-font-ttf
         AddOutputFilterByType DEFLATE application/x-font-opentype
         AddOutputFilterByType DEFLATE application/x-font-woff
    </IfModule>
    

Performance advice > cacheHeadersLong

Cache の有効期限が短いリソースがあるので、可能であれば30日以上にした方が良いというアドバイスです。
一部短いリソースがありましたので、対応するとします。
対象リソースの有効期限を長くしました。

Performance advice > avoidScalingImages

チェックしたページに100pixel 以上の画像が存在する。
ブラウザはこの大きさの画像を必要としないというアドバイスです。
すぐに対応するのが難しかったので、後で対応するとします。

Performance advice > fastRender

レンダリングをブロックする css 、 javascript があることを示すアドバイスです。
async,defer が付与されていない css, javasciprtへのリンクが head 内に記載されているため出ているのかと思います。
こちらは必要な記述なので、無視するとします。

Performance advice > inlineCss

head内で記載されている cssから、初期レンダリングに必要な部分を切り出して、インライン化することを推奨するアドバイスです。
fastRender と関係してくるアドバイスかと思います。
こちらはすぐには修正できないので、後で対応するとします。

Performance advice > optimalCssSize

css のサイズが大きすぎるというアドバイスになります。
どうもTCPのフレームサイズが関連しているようで、14.5KB以下だと早くなるようです。
2つに分割したほうがいいのかもしれません。 後で対応するとします。

修正後、コマンドを再度実行

以下、コマンドを再実行した結果です。
変わってないです。警告数は減ったものの以前0点の部分は0点のままです。
fontに圧縮設定を追加したところ、fewFonts という新たな警告が出力されました。。

├─────────────────────────┴───────────────────────────────────────────────────────┴──────────┤
│                                       Score per type                                       │
├─────────────────────────┬──────────────────────────────────────────────────────────────────┤
│ Advice                  │ Score                                                            │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Performance             │ 70                                                               │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Best practice           │ 94                                                               │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Accessibility           │ 97                                                               │
├─────────────────────────┼──────────────────────────────────────────────────────────────────┤
│ Total average           │ 78                                                               │
└─────────────────────────┴──────────────────────────────────────────────────────────────────┘

まとめ

Coach をインストールして、実行、アドバイスを元に、Webページに修正、HTTPサーバーの設定変更を行いました。
以下まとめます。

  • sitespeed.io は、Coach を内部で使用しており、Coach単独でも実行できる。

  • 実行結果は、ConsoleにTable形式で出力もしくは、json形式で出力できる。

  • YSlow を 測定項目を2017年versionにupdateしていて、HTTP/2 か否か等がチェックできる。

  • PageSpeed Insights の対策済のサイト等は更に得点をあげるのは難しい。(実際対策はしたがかわらなかった。)

イントラネットのサイトにも、同様のチェックを行うことができるので、そこが利点かと思いました。
サイト公開前から定期的に実行してアドバイスをもらうことができます。
また、スクリーンショットの取得ができるので、mobileとして動作させ、スクリーンショットを取得してサイト全体の崩れがないか確認する用途等に使えそうです。
以上です。

コメント