預覽模式 (Preview Mode)
注意:此功能已被 草稿模式 (Draft Mode) 取代。
範例
- WordPress 範例 (演示)
- DatoCMS 範例 (演示)
- TakeShape 範例 (演示)
- Sanity 範例 (演示)
- Prismic 範例 (演示)
- Contentful 範例 (演示)
- Strapi 範例 (演示)
- Prepr 範例 (演示)
- Agility CMS 範例 (演示)
- Cosmic 範例 (演示)
- ButterCMS 範例 (演示)
- Storyblok 範例 (演示)
- GraphCMS 範例 (演示)
- Kontent 範例 (演示)
- Umbraco Heartcore 範例 (演示)
- Plasmic 範例 (演示)
- Enterspeed 範例 (演示)
- Makeswift 範例 (演示)
在 頁面文件 和 資料獲取文件 中,我們討論了如何使用 getStaticProps
和 getStaticPaths
在建置時預渲染頁面(靜態生成 (Static Generation))。
當您的頁面從無頭 CMS (headless CMS) 獲取資料時,靜態生成非常有用。但是,當您在無頭 CMS 上撰寫草稿並希望立即在頁面上預覽 (preview) 草稿時,這就不太理想了。您會希望 Next.js 在請求時 (request time) 而非建置時渲染這些頁面,並獲取草稿內容而非已發布的內容。您會希望 Next.js 僅針對這種特定情況繞過靜態生成。
Next.js 有一個稱為預覽模式 (Preview Mode) 的功能可以解決這個問題。以下是使用說明。
步驟 1:建立並存取預覽 API 路由
如果您不熟悉 Next.js API 路由,請先查看 API 路由文件。
首先,建立一個預覽 API 路由。它可以有任何名稱,例如 pages/api/preview.js
(如果使用 TypeScript 則為 .ts
)。
在這個 API 路由中,您需要在回應物件上呼叫 setPreviewData
。setPreviewData
的參數應該是一個物件,這可以被 getStaticProps
使用(稍後會詳細說明)。現在,我們將使用 {}
。
res.setPreviewData
會在瀏覽器上設定一些 cookies,從而啟用預覽模式。任何包含這些 cookies 的 Next.js 請求都會被視為預覽模式,靜態生成頁面的行為也會改變(稍後會詳細說明)。
您可以通過建立如下 API 路由並從瀏覽器手動存取來測試:
如果您打開瀏覽器的開發者工具並訪問 /api/preview
,您會注意到 __prerender_bypass
和 __next_preview_data
cookies 會在此請求中被設定。
從無頭 CMS 安全存取
實際上,您會希望從無頭 CMS 安全地 呼叫此 API 路由。具體步驟會因您使用的無頭 CMS 而異,但以下是一些常見的步驟。
這些步驟假設您使用的無頭 CMS 支援設定 自訂預覽 URL。如果不支援,您仍然可以使用此方法來保護預覽 URL,但需要手動建構和存取預覽 URL。
首先,您應該使用您選擇的 token 生成器建立一個 秘密 token 字串。此秘密僅由您的 Next.js 應用程式和無頭 CMS 知道。此秘密防止沒有存取 CMS 權限的人存取預覽 URL。
其次,如果您的無頭 CMS 支援設定自訂預覽 URL,請將以下內容指定為預覽 URL。這假設您的預覽 API 路由位於 pages/api/preview.js
。
<your-site>
應該是您的部署網域。<token>
應該替換為您生成的秘密 token。<path>
應該是您想要預覽的頁面路徑。如果您想預覽/posts/foo
,則應該使用&slug=/posts/foo
。
您的無頭 CMS 可能允許您在預覽 URL 中包含變數,以便 <path>
可以根據 CMS 的資料動態設定,例如:&slug=/posts/{entry.fields.slug}
最後,在預覽 API 路由中:
- 檢查 secret 是否匹配以及
slug
參數是否存在(如果沒有,請求應該失敗)。 - 呼叫
res.setPreviewData
。 - 然後將瀏覽器重新導向到
slug
指定的路徑。(以下範例使用 307 重新導向)。
如果成功,瀏覽器將被重新導向到您想要預覽的路徑,並設定預覽模式的 cookies。
步驟 2:更新 getStaticProps
下一步是更新 getStaticProps
以支援預覽模式。
如果您請求一個具有 getStaticProps
的頁面,並且設定了預覽模式的 cookies(通過 res.setPreviewData
),則 getStaticProps
將在請求時 (request time)(而非建置時)被呼叫。
此外,它將被呼叫時帶有一個 context
物件,其中:
context.preview
將為true
。context.previewData
將與setPreviewData
使用的參數相同。
我們在預覽 API 路由中使用了 res.setPreviewData({})
,因此 context.previewData
將為 {}
。您可以使用它來從預覽 API 路由傳遞會話資訊到 getStaticProps
(如果需要)。
如果您還使用 getStaticPaths
,則 context.params
也將可用。
獲取預覽資料
您可以根據 context.preview
和/或 context.previewData
更新 getStaticProps
以獲取不同的資料。
例如,您的無頭 CMS 可能有不同的 API 端點用於草稿文章。如果是這樣,您可以使用 context.preview
來修改 API 端點 URL,如下所示:
就是這樣!如果您從無頭 CMS 或手動存取預覽 API 路由(帶有 secret
和 slug
),您現在應該能夠看到預覽內容。如果您更新草稿而不發布,您應該能夠預覽草稿。
將其設定為無頭 CMS 上的預覽 URL 或手動存取,您應該能夠看到預覽。
更多細節
須知:在渲染期間,
next/router
會公開一個isPreview
標誌,請參閱 router 物件文件 以獲取更多資訊。
指定預覽模式的持續時間
setPreviewData
接受一個可選的第二個參數,該參數應該是一個選項物件。它接受以下鍵:
maxAge
:指定預覽會話持續的秒數。path
:指定 cookie 應應用於的路徑。預設為/
,為所有路徑啟用預覽模式。
清除預覽模式 cookies
預設情況下,預覽模式 cookies 沒有設定過期日期,因此預覽會話會在瀏覽器關閉時結束。
要手動清除預覽模式 cookies,請建立一個呼叫 clearPreviewData()
的 API 路由:
然後,發送請求到 /api/clear-preview-mode-cookies
以呼叫 API 路由。如果使用 next/link
呼叫此路由,則必須傳遞 prefetch={false}
以防止在連結預取期間呼叫 clearPreviewData
。
如果在 setPreviewData
呼叫中指定了路徑,則必須將相同的路徑傳遞給 clearPreviewData
:
previewData
大小限制
您可以將物件傳遞給 setPreviewData
並使其在 getStaticProps
中可用。但是,由於資料將儲存在 cookie 中,因此有大小限制。目前,預覽資料限制為 2KB。
與 getServerSideProps
一起使用
預覽模式也適用於 getServerSideProps
。它也會在包含 preview
和 previewData
的 context
物件上可用。
須知:使用預覽模式時不應設定
Cache-Control
標頭,因為它無法被繞過。相反,我們建議使用 ISR (增量靜態再生)。
與 API 路由一起使用
API 路由將可以透過請求物件存取 preview
和 previewData
。例如:
每個 next build
唯一
當 next build
完成時,繞過 cookie 值和用於加密 previewData
的私鑰都會改變。這確保了繞過 cookie 無法被猜測。
須知:要在 HTTP 上本地測試預覽模式,您的瀏覽器需要允許第三方 cookies 和本地儲存存取。