PageSpeedスコアを左右する「ロングタスク」を体感する

# 2020/6/3 追記

本家レポートより**PageSpeed Insightsのスコア改善が捗る裏レポートツール**を公開しました。合わせてご参考ください。
https://simulate.site/cheatspeed-insights/

# PageSpeedスコアの「インタラクティブになるまでの時間」

PageSpeedスコアが計算される上で、最も重視される指標が**「インタラクティブになるまでの時間」(TTI)**です。

[PageSpeed Insightsの点数はどのように計算されているか。100点をとるための条件](https://qiita.com/miyanaga/items/d38124cdd64a1999fed9)

この**「インタラクティブになるまでの時間(操作可能になるタイミング)」**について、公式では以下のように説明されていますが、

> 「操作可能になるタイミング」とは、レイアウトが安定して、主要なウェブフォントが表示され、メインスレッドでユーザー入力を処理できる状態になるタイミングとして定義されます。
> https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive?hl=ja

もう少し詳しく調べてわかったことを以前、[インタラクティブになるまでの時間(TTI: Time To Interactive)とは何か](https://qiita.com/miyanaga/items/49aee938d1cbb1e42fd7)にまとめました。

## 50ms以上の「ロングタスク」

Lighthouseのソースコードとしては以下のファイルにロジックが記述されていることがわかり、上記の考察はおおよそ合っていたと理解しました。
[/lighthouse-core/computed/metrics/interactive.js](https://github.com/GoogleChrome/lighthouse/blob/0f600e0cd3b6f1bd8be10d5b4ede9edcfc4940fb/lighthouse-core/computed/metrics/interactive.js#L90)

実際ほとんどのページでは、初期段階に起こりがちな重たい処理(`ロングタスク`:50ms以上メインスレッドを専有する処理)が、5秒以上収束するタイミングを**インタラクティブになるまでの時間**と呼ぶこととなります。

ロングタスクは、JavaScriptが引き起こす以外にも、レンダリングやペイントによって発生することがあります。

ついでに言うと、公式の説明にある「レイアウトが安定して」「主要なウェブフォントが表示され」という部分は実際、見てなさそうです。

## ロングタスクを駆逐せよ

TTIについてのスコア改善の理想は(実際は難しいのですが)、**50ms以上メインスレッドを専有する「ロングタスク」をJavaScriptから無くすこと**です。

ロングタスクが一切発生しなければ、早いタイミングで`インタラクティブになるまでの時間`を迎えます。その場合は、`DocumentContentLoaded`イベントの終わりか、重たいレンダリング処理の終わりでTTIが評価され、PageSpeedスコアは高得点が期待できます。

しかし、たかだか50msの処理がどれだけ応答性を阻害するのでしょうか？

それをとりあえず体験してみる環境を作ってみました。

# ロングタスクを体験するサンプルページ

ロングタスクとして、メインスレッドで空の`for`ループを回すダミータスクを定期的に発生させてみます。

実際のWebページに近いサンプルとして、[Colorlib](https://colorlib.com/)で無償公開されているテンプレートをいくつか拝借しました。

スマホでの閲覧をお勧めします。
https://www.ideamans.com/_samples/long-tasks/

いずれかのサンプルを開くと、こんな感じで右下に簡単なコントロールパネルが表示されます。

<img width="470" alt="Neuron_HTML_CSS_Template.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35178/97c46436-493b-b1c1-c38e-8287bdf41ce8.png">

* `LONG TASK ≧ 50ms` 50ms以上のロングタスク実行中に点灯
* `Dummy Tasks` ダミータスクを発生させるか(ON/OFF)
* `Duration Mean` ダミータスクの平均所要時間(ms)
* `Task Interval` ダミータスク間の間隔(ms)

`Apply`で設定を変更します。`Index`でサンプルテンプレートの一覧に戻ります。

ダミータスクの所要時間は、`Duration Mean`を期待値(母集団の平均値)とする正規分布に基づき、乱数で決めています。パラメータをいろいろ変えて試してみてください。

<table>
<tbody>
<tr>
<th>ロングタスクなし</th>
<th>ロングタスクによる引っかかり</th>
</tr>
<tr>
<td>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35178/b04813de-fbb1-cf96-90c4-3301e4a40a14.gif">
</td>
<td>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35178/f0fabae3-9e0c-5779-a58e-5fe7a446b45e.gif">
</td>
</tr>
</tbody>
</table>

## 素のスクロールにはあまり影響しない

上記のサンプルページではスムーススクロール系ライブラリが利用されているため、スクロール操作で引っかかりまくりですが、そうでないページではスクロールに大きな違和感はありません。

例えば、[次のサンプルページ](https://www.ideamans.com/_samples/long-tasks/juli/)は、JavaScriptによるカルーセルスライダーのひっかかりはあるものの、ページ自体のスクロールはなめらかです。

<table>
<tbody>
<tr>
<th>スクロール系ライブラリなし</th>
</tr>
<tr>
<td>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35178/25dcfafe-e6f3-cda2-81b0-9561a16d21b7.gif">

</td>
</tr>
</tbody>
</table>

# まとめ

## 閲覧中心のページではロングタスクを感じにくい

静的なコンテンツをスクロールで閲覧するだけの読み物系のページでは、ロングタスクによるストレスは感じにくいと言えるでしょう。

これが確認したかったことのひとつでした。多くのWebページは上記のような目的なので、トラッキングタグなどによるロングタスクによってPageSpeedスコアが低迷しても、**「遅いとは感じない」**という認識の不一致を招きがちです。

## PageSpeedスコアの「インタラクティブ」の条件は厳しい

ロングタスクは引っかかりを起こすものの、まったく操作できなくなることはありません。言葉の印象としても、`インタラクティブ`とは性能はさておき**ユーザーの操作への応答性自体の有無**を示すような気がします。

ところがPageSpeedスコアにおいては、50msという短い引っかかりも許さない**非常に高い応答性能を示す状態**を`インタラクティブ`と評価します。

かなり厳しい基準です。Google AnalyticsやAdSenceなど一般的なサードパーティスクリプトを導入するだけで、通常はスコアが下がります。

このサンプルでは引っかかりがわかっているから許容できるものの、急に起きたらストレスだろうなぁ…とも思います。

## なくせないロングタスクは遅延させる

サードパーティーのロングタスクは手を出せないので、遅延させるしかありません。

例えば広告表示のスクリプトであれば、少しスクロールされたタイミングで起動すると、PageSpeedスコアの採点からは逃れることができます。