導入
こんにちは、もんすんです!
私の個人アドカレであるひとりアドカレ2024 byもんすん Advent Calendar 2024の25記事目をお届けいたします🎄
ついに最終回となります。。
私が担当していたプロジェクトでは、Nuxt3をベースに開発されているものがありました。
元々は状態管理にVuex
を採用していましたが、最新のプロジェクト要件や技術トレンドに対応するため、Pinia
に移行しました。
今回はPinia
への切り替えについて紹介していきます。
VuexとPinia
なぜVuexを利用していたか
VuexはVue.js公式の状態管理ライブラリであり、長年にわたってVueエコシステムの中核的な存在として活用されてきました。
当プロジェクトでも、当時ドキュメントが充実しており、コミュニティも活発であったことから、プロジェクト初期においては安定性と信頼性が重視され、選択されました。
なぜPiniaに乗り換えたか
プロジェクトを進めていく中で、Vuexのいくつかの課題や、Piniaの新しい利点が浮き彫りになり、移行を検討することになりました。
PiniaはVue3とそのComposition APIを念頭に設計されています。
Vuexと比較してAPIが直感的でシンプルです。
特に、ステート、ゲッター、アクションの定義が簡潔になり、コード量が大幅に削減されました。
また、Vue3の登場により、Vueエコシステム全体が進化しています。
その中で、Piniaは公式に推奨される状態管理ライブラリとなり、今後の標準となる可能性が高いと判断しました。
Piniaに乗り換え手順
パッケージのインストール
以下のコマンドを実行します。
私のプロジェクトでは、データをSessionStorageに保持したかったため、pinia-plugin-persistedstate
を入れていますが、なくてもpinia
を利用することは可能です。
npm i pinia @pinia/nuxt pinia-plugin-persistedstate
ソースコードの変更
では、ソースコードの変更です。
Vuexを利用していた時は、モジュール用のソースの他に、accessor
とstore/index.ts
という全Storeデータをまとめた処理も実装していました。
Vuex(変更前)
- モジュール
import { Module, VuexModule, Action, Mutation } from 'vuex-module-decorators'
export const COUNT_MODULE = 'CountModule'
import { inject } from 'vue'
@Module({
name: COUNT_MODULE,
namespaced: true,
stateFactory: true,
})
export default class CountModule extends VuexModule {
private count = 0
get getCount() {
return this.count
}
@Mutation
public resetCount() {
this.count = 0
}
@Action
public fetchCount(){
// 非同期でのCount取得処理など
GetCountService.get().then((count) => {
this.count = count
})
}
}
- accessor.ts
import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import CountModule from '~/store/count-module'
let countStore: CountModule
function initializeStores(sessionStore: Store<any>, localStore: Store<any>): void {
countStore = getModule(CountModule, sessionStore)
}
export {
initializeStores,
countStore,
}
- store/index.ts
import { Store } from 'vuex'
import { initializeStores } from '~/store/accessor'
import CountModule, { COUNT_MODULE } from './count-module'
import VuexPersist from 'vuex-persist'
const vuexSessionStorage = new VuexPersist({
key: 'vuex',
storage: window.sessionStorage,
modules: [
UNREAD_MESSAGE_COUNT_MODULE_NAME,
],
})
const sessionStore = new Store({
modules: {
CountModule,
},
plugins: [
vuexSessionStorage.plugin,
],
})
const initializer = (sessionStore: Store<any>) => initializeStores(sessionStore)
initializer(sessionStore)
export const plugins = [initializer]
export * from '~/store/accessor'
Pinia(変更後)
import { defineStore } from 'pinia'
import { inject, ref } from 'vue'
export const useCountStore = defineStore('CountStore', () => {
const count = ref(0)
const resetCount = () => {
count.value = 0
}
const fetchCount = () => {
// 非同期でのCount取得処理など
GetCountService.get().then((newCount) => {
count.value = newCount
})
}
return {
count,
resetCount,
fetchCount,
}
}, {
persist: {
storage: sessionStorage,
}
})
Piniaの方がかなりシンプルに記述できていることかと思います。
最後に
Piniaへの移行は、コードのシンプルさだけでなく、開発体験の向上やメンテナンス性の向上にも大きく寄与しました。
Piniaの導入はスムーズでありながら、Vue3に最適化されたモダンなアプローチを提供してくれます。
ぜひ、みなさんのプロジェクトでもPiniaを試してみてください!