Vue.js v-tokyo Meetup #19 に参加してきました

2024/03/06 OPTIMさんのオフィスで開催された Vue.jsのMeetupイベントにリアル参加してきましたので、お聞きしたLT内容など、メモを元にご紹介します。

※ 間違い/解釈違いが含まれる可能性もあるのでご注意ください。もしお気づきの点あればそっとコメントで教えて頂けると嬉しいです。

## イベント概要
[Vue.js 日本ユーザーグループ](https://vuejs-jp.org/)のMeetupイベント、参加者は60名ほどでした。

### Connpass 
https://vuejs-meetup.connpass.com/event/309755/

### お知らせ
`VueFes 2023` の次の会 `VueFes 2024`が2024/10/19に開催するそうです。
お時間あれば、みなさん参加しましょう
(そしてVueを技術スタックに採用しもっと布教しましょう)

## LT・セッション

### Vue.jsを用いて数万の農地のデータを数秒で表示させるまでのカイゼンの軌跡 (西村さん)
[ドローンを使ったピンポイント農薬散布システム](https://www.optim.co.jp/agriculture/services/pts)の散布範囲設定画面(マップ)にVueを利用しており、その範囲表示(ポリゴン)が重いという問題を改善したというお話。

- 改善1 初回に必要なデータを一括取得・範囲計算してPiniaストアに代入
  - 範囲を動的に計算せず予め結果を求めておく
  - ストアから画面に必要な一部だけを取ってくる
- 改善2 ポリゴン数を減らす
  - ズーム倍率を下げた場合は、四角形に正確に表示するのでなく中心点だけを表示する
- 結果
  - 16秒ほどかかっていた描画を7秒まで縮めることができた

#### 感想
自分もつい最近パフォーマンスの最適化をするタスクをやったので、同じような苦労をしてるなぁと思いました。事前にデータを求めておく、そもそも表示するデータ数を減らすというのは基本として覚えておいたほうが良さそうです。


### [defineModelを使って気軽にコンポーネントのv-modelをやろう](https://speakerdeck.com/nishiharatsubasa/definemodelwoshi-tuteqi-qing-nikonponentonov-modelwoyarou) ([にしはらさん](https://twitter.com/crayfisher_zari))
Vue3.4から追加されたdefineModelの布教のお話。

- 簡単に双方向bindができるVueのv-model
  - HTML要素は 単に `<input type="text" v-model="newValue" />`のようにbindできる
  - これがコンポーネントの場合、propsとemitsと `@handleClick`等を書く必要があり面倒だった
- 新型記法 defineModel
  - `const model = defineModel<string>();`
    - この1行で 双方向同期 / prop / emit の定義が完了する
    - 定義したものはref値として扱える + v-modelにそのまま使える
    - defineModelを繰り返せば 親/子/孫まで データを受け渡しできる
      - (バケツリレー(PropsDrilling)も 負担が減る

#### 感想
propとemitの定義は地味に面倒だったので、defineModelの登場はとても便利でぜひ使って行きたく思いました。

### [軽率にVue 3でリアルタイム3Dアプリを作れるライブラリを作ってみた](https://speakerdeck.com/drumath2237/vue-with-3d-app) ([にー兄さんさん](https://github.com/drumath2237))
Web3D系のライブラリ [Babylon.js](https://www.babylonjs.com/)をVueで簡単に扱えるようにするラッパー[BabyuwuJS](https://github.com/drumath2237/BabyuewJS)を作った話

- 前提
  - Babylon.jsは Web3D(webGPU)を扱えるライブラリ
    - 3Dゲーム等の高度なアプリに最適
  - Three.jsは同じくWebで3DCGを扱えるライブラリ
    - シンプルなAPIで簡単な3DCGアプリケーションを作るのに最適
- 既にあるライブラリ事例
  - React + Three.js の react-three-fiber
  - Vue + Three.js の Tresjs/tres
    - Vue + Babylon.jsが無かったので開発
- vueで書けるメリット
  - template記法でコンポーネントとして3Dオブジェクトを扱える

#### 感想
Web3Dは AR程度しか試したことがないですが、Vueを使い複雑な3DCGアプリができたらなかなか面白そうです。VueでWeb3Dを使う事例がもっと増えたらやってみたいです。


### [BuefyのMaintainerを引き継いだ件](https://speakerdeck.com/kikuomax/buefynomaintainerwoyin-kiji-idajian) ([kikuomaxさん](https://github.com/kikuomax))

Vue2で利用されていたBulmaベースのUIフレームワークBuefyをVue3に移植しメンテナンスをしているというお話。

- Vue2からVue3への移行で苦戦した点(移行の技)
  - 1 extendの廃止
    - extendに依存して どこでもmodalを出せるUI機能(グローバルDOM干渉)がvue2ではあった
    - 黒魔術でなんとか動くようにした
  - 2 vue-18nと相性が悪かった
    - globalに突き刺さっているvue-i18nのAPIの参照をbuefy内でも扱える必要があった
  - 2 propの初期化・thisの置き換え
    - this._uidのようなユニークIDがvue3では使えない
      - とりあえずで UUID()等を使うとSSRで hydrationMismatchが起こる
    - nullを初期値にしてユニークIDは computed内で求めるように
  - 3 vue3.2.25 での変更対応
    - vue3.0.11で変わった v-for内でのrefの扱いが、vue2系のような挙動に再び戻された
- vue3に対応しているリポジトリ
  - https://github.com/ntohq/buefy-next

#### 感想
昔使っていたUI FWなので、まだ保守されているのはとても嬉しく思いました。
一時期はBuefyの更新が止まっていたため、UI Frameworkに依存しないという[OrugaUI](https://oruga-ui.com/)のBulma版が移行先におすすめされていたのを思い出しました。こちらとどちらがいいか、今後試してみたいです。

### vue3-openlayersを使ったGISシステム [(okameさん)](https://github.com/okame)
気象情報のマップビジュアライズ機能(地図上に気象状態を表示する機能)を開発中、便利なライブラリのお話。

- [openlayers](https://openlayers.org/)
  - 素のJavascript向けのマッピングライブラリ
  - 書き方はGoogleMapのJS APIに似ている
- [vue3-openlayers](https://vue3openlayers.netlify.app/)
  - openlayersをvue3向けにラッピングしたライブラリ
  - 地理情報を使ったものを作る場合便利
  - template内でレイヤー、アイコン、地域枠等をvueコンポーネントで表現できる
    - 動的に変更できる (v-ifやv-for、@ click等が使える)
  - 嬉しいこと
    - 書きやすい
    - ライブラリの癖を意識せずに書くことができる
  - 嬉しくないこと
    - メモリのオーバーヘッドがある程度ありそう

#### 感想
openlayersというライブラリの存在をまず知らなかったので、マップを使うアプリを今後使うことがあればvue3-openlayersを調査してみようと思います。

### [Nuxt Test Utils で始める効率的な Nuxt アプリケーションのテスト](https://speakerdeck.com/wattanx/getting-started-with-nuxt-test-utils-for-efficient-testing-nuxt-applications) [(wattanxさん)](https://github.com/wattanx)
Nuxtでテストを行う場合、予めNuxt向けの便利なテストユーティリティが詰まっている [@nuxt/test-utils](https://github.com/nuxt/test-utils)がおすすめというお話

- `@nuxt/test-utils`
  - Nuxt向けのテストライブラリ
  - 通常は大変なNuxt固有の処理の呼び出し・モックが簡単にできる
  - 対応しているテスト
    - Unitテスト
    - E2Eテスト
- 対応するUnitテスト (vitest)
  - useFetch / plugin inject / autoImport / plugin / middleware / modules などなどのNuxtランタイム依存のものを実際に動かしたりモックしたりができる
  - indexedDBやinteractionAPIもモックできる
    - 通常Node実行環境にないBrowserのAPIをモックできる
  - バックエンド側のものも registerEndpointでAPIモックできる
  - mockComponentでコンポーネントをモックできる
- 対応するE2Eテスト(ブラウザなし) (jest/vitest)
  - $fetchでレンダリングした結果となるページのHTMLを取れる
- 対応するE2Eテスト(ブラウザ有り) (playwright)
  - ページ操作をテストできる
- このテストライブラリでできることと主な用途まとめ
  - ユニットテスト: Nuxtの関数などなどのテストに
  - E2Eテスト(ブラウザなし): サーバーサイドレンダリングのテストに
  - E2Eテスト(ブラウザあり): ユーザーが触るレベルのテストに

#### 感想
今はNuxtを使えていませんが、Nuxtを使う機会が来たらまず利用できないか検討しようと思います。公式サイトにも書かれていたため、テストの柔軟性が高そうです。

### [Vue3.4](https://speakerdeck.com/kazupon/vue-3-dot-4) [(kazuponさん)](https://github.com/kazupon)
vuejs core team kazuponさんによる直々のvue3.4変更についてのお話。

#### 内容

##### 主な変更
  - 新機能
    - defineModelの安定化
    - v-bindの省略
  - 改善
    - ビルドパフォーマンス改善
    - 実行パフォーマンス改善(特にcomputed)
    - ハイドレーション周りの改善
    - エラー時Vueの内部エラーコードが出力されるように
  - 廃止
    - グローバルなJSXの型定義削除
    - vnodeの記法変更
    - v-isの記法変更

##### 詳細
- defineModelの安定化
  - (前述の通りなので省略)
- v-bindの省略
  - `<input type="text" :value="value" />` を `<input type="text" :value />` と書けるように
- ハイドレーション周りの改善
  - SSRでクライアントとHydrationMismatchした場合のエラーが非常にわかりやすく改善
    - エラーした箇所 / DOMの差等がコンソールにわかりやすく出るように
- プロダクションでのエラー時もVueの内部エラーコードが出力されるように
  - プロダクションビルドでも、エラー発生時 コンソールにエラーコードとリファレンスURLを吐いてくれるように
- ビルドパフォーマンス改善
  - 44%改善 (SFC -> JSのコンパイル)
    - パーサーをフルスクラッチ
    - ソースマップ生成の最適化
    - SFCテンプレートのコンパイル最適化
      - パースが2回実行されるのを回避
- 実行パフォーマンス改善(特にcomputed)
  - watchでcomputedを使った場合の問題解決
    - 値が変わってないのにwatchで再計算されてしまう
    - shiftやspliceでwatchが何度も発火してしまう
      - 不要なGCを避けて改善
  - reactive effectの効率化
    - 無駄なcomputed再計算を避けた
    - 内部スケジューラを改善
- グローバルなJSXの型定義削除
  - プライベートなjsx/tsx型定義であれば今後も別設定で書ける
    - 型だけなら破壊的変更でなくセーフ扱い
- ReactivityTransform(Experimental)の削除
  - 予定通り削除
- provide / injectで定義したrefが .valueを付けないとtemplate内で読めない問題の回秘策を削除
  - 根本的バグを修正したため
- v-node-before-mount等のフックを vue:before-mount等にリネーム
- v-is="hoge" を `is="vue:hoge"` にリネーム
  - (DOMテンプレートでVueコンポーネントを使う、WebComponents等用のもの
  - v-isとisを使い分ける必要をなくすための変更

##### まとめ
- defineModelとv-bindの省略は便利なためおすすめ
- ビルドパフォーマンスと実行パフォーマンス両方上がるので DX/UX向上
  - vue3.4のアップデートを要検討

#### 感想
computedが早くなったという評判をTwitterで見て、以前からvue3.4を検討していました。リリースノートを読んだ通り、破壊的な変更はやはりないようで安心しました。HydrationMismatchのエラーメッセージ明確化や、Vueのエラーコード出力は エラーの解決に非常に役立ちそうで助かると思いました。

## 完走した感想
使ったことがない変わったライブラリの紹介があり、面白かったです。
また、普段の担当プロジェクトでは、まだVue3.4に上げられていないため、やはり早急にバージョンを上げたいなぁと思いました。

なお、今回は会場スポンサーのOPTIMさんに、(ドローン等技術を活用して作られた)石川能登のスマート米を振る舞ってもらいました。美味しかったです。