🍍

Vue3(Nuxt3)にて、PiniaさんでStoreを永続化する実験したよ

2023/05/06に公開

Piniaさんがかわいい


まず何の話?ってなるかも。
このかわいいパイナポーのPiniaさん。
Vue3では、storeライブラリでPiniaを使うことを推奨しています。

https://pinia.vuejs.org/

Vue2まではVuexがそのポジションにいたので、そちらのほうが耳馴染みがあるかもしれないし、
Vuexも一応現在Ver.4まで上がっていてVue3対応になったり、頑張ってくれているようです。
https://vuex.vuejs.org/ja/

でも、Nuxt3の公式ページでは、Piniaちゃんが一番上に出てくるので、
それに従って使ってみることにしました。

https://nuxt.com/modules?type=3rd-party

環境

  • Mac M1 Venture13.1
  • nuxt 3.4.1
  • @vue/cli 5.0.8
  • typescript@4.7.4

    あとなにがいる?(いつも言っている)

参考リンク

こちらは公式(再掲)
https://pinia.vuejs.org/
https://www.npmjs.com/package/pinia

でも、我々の環境はNuxtなので、こちらを使います。
https://pinia.vuejs.org/ssr/nuxt.html
これのほうがいいか
https://www.npmjs.com/package/@pinia/nuxt

手順

install

まずインストールします。つくるディレクトリ直下まで飛んでインストールします。

$ pnpm i @pinia/nuxt

えっと、過去記事でも言ってますがpnpm芸人なので、pnpmでいってますが、

$ npm i @pinia/nuxt

だろうが

$ yarn add @pinia/nuxt

だろうがいけます。さらにいうなら、

$ pnpm add @pinia/nuxt

だろうがいけるのでpnpmさんにフレキシブルさには頭を垂れるほかないだろう

過去記事こちら
https://zenn.dev/mihorin1729/articles/53bee59a26be65

インストール確認

package.json
  "dependencies": {
     "@pinia/nuxt": "^0.4.9",
  }

ちょっとなーまだver.0なのがきになるところなんだよな
ちなみに本家piniaさんはver.2.0.35まできてるようなのでそのうちnuxtバージョンも追随してくれるでしょうということで

言われるがままセットアップ

今回は永続化の実験ですが、いったんこのpinia氏のおちからを拝見しようと思う

nuxt.config.tsにかきこみ

package.json
export default defineNuxtConfig({
...
  modules: ['@pinia/nuxt'],
})

イージーアプリの予定だから他にmoduleなかった

ハイパーイージーカウントアプリを使ってstoreの機能を実験

storeには、まじで足すだけの簡単構造を実装

store/counter.ts
import { ref, computed } from "vue";
import { defineStore } from "pinia";

export const useCounterStore = defineStore(
  "counter",
  () => {
    const count = ref(0);
    function increment() {
      count.value++;
    }
    return { count, increment };
  },
 );

pagesで操作する、と

pages/pinia.vue
<script setup lang="ts">
import { useCounterStore } from "@/store/counter";
import { storeToRefs } from "pinia";
const counterStore = useCounterStore();
const { increment } = counterStore;
const { count } = storeToRefs(counterStore);
</script>

<template>
  <div>
    <h1>Count:{{ count }}</h1>
    <button @click="increment">たすよ</button>
    <br />
    <nuxt-link to="/">もどる</nuxt-link>
  </div>
</template>

ここまでやって、エミュレータ起動

$ pnpm dev


足してくれるようになった!

で、これを他のpageに持っていけるかを実験するのに、

pages/index.vue
<script setup lang="ts">
import { useCounterStore } from "~/store/counter";
const counter = useCounterStore();
</script>

<template>
  <div>
    <nuxt-link to="/editList"> エディターページへ飛ぶ </nuxt-link>
    <nuxt-link to="/contentList"> 再描画ページへとぶ </nuxt-link>
    <nuxt-link to="/pinia"> 永続化実験用カウンターアプリへ飛ぶ </nuxt-link>
    <p>persistedState ぼたんをおしました : {{ counter.count }}</p>
  </div>
</template>

っていう鬼ほど雑な(無CSS)トップページを作って、見てみました。

おいときます(第2弾後日公開)
https://zenn.dev/mihorin1729/articles/225c19603d88dd

そうしましたらば

うおあすごい、ちゃんと保存して飛ばせる!
piniaちゃんえらいぞう

※お気づきだろうか わたしはAtcoder社のChokudaiさんを尊敬しすぎていて、「ぼたんをおしました」にしていることを…

では永続化いってみよう

storeは無事起動したので、つぎはこれを永続化してみようと思う
で、選択肢っぽいものは3種類あります。結論から言うと①しか成功してないので、②と③は感想戦になります

① pinia-plugin-persistedstate

https://prazdevs.github.io/pinia-plugin-persistedstate/frameworks/nuxt-3.html
これです。どうやら公式も推奨しているようです。
https://nuxt.com/modules?type=3rd-party
ここにも登場する。

この画像に関しては…わたしはもう、かわいくてかわいくてTwitterでも3回は取り上げて発言しているのだけど、store永続化のおしごとなのに、この子の記録媒体フロッピーなんだよなーそれって何KB入るの?かわいすぎるだろー

はなしをもどします

まずはインストールします

$ pnpm i -D @pinia-plugin-persistedstate/nuxt

実際なんでもいいってよ
https://prazdevs.github.io/pinia-plugin-persistedstate/frameworks/nuxt-3.html#installation
pnpmを頭に持ってきてるあたりに最新鋭の香りを感じるぜ

nuxt.config.tsにかきこみ

package.json
export default defineNuxtConfig({
...
  modules: [
    '@pinia/nuxt',
+    '@pinia-plugin-persistedstate/nuxt',
  ],
})

storeに追加記述

store/counter.ts
import { ref, computed } from "vue";
import { defineStore } from "pinia";

export const useCounterStore = defineStore(
  "counter",
  () => {
    const count = ref(0);
    function increment() {
      count.value++;
    }
    return { count, increment };
  },
+  {
+  persist: true,
+  }
 );

なんか、{}は公式の説明には入ってないんだけど、わたしの環境はいれろってキレてきたから入ってます。

sessionStorageがいいならこう

store/counter.ts
import { ref, computed } from "vue";
import { defineStore } from "pinia";

export const useCounterStore = defineStore(
  "counter",
  () => {
    const count = ref(0);
    function increment() {
      count.value++;
    }
    return { count, increment };
  },
+ {
+  persist: {
+   storage: persistedState.sessionStorage,
+ },
+  }
 );

これで保存してくれます。

検証します

みえますか?これはlocalStorageに入れているバージョン
保管してくれて、リロードしてもしっかり残してくれます。

② pinia-plugin-persistedState-2

名前似すぎ

こいつ
https://github.com/iendeavor/pinia-plugin-persistedstate-2

こいつ…なんだったんだろう?Nuxt版なかったし、通常版もインストールできずに終わったんだよな

③ Pinia Plugin Persist

名前似すぎ(2回め)

https://seb-l.github.io/pinia-plugin-persist/
こちらです。
Nuxtのページもあるので一応なんとかなりそう。

これやってみて、結論から言うと、
なんかできなかった(笑)

このページに、

plugins/pinia-plugin-persist.client.ts
import { Context } from '@nuxt/types'
import piniaPersist from 'pinia-plugin-persist'

export default ({ app }: Context) => {
  app.pinia?.use(piniaPersist)
}

って書いてある、最終行のpiniaが通らない(TypeError: Cannot read properties of null (reading 'pinia'))
どこに書くといいかわからないし、すでに①で成功してたのでやめてしまいました。

pluginsたてて呼び出して使ってね!ってあって、そのとおりにしたんだけど、謎のエラーをつぶせなかった。
明日には出来るかもしれないけれど、楽さとかを鑑みても①だろうしいいや。

まとめ

piniaと、pinia-plugin-persistedStateのセットで、普通に利用できました。そりゃ公式がすすめてるから大丈夫だろうけど。
はやくpiniaちゃん本体のNuxt版の安定版がほしいねというところかしら。persistなんとか(なげえ)は他に余計なpluginをかかなくていいし、わりと直感的にスッと使えたのでいいのでは。
Vue2のときはactionだっけ?mutationとか、いろいろあった気がするけど今回は大丈夫そうですな。たぶん

以上、報告でしたー。

かわいいなあ

Discussion