NuxtJSのSSRモードで、vuex-persistedstateによるデータ永続化を適用してしまいSSRのfetchライフサイクルでstoreに設定したデータが上書きされてしまった。これは、私がvuex-persistedstateの使用方法を誤っただけである。SSRモードで動かす場合は、クライアントサイドで永続化したいpathにのみ適用すべし(自分への戒め)。
stateが上書きされてしまったケース
具体的には以下のような使い方をしてしまっていた。
- vuex-persistedstateをpluginとしてロード
- クライアントサイドでstoreにデータ書き込み(この段階でlocalStorageにデータが書かれている)
- SSRでサーバサイドでfetch処理でstateにデータを書き込む
期待する動きは、3で初回ページアクセスしてサーバサイドでcommitしたstateがクライアントサイドで復元される、である。
しかし、3番目のステップでSSRで設定したstateデータがクライアントサイドで復元されると期待するものの、vuex-persistedstateプラグインの永続化処理により、以前にlocalStorageに書き込んだ値で上書きされてしまう、という訳である
1 2 3 4 5 |
// nuxt.config.js plugins: [ { src: '~/plugins/persistedState.js', mode: 'client' }, ] |
1 2 3 4 5 6 7 8 9 10 11 |
// pages/index.vue fetch({ store }) { store.commit('setCounter', 100) // counter=100 }, methods: { doSomething() { this.$store.commit('setCounter', 9999) // localStorage => counter=9999 } } |
1 2 3 4 5 6 7 8 9 10 11 |
// store/index.js export const state = () => ({ counter: 0, }) export const mutations = { setCounter(state, value) { state.counter = value }, } |
1 2 3 4 5 |
import createPersistedState from 'vuex-persistedstate' export default ({ store }) => { createPersistedState({ key: 'share' })(store) // => counter=9999 not but 100 } |
プラグインロードのタイミング
NuxtJSでは以下のようにpluginとして組み込める。クライアント再度でpluginがロードされるタイミングは、ライフサイクルでは以下となる。
- Receives the HTML
- Loading assets (e.g. JavaScript)
- client-side Nuxt plugin ★ここ
- in order as defined in nuxt.config.js
- Vue Hydration
- Middleware
- Global middleware
- Layout middleware
- Route middleware
- asyncData (blocking)
- beforeCreate (Vue lifecycle method)
- created (Vue lifecycle method)
- The new fetch (top to bottom, siblings = parallel) (non-blocking)
- beforeMount (Vue lifecycle method)
- mounted (Vue lifecycle method)
引用:https://nuxtjs.org/docs/concepts/nuxt-lifecycle/
Stateのrestoreのタイミング
サーバーサイドでcommit
されたstate
の情報は、ページアクセスのレスポンスデータの中でシリアライズされて送信される。そして、アプリケーション初期化のタイミングでstate
に復元される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// .nuxt/index.js if (process.client) { // Replace store state before plugins execution if (window.__NUXT__ && window.__NUXT__.state) { store.replaceState(window.__NUXT__.state) } } // Add enablePreview(previewData = {}) in context for plugins if (process.static && process.client) { app.context.enablePreview = function (previewData = {}) { app.previewData = Object.assign({}, previewData) inject('preview', previewData) } } // Plugin execution if (typeof nuxt_plugin_plugin_b9ce5b40 === 'function') { await nuxt_plugin_plugin_b9ce5b40(app.context, inject) } ... |
store.replaceState
の復元段階では、まだプラグインの初期化はされていない。プラグインの初期化が呼ばれるのは、コメント // Plugin execution
の以降になるので、上記で復元されたstate
は上書きされてしまう。
参考リンク
- https://nuxtjs.org/docs/concepts/nuxt-lifecycle/
- https://github.com/robinvdvleuten/vuex-persistedstate
コメント