如何在 Next.js 中使用預覽模式 (Preview Mode) 預覽內容
注意:此功能已被 草稿模式 (Draft Mode) 取代。
範例
- Agility CMS 範例 (演示)
- Builder.io 範例 (演示)
- ButterCMS 範例 (演示)
- Contentful 範例 (演示)
- Cosmic 範例 (演示)
- DatoCMS 範例 (演示)
- DotCMS 範例 (演示)
- Drupal 範例 (演示)
- Enterspeed 範例 (演示)
- GraphCMS 範例 (演示)
- Keystone 範例 (演示)
- Kontent.ai 範例 (演示)
- Makeswift 範例 (演示)
- Plasmic 範例 (演示)
- Prepr 範例 (演示)
- Prismic 範例 (演示)
- Sanity 範例 (演示)
- Sitecore XM Cloud 範例 (演示)
- Storyblok 範例 (演示)
- Strapi 範例 (演示)
- TakeShape 範例 (演示)
- Tina 範例 (演示)
- Umbraco 範例 (演示)
- Umbraco Heartcore 範例 (演示)
- Webiny 範例 (演示)
- WordPress 範例 (演示)
- 部落格起始範例 (演示)
在 頁面文件 和 資料獲取文件 中,我們討論了如何使用 getStaticProps
和 getStaticPaths
在建置時預渲染頁面(靜態生成 (Static Generation))。
當您的頁面從無頭 CMS (headless CMS) 獲取資料時,靜態生成非常有用。但是,當您在無頭 CMS 上撰寫草稿並希望立即在頁面上預覽草稿時,這並不理想。您會希望 Next.js 在請求時而非建置時渲染這些頁面,並獲取草稿內容而非已發布的內容。您會希望 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。
首先,您應該使用您選擇的令牌生成器建立一個秘密令牌字串。此秘密僅由您的 Next.js 應用程式和無頭 CMS 知道。此秘密可以防止沒有存取您 CMS 權限的人存取預覽 URL。
其次,如果您的無頭 CMS 支援設定自訂預覽 URL,請將以下內容指定為預覽 URL。這假設您的預覽 API 路由位於 pages/api/preview.js
。
<your-site>
應該是您的部署網域。<token>
應替換為您生成的秘密令牌。<path>
應為您要預覽的頁面路徑。如果您想預覽/posts/foo
,則應使用&slug=/posts/foo
。
您的無頭 CMS 可能允許您在預覽 URL 中包含變數,以便根據 CMS 的資料動態設定 <path>
,例如:&slug=/posts/{entry.fields.slug}
最後,在預覽 API 路由中:
- 檢查秘密是否匹配以及
slug
參數是否存在(如果沒有,請求應失敗)。 - 呼叫
res.setPreviewData
。 - 然後將瀏覽器重新導向到由
slug
指定的路徑。(以下範例使用 307 重新導向)。
如果成功,瀏覽器將被重新導向到您要預覽的路徑,並設定預覽模式 cookies。
步驟 2:更新 getStaticProps
下一步是更新 getStaticProps
以支援預覽模式。
如果您請求一個具有 getStaticProps
的頁面,並且設定了預覽模式 cookies(透過 res.setPreviewData
),則 getStaticProps
將在請求時(而非建置時)被呼叫。
此外,它將被呼叫並帶有一個 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 和本地儲存存取。