nuxt3_使用pinia實現伺服器端渲染狀態管理

Syinho發表於2024-04-16

目錄
  • 安裝nuxt3的pinia包
  • 修改nuxt.config.ts的配置
  • 在專案中建立pinia倉庫
  • 建立本地的測試伺服器用於測試ssr
  • 在nuxt專案中建立伺服器端請求介面
  • /article/[id]路由頁面中實現伺服器端渲染
  • 使用postman向http://localhost:3000/article/95傳送請求
  • 修改路由配置實現頁面資料快取

安裝nuxt3的pinia包

pnpm i pinia @pinia/nuxt
yarn add pinia @pinia/nuxt
npm i pinia @pinia/nuxt

修改nuxt.config.ts的配置

// nuxt.config.ts
export default defineNuxtConfig({
  // ... 其他配置
  modules: [
    // ...
    '@pinia/nuxt',
  ],
})

在專案中建立pinia倉庫

// /stores/index.js
import { defineStore } from 'pinia'
export const useRootStore = defineStore('root', {
  state: () => ({
    msg: '測試msg資料',
    articleData: {
      id: undefined,
      title: undefined,
      content: undefined,
    },
  }),
  getters: {},
})

建立本地的測試伺服器用於測試ssr

import express from 'express'
import cors from 'cors'
const article = {
  title: 'hello world',
  content:
    'Eu pariatur aliquip enim enim officia laboris proident adipisicing duis aute ex labore nisi excepteur.',
}
const app = express()

app.use(cors())
app.use(express.json())

app.get('/article', cors(), (req, res) => {
  const { id } = req.query
  console.log('訪問/article ' + new Date().toString())
  setTimeout(() => {
    res.send({ code: 200, data: { id:Number(id), ...article } })
  }, 1500)
})

app.listen(4520, err => {
  console.log('server is running at port 4520')
})

在nuxt專案中建立伺服器端請求介面

// /server/article.get.js
export default defineEventHandler(async event => {
  // console.log(event)
  const { id } = getQuery(event)
  return new Promise(async (resolve, reject) => {
    const res = await $fetch(`http://127.0.0.1:4520/article?id=${id}`).catch(err => err)
    if (res.code === 200) {
      resolve(res)
    } else {
      reject(res)
    }
  })
})

/article/[id]路由頁面中實現伺服器端渲染

// /pages/article/[id].vue
<template>
  <div id="articleContainer">
    <p>{{ $rootStore?.msg }}</p>
    <p>id:{{ $rootStore?.articleData?.id }}</p>
    <p>標題:{{ $rootStore?.articleData?.title }}</p>
    <p>內容:{{ $rootStore?.articleData?.content }}</p>
  </div>
</template>

<script setup>
import { useRootStore } from '~/stores/index'
const articleStore = useArticleStore()
const $route = useRoute()
const $rootStore = useRootStore()

//#region 初始化資料
initData()
async function initData() {
  const res = await useFetch(`/api/article?id=${$route.params.id}`)
  const res_ = res.data.value
  if (res_.code === 200) {
    $rootStore.$patch({
      articleData: { ...res_.data },
    })
  }
}
//#endregion
</script>

<style scoped lang="scss"></style>

使用postman向http://localhost:3000/article/95傳送請求

  • 註釋: localhost:3000是nuxt3專案的預設啟動地址
  • 得到如下的html結構, 代表服務端渲染成功
<p data-v-inspector="pages/article/[id].vue:3:5">測試msg資料</p>
<p data-v-inspector="pages/article/[id].vue:4:5">id:95</p>
<p data-v-inspector="pages/article/[id].vue:5:5">標題:hello world</p>
<p data-v-inspector="pages/article/[id].vue:6:5">內容:Eu pariatur aliquip enim enim officia laboris proident adipisicing duis aute ex labore nisi excepteur.</p>

修改路由配置實現頁面資料快取

// nuxt.config.ts
  routeRules: {
    '/article/**': { ssr:true },
  },
  • 當路由設定為上面所示時, 每次向/article/[id]路由發起請求都會重新向伺服器呼叫介面,
// 每次重新整理頁面伺服器介面都會列印請求
訪問/article Tue Apr 16 2024 13:21:37 GMT+0800 (中國標準時間)
訪問/article Tue Apr 16 2024 13:23:28 GMT+0800 (中國標準時間)
訪問/article Tue Apr 16 2024 13:23:30 GMT+0800 (中國標準時間)
  • 修改路由配置為
'/article/**': { swr: 60 }, // 頁面資料快取60s, 在快取資料有效期間不向伺服器發起新的請求
  • 修改後, 在60s內無論重新整理多少次頁面, 伺服器介面只會列印一條請求
訪問/article Tue Apr 16 2024 13:28:53 GMT+0800 (中國標準時間)

相關文章