owned this note
owned this note
Published
Linked with GitHub
# Nuxt3 Pinia Plugin Persistedstate
[Pinia Plugin Persistedstate](https://prazdevs.github.io/pinia-plugin-persistedstate/) 讓你可以將 Pinia 的狀態持久化儲存在瀏覽器的 Cookie、SessionStorage 或 LocalStorage 中。
---
## 安裝
```bash
npm install pinia @pinia/nuxt pinia-plugin-persistedstate
```
---
## Nuxt 配置
在 `nuxt.config.js` 中加入以下設置:
```javascript
export default {
modules: [
'@pinia/nuxt',
'pinia-plugin-persistedstate'
],
imports: {
// 設定要 auto imports 的資料夾
dirs: ['stores']
}
}
```
### 常見問題處理
**錯誤:** 在 Nuxt 3.7.0+ 版本可能出現 `[vite-node] [ERR_LOAD_URL]` 錯誤
:::spoiler 示意圖

:::
**解決方式:** 在 `nuxt.config.js` 加入 transpile 配置
```javascript
export default {
// ...其他配置
build: {
transpile: ['pinia-plugin-persistedstate']
}
}
```
**參考資料:** [GitHub Issue #236](https://github.com/prazdevs/pinia-plugin-persistedstate/issues/236)
---
## Store 定義
在 `/stores/` 目錄下建立 store 檔案:
```javascript
import { defineStore } from 'pinia'
// 方法一: Options API 語法
export const useCounterStore = defineStore('counter', {
state: () => ({
message: 'Hello World!!'
}),
getters: {
// getters 定義
},
actions: {
setNewText(newText) {
this.message = newText
}
},
persist: {
storage: persistedState.sessionStorage
}
})
// 方法二: Composition API 語法 (推薦)
export const useCounterStore = defineStore(
'counter',
() => {
// State
const count = ref(0)
const message = ref('pinia')
const objUser = ref({
id: 1,
name: 'Pinia'
})
// Actions
const addCount = () => {
count.value++
}
const setNewText = (newText) => {
message.value = newText
}
return {
count,
message,
objUser,
addCount,
setNewText
}
},
{
// Persist 配置
persist: {
key: 'counter-store', // 自訂儲存 key
storage: process.client ? persistedState.sessionStorage : null,
paths: ['count', 'message'] // 只儲存指定的狀態
}
}
)
```
---
## Persist 配置選項
### 1. 基本啟用
```javascript
persist: true
```
**預設行為:**
- 儲存位置: Cookie
- 儲存 Key: Store 的 ID (defineStore 第一個參數)
- 儲存範圍: 整個 state
---
### 2. 自訂 Key
```javascript
persist: {
key: 'my-custom-key'
}
```
覆寫預設的儲存 key 名稱。
---
### 3. Storage 選項
```javascript
persist: {
storage: persistedState.sessionStorage
}
```
**可用選項:**
- `persistedState.cookies` (預設)
- `persistedState.localStorage`
- `persistedState.sessionStorage`
**重要提醒:** 為避免 SSR Hydration 錯誤,建議使用:
:::spoiler error message
Hydration completed but contains mismatches.

:::
```javascript
storage: process.client ? persistedState.sessionStorage : null
```
---
### 4. Cookie 進階配置
```javascript
persist: {
storage: persistedState.cookiesWithOptions({
sameSite: 'strict',
maxAge: 60 * 60 * 24 * 7, // 7 天
secure: true,
path: '/'
})
}
```
選項參考 [Nuxt useCookie 文檔](https://nuxt.com/docs/api/composables/use-cookie#options)
---
### 5. 部分狀態儲存
```javascript
persist: {
paths: ['count', 'message']
}
```
只儲存指定的狀態屬性,其他屬性不會被持久化。
---
### 6. Debug 模式
```javascript
persist: {
debug: true
}
```
啟用後會在 Console 輸出錯誤訊息,方便除錯。
---
## 在組件中使用
```htmlembedded
<template>
<div>
<ClientOnly>
<div>
<p>{{ counter.message }}</p>
<button @click="counter.setNewText('New text!')">
更新文字
</button>
</div>
<div>
<p>計數: {{ counter.count }}</p>
<button @click="counter.addCount">
增加計數
</button>
</div>
</ClientOnly>
</div>
</template>
<script setup>
const counter = useCounterStore()
</script>
```
### Hydration 錯誤處理
如果遇到 `Hydration completed but contains mismatches` 錯誤:
**方法一:** 使用 `<ClientOnly>` 組件包裹使用 store 的部分
**方法二:** 修改 storage 配置 (推薦)
```javascript
storage: process.client ? persistedState.sessionStorage : null
```
---
## 參考資料
- [Pinia Plugin Persistedstate 官方文檔](https://prazdevs.github.io/pinia-plugin-persistedstate/)
- [GitHub Issue #218 - Customize persist option](https://github.com/prazdevs/pinia-plugin-persistedstate/issues/218)
- [Nuxt 3 ClientOnly 使用教學](https://ithelp.ithome.com.tw/articles/10327918)
- [IT邦幫忙 - Pinia Plugin Persistedstate 教學](https://ithelp.ithome.com.tw/articles/10332698)
---
## 完整配置範例
```javascript
export const useUserStore = defineStore(
'user',
() => {
const userInfo = ref(null)
const token = ref('')
const preferences = ref({})
const login = (info) => {
userInfo.value = info
}
const logout = () => {
userInfo.value = null
token.value = ''
}
return {
userInfo,
token,
preferences,
login,
logout
}
},
{
persist: {
key: 'user-session',
storage: process.client ? persistedState.localStorage : null,
paths: ['userInfo', 'token'], // 不儲存 preferences
debug: import.meta.env.DEV
}
}
)
```
---
> **提示:** 敏感資訊 (如 token) 建議加密後再儲存,或考慮使用 httpOnly Cookie。