Vueの秘密のパフォーマンステク9選紹介

# VueConf USでのさまざまな発表

今年の3月に [VueConf US](https://us.vuejs.org/) が開催されました。最近になってビデオが公開されて初めて知ったこともあるので本記事ではその紹介をします。

https://www.vuemastery.com/conferences/vueconf-us-2019/state-of-vuenation/

いろいろ面白いトピックがあるのですが、特にVueコアチームのGuillaume Chauさんによるパフォーマンス改善テクニックはまじかーという感じだったのでここにまとめたいと思います。

# "9 Performance Secrets Revealed with Guillaume Chau"

[![9 Performance Secrets Revealed with Guillaume Chau](http://img.youtube.com/vi/5B66qer8cZo/0.jpg)](http://www.youtube.com/watch?v=5B66qer8cZo)

- プレゼン動画: http://www.youtube.com/watch?v=5B66qer8cZo
- スライド: https://slides.com/akryum/vueconfus-2019#/
- デモサイト: https://vue-9-perf-secrets.netlify.com
- ソース: https://github.com/Akryum/vue-9-perf-secrets

↑本記事より元動画見たほうが5京倍くらい分かりやすいので是非見ましょう！

## 1. Functional components

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/79346806-02e7-0ca1-05f4-2d00f685e08b.png)

:innocent: スクリプト処理削減

- しょっぱなはまあぜんぜん秘密テクではないです。関数コンポーネント化です
- →[関数型コンポーネント](https://jp.vuejs.org/v2/guide/render-function.html#%E9%96%A2%E6%95%B0%E5%9E%8B%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88)
- 関数型にすると、ライフサイクルメソッドやlocal stateを持たず、propsを受け取ってrender結果を返すだけのシンプルな処理になります
- 毎フレーム生成と削除を行ったりするようなコンポーネントのscripting処理削減に効きます

## 2. Child component splitting

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/6af77557-533e-d726-9803-24645c61fa5a.png)

:innocent: スクリプト処理削減

- 重い処理を子コンポーネントに逃がします
- 正直これでなんで速くなるの？ってよく分かってません :weary: 
- 詳しい人コメントください

（追記）

コメント欄で解説していただきました。
元コンポーネントではnumberの変更のたびにupdateされてheavy()が再実行されてしまっていたんですが、numberに依存しないコンポーネントに分けることでライフサイクルを分離し、heavy()が再実行されないようするという改善となっています。
@masaha03 さん、@kazupon さんありがとうございます！ :pray: 

## 3. Local variables

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/615635c4-5e6f-8d12-053c-8639d8755bc3.png)

:innocent: スクリプト処理削減

- reactiveな値は取得ロジックが走るので、ループの中では事前にlocal変数に代入したほうが余計な処理しません
- 大量にアクセスすると塵が積もって処理負荷に繋がる

## 4. Reuse DOM with v-show

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/11caa5e4-aacc-6ebf-375f-c3e0416a3ac3.png)

:innocent: スクリプト処理削減
:weary: メモリ使用増

- v-ifとv-showの使い分け。まあこれも秘密ではない基本テク
- v-showだと単にhideするだけなのでDOMを保持する。destroyしないので再表示が速い
- ただしメモリは食う

## 5. Keep-alive

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/c099d2b6-d0df-3175-c298-e2ac305b6815.png)

:innocent: スクリプト処理削減
:weary: メモリ使用増

- 前述のv-showと同様な効果
- https://jp.vuejs.org/v2/api/#keep-alive
- 動的コンポーネントをキャッシュするのでrouter-viewを保持したいときはこれを使う
- destroyしないので重いページの再表示が速くなる
- もちろんメモリは食う

## 6. Deferred features

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/47bf329c-566f-3e27-f1e6-698bc09868e8.png)

:innocent: 体感速度向上

- 遅延処理の実装
- 処理負荷が高くて数秒フリーズしてしまうようなページの場合、要素を段階的に読み込ませることで即座に遷移が可能になる
- 高負荷部分はmount時にv-ifでskipし、mount後に指定frame数タイミングをずらして読み込んでいく
- 実際の処理速度が向上しているわけではないが、ユーザーの体感速度（perceived performance）が上がるのでUX改善になる

## 7. Time slicing

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/141f41cc-0440-eb83-c330-98488f7e0b3a.png)

:innocent: 体感速度向上
:weary: 処理完了時間増

- こちらもフリーズ対策
- 処理負荷が高くてアプリがフリーズしてしまうと、ユーザーのインタラクションを受け付けられないしローディング表示などもできなくなってしまいます
- 処理をいっぺんにやるのではなく、単位時間あたりのキューに分割することでレンダリングを止めないようにする
- 1フレームごとの処理量を小さくするほどレンダリングを妨げないようになるが、完了までの時間は長くなるのでトータルのバランスを考える

## 8. Non-reactive data

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/97e322d8-f352-7b68-beb7-16f0ef662c14.png)

:innocent: スクリプト処理削減

- reactiveなObject内で、reactiveにする必要がないpropを非reactiveにして最適化するテク
- 全然知らんかった。目からウロコ
- `Object.defineProperty` の引数 `descriptor` を `configurable: false` にして加えることでreactiveの対象から外すことができる
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
- このデモの場合は17倍も処理が向上

## 9. Virtual scrolling

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117743/56f3b3d8-0e00-17ce-35ce-75f7ed2bd7f9.png)

:innocent: スクリプト処理削減
:innocent: レンダリング処理削減

- 大量のリストをスクロール表示をする場合に、見えている範囲だけ描画する仮想スクロールテク
- 特にVueに限らない一般的な最適化処理。Guillaume Chauさん自身が仮想スクロールライブラリ作ってるのでオマケ的な紹介かも？ https://github.com/Akryum/vue-virtual-scroller
- デモだと一万件のリストをそのままレンダリングしようとするとクラッシュするけど、Virtual scrollingすれば何個でも大丈夫！

# まとめ感想

- 単にVueを使ってWebページ表示するだけならそんなに気にしなくていいと思います
- 数百個以上のオブジェクトを何度も書き換えて継続的に再レンダリングするようなアプリ志向の局面で有用になってくる
- 60fpsを切ってしまう重い処理や、フリーズしてインタラクションを受け付けない時間が発生してしまうような場合にはこうした最適化が求められる
- なんか重いなと思ったらScripting処理とRendering処理を計測してどこに改善の余地があるか検討しましょう