typescript - 如何清除 NextJs GetStaticPaths 的快取/「取消發布」一個動態路由?
我覺得這問題相當普通,但我在 Google 上找不到任何資料。
我正在學習 NextJs(使用 TypeScript),我已經成功建立了一個網站,支援動態路由、伺服器端渲染(SSR)和增量再生(Incremental Regeneration),並已部署到 Vercel。這裡是一個我在動態路由處理器中使用的 GetStaticProps 和 GetStaticPaths 範例代碼:
export const getStaticPaths: GetStaticPaths = async () => {
const routes = new CmsHelper().GetRoutes();
const paths = (await routes).items.map((item, index, items) => {
return item.fields.urlPath;
})
return {
paths: paths,
fallback: 'blocking',
};
}
export const getStaticProps: GetStaticProps = async (context) => {
const urlParts = context.params?.url as string[] || [];
const urlPath = `/${urlParts.join('/')}`;
const article = await new CmsHelper().GetArticle(urlPath);
return {
props: {
article
},
revalidate: 10,
}
}
如果我請求一個在建置時間之後於 CMS 發佈的新路徑,它會在伺服器上成功重新生成並返回該頁面。
到目前為止一切順利。
然而,如果我在我的 CMS 中 取消發布 一個路由……它仍然會被應用返回,除非我重新構建和重新部署(或者在開發中以其他方式使進程重啟)。
所以我的問題是:我該如何動態地讓 NextJs 從它的 GetStaticPaths 快取中移除一個動態路由?
我理解因為 revalidate 設定,GetStaticProps 最多每 10 秒會被呼叫一次。但據我所知,GetStaticPaths 只有在來自目前尚未快取的路由的請求時才會被呼叫(?)
換句話說,對於與無頭 CMS 的整合,我如何在不觸發重建/部署的情況下,使用 NextJs 支援 取消發布或重新命名 頁面?
提前感謝你!
答案#1
也許可以嘗試這裡描述的方法。
這裡也提供程式碼以供參考。
// pages/blog/[slug].js
import {useRouter} from 'next/router'
import DefaultErrorPage from 'next/error'
export async function getStaticProps({ params }) {
// fetch data from CMS through params
const post = await getBlogItem(params.slug)
return {
props: {
post
}
}
}
export async function getStaticPaths() {
return {
fallback: true,
paths: []
}
}
export default function MyPage({post}) {
const router = useRouter()
if(router.isFallback) {
return <h1>Loading...</h1>
}
// This includes setting the noindex header because static files always return a status 200 but the rendered not found page page should obviously not be indexed
if(!post) {
return <>
<Head>
<meta name="robots" content="noindex">
</Head>
<DefaultErrorPage statusCode={404} />
</>
}
return <h1>{post.title}</h1>
}
所以,與其刪除/清除快取,不如嘗試成功處理你正在取得的內容是“未發佈”的情況,如果是這樣,你可以顯示一個 404 Not found 頁面或其他你選擇的內容。
像這樣的東西:
export async function getStaticProps(context) {
const {params: {id}} = context
let data;
try {
data = await httpClient...
} catch (err) {
if (not err is caused due to content being unpublished){
// re throw it
throw err;
}
// Else handle it gracefully
data = null;
}
return {
props: {
data,
},
revalidate: 1
};
}
然後在你的視圖上:
export default function Data(props) {
const {data} = props;
const router = useRouter()
// If the page is not yet generated, this will be displayed
// initially until getStaticProps() finishes running
if (router.isFallback) {
return <div>Loading...</div>
}
if (!data) {
return (
<>
<Head>
<meta name="robots" content="noindex"/>
</Head>
<DefaultErrorPage statusCode={404}/>
</>
)
}
return <DataView {...data} />;
}
答案#2
我面臨了一個類似但不同的問題:部署我的項目從數據生成的 URL,但當資料庫中的數據變更時,我無法添加任何新的 URL。
我問題的關鍵在於我在 getStaticPaths 方法中將 fallback 設為 false。當我將其設為 true 時,生產部署開始像我的本地開發構建一樣運行。
我看到你正在為你的 fallback 屬性傳遞一個字串值。你可以嘗試使用這裡描述的布林值:https://nextjs.org/docs/basic-features/data-fetching#the-fallback-key-required
