【視聴メモ】 Elevating the Web Platform with the JavaScript Framework Community (Google I/O ’19)

この記事は Google I/O '19 のセッションの視聴メモです。
想定読者は自分なので正確性や網羅率には問題があるかもしれません。

---

## References

https://www.youtube.com/watch?v=-xZHWK-vHbQ

Speaker(s): Shubhie Panicker and Nicole Sullivan

## Abstract

Chromeがオープンソースプロジェクトと協力して行ってきたWebプラットフォームとツール、フレームワークの改善について紹介します。

## Contents

### 1. Year in review: collaborating with frameworks

**Chunking code**

シングルスレッドでユーザーからの入力にただちに応答するためには、メインスレッドで行われている処理を細切れに分割していつでも割り込みができるようにして置かなければならない。発表者のチームはタップ時の遅延について分析を行った。

* ユーザーの操作がブロックされるまでに10msから50msの時間がかかっていた
* React や Vue などのライブラリはレンダープロセスを小さなチャンクに分けている
    * よってレンダリングサイクルの途中でもユーザーの入力を受け付けることができる
    * これは各ライブラリのすぐれたスケジューラーによって実現されているが、もちろんそのスケジューラーはアプリ全体の面倒を見ることはできない
    * フレームワークは次のシグナル情報がないためそれが行えない
        * Fetch responses
        * Script tag responses
        * Callbacks e.g. onreadystatechange in xhr
        * Browser internal work like garbage collection
    * というわけで全く新しいスケジューラーを作ることにした

**Scheduling API**

スケジューラーの説明

* JSの処理はプライオリティレベルで４つに分けられる
    * 緊急でない処理をレンダリングをブロックしない処理に移動する
    * Defaultレベルとなるプライオリティにありとあらゆるタスクが入ってしまっていて整理がつかない
    * そこでDefaultレベルのタスクをさらにHigh/Medium/Lowにわけた
    * プロトタイプを作り始めたばかり
    * https://github.com/WICG/main-thread-scheduling
* 下記のような感じでスケジューラーにタスクを登録していけば良いらしい

```
function importantWork() {
  ...
}

let task = scheduler.postTask(importantWork, {priority: 'high'});
```

**isInputPending**

* isInputPending というAPIをChromeに追加した
* Reactなどのライブラリがユーザーの入力があるかどうかを判断するのが簡単になった
* Facebookの人がChromiumに追加した

**Display Locking**

* JSにより操作されるどのDOMがレンダリングされる必要があるのかをブラウザが知れるようになった
* スクロールコンテンツやタブ・ウィジェットなど様々なユースケースでパフォーマンスを発揮する

### 2. Nuanced Performance Goals

**Page load time and SPAs**

* SPAサイトの開発者は常に速いけど意味のない画面の表示と遅いけど意味のある画面の表示というトレードオフと戦っている
    * ちなみに後者を選びがち
    * SPAサイトの遷移時間は測定するのが難しい
* 発表者の目的は開発者がそのようなトレードオフをしなくてよくなること 

**Budgets for total resource sizes**

* critical resources の量は１ページに付き170kbに収めたほうが良い
    * コードもデータも全てで170kb
* Code Splitting と SSR が重要になってくる

### 3. Secrets of facebook & google internal tools 

* インクリメンタルローディング
* Google Hotel の事例
    * ユーザーの入力を受け付けるまで時間がかかりすぎている
    * ほとんどのユーザーが使わない機能の処理は無駄
    * 見た目はできていているのでユーザーが入力しようとするが、裏で処理が走っていて入力できない時間がある
        * uncanny valley (不気味の谷)と呼ばれていた
        * 反応がないと思って何回もクリックするやつ
    * ページが複雑だとSSRが非常に重くなってしまう
    * → Interaction driven late-loading
        * フォームだけ用意して処理はあとからダウンロードする
        * 基本的にはプリロードしておくことでネットワークの遅延による影響を最小にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3387/170b7ed9-5cf2-3ff7-fd49-c1e7d8c53b3f.png)

* jsaction というGoogle製のライブラリを使ってイベントをデリゲートする
    * 真のイベントハンドラーがロードされるまでユーザーのクリックイベントをキューイングする
    * イベントと真のハンドラーをDispatcherが紐付ける

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3387/b685e605-08d5-2698-ed4a-01d44f2b4b20.png)

* コードの次はデータ
    * 初期データはフッターに入れてる
* Streaming SSR
    * Smart SSRとも呼ばれていた
    * 主要なコンポーネントごとにSSRを行い順次表示するSSR（？）
* HTTP Cascade from native code splitting
    * コードに Code split point を設け、段階的にレンダリングしていくこと
    * Facebookでは未レンダリング要素をLoading要素として表示している
    * ReactのLazyとかSuspenseの話かな？

まとめ（下図） 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3387/b5ef235a-6350-e62f-b479-2637401356b6.png)

* FacebookとGoogleはこれらの要素に完全に独立に到達した
* それ自体がこのリストの正当性を証明していると言える

### 4. Bundle bloat and npm modules

* 不必要なJSをどう扱うか
* JSバンドルの中に真に不必要なコードが２０%から３０%ほど含まれているということはまったく珍しいことではない
* npmモジュールの中のJSをどう扱うかが重要なのだが、GoogleもFacebookもどうすれば良いかわかってない
    * この問題がしんどいのは次の３つの理由が主な理由
    * 1. 過度なトランスパイルがJSサイズの膨張と控除の難しさを招いている
    * 2. 新しいブラウザは不必要なポリフィルを受け取っている
    * 3. 1と2によるコードの重複
* 普通のサービスのコードの97%はnpmモジュールによって入れられた外部依存
    * また、1000個の外部依存を持っている
* 非常に薄いレイヤーでユニークなアプリケーションを作れているというのは素晴らしいことだが…
* とりあえず webpack-bundle-analyzer を見てみよう
    * Reactが２個入ってたりmoment.jsが３個入ってたりしないですか…
* Module と NoModule
    * script タグで `type="module"` や `nomodule` を指定することでブラウザによって読み込むファイルを切り替えられる
    * Angularに実装された Differential loading は7~20%のサイズ減少という効果を発揮した
    * moduleをサポートしているかどうかでしか切り替えられないので、将来的に同じ問題に立ち向かうことになるんだけどね
* longer term solution を思いついたら私達に連絡してね
* Framework fund に応募してね

## Memo

* 自分がある処理を実装するときに Scheduler を使ってまでパフォーマンスを上げたいかと言うと微妙かも知れないけど、様々なライブラリが簡単にスケジュール管理できるようになると考えると、一般のサービス開発者にとってもメリットが大きそう
* OSSをどう改善したかという話かと思ったらWebページのパフォーマンスを向上させるための様々な施策についてデータ込みで語られていて面白かった
* かなり内容の濃い発表だったので消化に時間がかかった
    * ようはReactの話なんだけど
* フロントエンド、やらないといけないことが多すぎ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3387/4c69945a-84ba-f7bd-24bb-5ece56a1e42f.png)