Vue 3 は速くなったのか？

Vue 3 リリースから半年以上が経過しました。
Vue 3 の改善点はいくつかあると思いますがリリース前から言われていた改善点としてより速く、より小さくなるというものがありました。

そこで簡単ではありますが実際にどれくらい速くなったのか調べてみました。

※ 特に記載がない限り 2021 年 3 月 31 日時点の情報になります。

## 短い結論

Vue 3 に更新しても速くなるとは限らない。むしろ遅くなることもある。

## 測定方法

調査するにあたって次の記事で紹介されているコードをお借りしました。

https://ics.media/entry/190731/

https://github.com/ics-creative/160916_performance_js_framework

元の記事ではフレームレートの測定に DevTools の FPS メーターを使用していますがこの機能は廃止されている [^1] ため Frames に表示されているパーセントを記録しています。

測定環境は Windows 10 20H2 上の Chrome 89 です。
60 Hz の Full HD ディスプレイにシークレットウィンドウをフルスクリーン表示したうえで強制再読み込みを行いながら 3 回測定して最も大きな数値を記録しています。

### コードに対する変更

測定しなおすにあたり一部コード修正や依存パッケージ更新を行っています。
変更したコードは次のリポジトリの vue3 ブランチに push しました。

https://github.com/sg0hsmt/160916_performance_js_framework

主に次の変更を行っています。

- 依存パッケージを更新しました。
- browserslist を default に変更したうえでアップデートしました。
- 不要な関数を削除しました。
- eslint および prettier を適用しました。
- vue-functional 実装をテンプレートベースに変更したうえで [`Object.freeze()`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) を使用するように変更しました。 [^2]

また Vue 3 実装を追加しています。

- `vue3-svg`
  - `vue-svg` をベースにできる限りそのまま Vue 3 に移行しました。
- `vue3-functional`
  - `vue3-svg` をベースに関数コンポーネント化しています。
  - `Object.freeze()` を使用した場合にリアクティブでなくなってしまったため `ParticleComponent` コンポーネントのプロパティをクラスから x と y の数値に変更しています。
- `vue3-composition`
  - `vue3-svg` をベースに [Composition API](https://v3.vuejs.org/guide/composition-api-introduction.html) 対応しています。
  - `shallowRef()` を使用した場合にリアクティブでなくなってしまったため `ParticleComponent` コンポーネントのプロパティをクラスから x と y の数値に変更しています。

`ParticleComponent` コンポーネントのプロパティ変更は元記事の趣旨からずれてしまうと思いますがパフォーマンスとリアクティブの兼ね合いで変更しました。

## 結果

| 実装              | Frames | JavaScript メモリ | 転送サイズ |
| ----------------- | ------ | ----------------- | ---------- |
| Vanilla JS        | 34 %   | 3876 KB           | 5.5 kB     |
| Vue 2             | 17%    | 103600 KB         | 104 kB     |
| Vue 2 functional  | 28 %   | 41904 KB          | 105 kB     |
| Vue 3             | 15 %   | 66248 KB          | 95.2 kB    |
| Vue 3 functional  | 27 %   | 33200 KB          | 96.1 kB    |
| Vue 3 composition | 22 %   | 50096 KB          | 95.9 kB    |

期待に反して Vue 3 は Vue 2 より遅いという結果が出てしまいました。
ただし、消費メモリは大きく改善されており転送サイズも小さくなっているようです。

ほかにも Vue 3 ではステートフルコンポーネント (通常のコンポーネント) のパフォーマンスが向上して関数コンポーネントとの違いはわずかになった [^3] ということでしたが大きく差がついています。

※ 上記の表には記載していませんが Vue 3 の functional 実装および composition 実装にて `Object.freeze()` や `shallowRef()` を使用しなかった場合の Frames は通常の Vue 3 実装とほぼ同じでした。

## まとめ

ユースケースによると思いますが Vue 3 に更新しても速くなるとは限らないということを確認できました。
実際に Vue 3 に移行したもののパフォーマンス向上は認められなかったという記事も公開されています。

https://dev.to/omohokcoj/vue-3-real-life-performance-3iie

とはいえ Vue 3 や Composition API は TypeScript との親和性も改善されますので移行する価値はあると感じています。
Vue 3 本体の改善も継続的に行われており Vue 3.2 [^4] ではリアクティブ周りのパフォーマンスとメモリ消費が改善される見込みなので期待しています。

https://github.com/vuejs/vue-next/pull/2345

(2021 年 8 月 30 日追記) Vue 3.2 でも比較してみました。

https://qiita.com/sg0hsmt/items/fae51fe167d9e56d6e75

[^1]: https://stackoverflow.com/questions/63782867/chrome-fps-meter-no-longer-shows-frame-rate
[^2]: https://vuedose.tips/improve-performance-on-large-lists-in-vue-js/
[^3]: https://v3.vuejs.org/guide/migration/functional-components.html
[^4]: (2021 年 7 月 4 日追記) 当初は 3.1 のマイルストーンに入っていましたが 3.1 での対応は見送られて 3.2 開発ブランチにマージされました。