/

如何在 Next.js 中在構建時在所有頁面上全局緩存數據

如何在 Next.js 中在構建時在所有頁面上全局緩存數據

在我使用 Next.js 架構的網站中,需要在構建時從 API 中獲取數據。

我嘗試了多種解決方案,但都沒有成功。經過大量的研究和試誤,我找到了解決方案。

這個解決方案同樣適用於本地開發(localhost)和 Vercel(生產環境)。

以下是情景描述:我有一個存儲“成員”電子郵件的位置,可以是遠程數據庫、Airtable 或其他任何地方。

我只想下載這些數據一次,然後在網站上一直保持可用,直到我觸發下一次構建。

這個成員列表非常靜態,最多一天可能會變化一次。如果這個列表發生變化,我只需要使用 Vercel 的 Deploy Hooks 以編程方式觸發重新部署。

以下是操作計劃。我們將在 .members 文件中創建數據的本地緩存。

lib/members.js 文件中的一個函數將負責在第一次調用時從緩存中將數據提取並存儲為 JSON,以後每次調用時從緩存中讀取數據:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import fs from 'fs'
import path from 'path'

function fetchMembersData() {
console.log('正在獲取成員數據...')
return [{ email: '[[email protected]](/cdn-cgi/l/email-protection)' }, { email: '[[email protected]](/cdn-cgi/l/email-protection)' }]
}

const MEMBERS\_CACHE\_PATH = path.resolve('.members')

export default async function getMembers() {
let cachedData

try {
cachedData = JSON.parse(
fs.readFileSync(path.join(\_\_dirname, MEMBERS\_CACHE\_PATH), 'utf8')
)
} catch (error) {
console.log('未初始化成員緩存')
}

if (!cachedData) {
const data = fetchMembersData()

try {
fs.writeFileSync(
path.join(\_\_dirname, MEMBERS\_CACHE\_PATH),
JSON.stringify(data),
'utf8'
)
console.log('已寫入成員緩存')
} catch (error) {
console.log('將成員緩存寫入文件時出錯')
console.log(error)
}

cachedData = data
}

return cachedData
}

現在在任何頁面中,我們可以添加以下代碼:

1
import getMembers from 'lib/members'

並在 getStaticProps() 函數中使用:

1
const members = await getMembers()

現在我們可以根據這些數據進行操作。

一個快速的例子是將 members 添加到 getStaticProps 函數返回的 props 對象中,然後在頁面中使用這些 props 進行迭代:

1
2
3
4
5
6
7
{members?.map((member) => {
return (
<p key={member.email} className='mt-3'>
{member.email}
</p>
)
})}

tags: [“Next.js”, “caching”, “data fetching”, “build time”]