perf: optimize public content caching
This commit is contained in:
@@ -3,6 +3,7 @@ import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { AboutContactTabs } from '@/components/site/about-contact-tabs'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates, extractRichTextPlainText, trimDescription } from '@/lib/seo'
|
||||
import { normalizeUploadUrl } from '@/lib/upload-url'
|
||||
@@ -15,13 +16,17 @@ function getAboutPageTitle(rawTitle: string | null | undefined) {
|
||||
return normalized
|
||||
}
|
||||
|
||||
async function getAboutPageData(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
return payload.findGlobal({
|
||||
slug: 'aboutPage',
|
||||
locale,
|
||||
})
|
||||
}
|
||||
const getAboutPageData = cacheCmsQuery(
|
||||
['about-page-global'],
|
||||
async (locale: Locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
return payload.findGlobal({
|
||||
slug: 'aboutPage',
|
||||
locale,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { AboutContactTabs } from '@/components/site/about-contact-tabs'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates } from '@/lib/seo'
|
||||
import { normalizeUploadUrl } from '@/lib/upload-url'
|
||||
@@ -158,15 +159,18 @@ function normalizeContactGroups(groups: unknown, locale: Locale) {
|
||||
return normalized.length > 0 ? normalized : getDefaultContactGroups(locale)
|
||||
}
|
||||
|
||||
async function getContactUsPageData(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const getContactUsPageData = cacheCmsQuery(
|
||||
['contact-us-page-global'],
|
||||
async (locale: Locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
return payload.findGlobal({
|
||||
depth: 1,
|
||||
locale,
|
||||
slug: 'contactUsPage',
|
||||
})
|
||||
}
|
||||
return payload.findGlobal({
|
||||
depth: 1,
|
||||
locale,
|
||||
slug: 'contactUsPage',
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { SiteIcon } from '@/components/site/site-icons'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildLocaleAlternates, extractRichTextPlainText, trimDescription } from '@/lib/seo'
|
||||
import { renderRichText } from '@/lib/render-rich-text'
|
||||
@@ -122,7 +123,7 @@ function hasRichTextContent(value: Download['notes'] | Download['changelog'] | n
|
||||
return Boolean(extractRichTextPlainText(value))
|
||||
}
|
||||
|
||||
async function getDownloadProductData(slug: string, locale: Locale) {
|
||||
async function getDownloadProductDataUncached(slug: string, locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const products = await payload.find({
|
||||
collection: 'products',
|
||||
@@ -231,6 +232,11 @@ async function getDownloadProductData(slug: string, locale: Locale) {
|
||||
}
|
||||
}
|
||||
|
||||
const getDownloadProductData = cacheCmsQuery<
|
||||
[string, Locale],
|
||||
Awaited<ReturnType<typeof getDownloadProductDataUncached>>
|
||||
>(['download-product-data'], getDownloadProductDataUncached)
|
||||
|
||||
function getRelatedProducts(download: Download) {
|
||||
const multi = Array.isArray((download as Download & { products?: DownloadProductReference[] }).products)
|
||||
? ((download as Download & { products?: DownloadProductReference[] }).products as DownloadProductReference[])
|
||||
|
||||
@@ -4,6 +4,7 @@ import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { SiteIcon } from '@/components/site/site-icons'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { isTemplateProduct } from '@/lib/product-template-navigation'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates, extractRichTextPlainText } from '@/lib/seo'
|
||||
@@ -224,7 +225,7 @@ async function getSeedDownloadGroups(locale: Locale): Promise<DownloadGroup[]> {
|
||||
.sort((left, right) => left.productLabel.localeCompare(right.productLabel))
|
||||
}
|
||||
|
||||
async function getDownloadsPageData(locale: Locale) {
|
||||
async function getDownloadsPageDataUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const downloadsResult = await payload.find({
|
||||
collection: 'downloads',
|
||||
@@ -337,15 +338,23 @@ async function getDownloadsPageData(locale: Locale) {
|
||||
return getSeedDownloadGroups(locale)
|
||||
}
|
||||
|
||||
async function getDownloadsPageSettings(locale: Locale): Promise<DownloadsPageSettings> {
|
||||
const payload = await getPayloadClient()
|
||||
const getDownloadsPageData = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getDownloadsPageDataUncached>>>(
|
||||
['downloads-page-data'],
|
||||
getDownloadsPageDataUncached,
|
||||
)
|
||||
|
||||
return (await payload.findGlobal({
|
||||
depth: 1,
|
||||
locale,
|
||||
slug: 'downloadsPage',
|
||||
})) as DownloadsPageSettings
|
||||
}
|
||||
const getDownloadsPageSettings = cacheCmsQuery<[Locale], DownloadsPageSettings>(
|
||||
['downloads-page-global'],
|
||||
async (locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
return (await payload.findGlobal({
|
||||
depth: 1,
|
||||
locale,
|
||||
slug: 'downloadsPage',
|
||||
})) as DownloadsPageSettings
|
||||
},
|
||||
)
|
||||
|
||||
function getRelatedProducts(download: Download) {
|
||||
const multi = Array.isArray((download as Download & { products?: DownloadProductReference[] }).products)
|
||||
|
||||
@@ -3,6 +3,7 @@ import Link from 'next/link'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { renderRichText } from '@/lib/render-rich-text'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates, extractRichTextPlainText, trimDescription } from '@/lib/seo'
|
||||
@@ -21,31 +22,34 @@ function formatPublishedAt(value: string | null | undefined, locale: Locale) {
|
||||
}).format(new Date(value))
|
||||
}
|
||||
|
||||
async function getNewsArticle(locale: Locale, slug: string) {
|
||||
const payload = await getPayloadClient()
|
||||
const result = await payload.find({
|
||||
collection: 'news',
|
||||
depth: 1,
|
||||
limit: 1,
|
||||
locale,
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
docLocale: {
|
||||
equals: locale,
|
||||
const getNewsArticle = cacheCmsQuery(
|
||||
['news-article'],
|
||||
async (locale: Locale, slug: string) => {
|
||||
const payload = await getPayloadClient()
|
||||
const result = await payload.find({
|
||||
collection: 'news',
|
||||
depth: 1,
|
||||
limit: 1,
|
||||
locale,
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
docLocale: {
|
||||
equals: locale,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: {
|
||||
equals: slug,
|
||||
{
|
||||
slug: {
|
||||
equals: slug,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
return result.docs[0] ?? null
|
||||
}
|
||||
return result.docs[0] ?? null
|
||||
},
|
||||
)
|
||||
|
||||
function getRelatedProduct(product: number | Product) {
|
||||
return typeof product === 'object' ? product : null
|
||||
|
||||
@@ -3,6 +3,7 @@ import Link from 'next/link'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { getBlogPosts } from '@/lib/blog-api'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates } from '@/lib/seo'
|
||||
import { normalizeUploadUrl } from '@/lib/upload-url'
|
||||
@@ -31,35 +32,41 @@ type NewsListItem = {
|
||||
title: string
|
||||
}
|
||||
|
||||
async function getNewsPageSettings() {
|
||||
const payload = await getPayloadClient()
|
||||
const getNewsPageSettings = cacheCmsQuery(
|
||||
['news-page-global'],
|
||||
async () => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
try {
|
||||
return await payload.findGlobal({
|
||||
slug: 'newsPage',
|
||||
})
|
||||
} catch {
|
||||
return { newsSource: 'externalBlog' as const }
|
||||
}
|
||||
}
|
||||
try {
|
||||
return await payload.findGlobal({
|
||||
slug: 'newsPage',
|
||||
})
|
||||
} catch {
|
||||
return { newsSource: 'externalBlog' as const }
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async function getLocalNewsPage(locale: Locale, page: number) {
|
||||
const payload = await getPayloadClient()
|
||||
const getLocalNewsPage = cacheCmsQuery(
|
||||
['local-news-page'],
|
||||
async (locale: Locale, page: number) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
return payload.find({
|
||||
collection: 'news',
|
||||
depth: 1,
|
||||
limit: 15,
|
||||
locale,
|
||||
page,
|
||||
sort: '-publishedAt,-updatedAt',
|
||||
where: {
|
||||
docLocale: {
|
||||
equals: locale,
|
||||
return payload.find({
|
||||
collection: 'news',
|
||||
depth: 1,
|
||||
limit: 15,
|
||||
locale,
|
||||
page,
|
||||
sort: '-publishedAt,-updatedAt',
|
||||
where: {
|
||||
docLocale: {
|
||||
equals: locale,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
function getCoverImageUrl(article: News) {
|
||||
if (!article.coverImage || typeof article.coverImage === 'number') return null
|
||||
|
||||
@@ -9,6 +9,7 @@ import { HomeNews } from '@/components/home/home-news'
|
||||
import { HomeRecognition } from '@/components/home/home-recognition'
|
||||
import { HomeStatement } from '@/components/home/home-statement'
|
||||
import { getBlogPosts } from '@/lib/blog-api'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getSiteChromeSettings } from '@/lib/global-settings'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { VISIBLE_PRODUCT_STATUS } from '@/lib/product-status'
|
||||
@@ -110,37 +111,45 @@ function normalizeHomepageModuleOrder(items: Homepage['moduleOrder']): HomepageM
|
||||
return [...new Set([...ordered, ...validModules])]
|
||||
}
|
||||
|
||||
async function getHomepageData(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
return payload.findGlobal({
|
||||
depth: 2,
|
||||
slug: 'homepage',
|
||||
locale,
|
||||
})
|
||||
}
|
||||
const getHomepageData = cacheCmsQuery<[Locale], Homepage>(
|
||||
['homepage-global'],
|
||||
async (locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
async function getPublishedProducts(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const published = await payload.find({
|
||||
collection: 'products',
|
||||
depth: 1,
|
||||
limit: 100,
|
||||
locale,
|
||||
sort: 'order',
|
||||
where: {
|
||||
and: [
|
||||
{ docLocale: { equals: locale } },
|
||||
{ status: { equals: VISIBLE_PRODUCT_STATUS } },
|
||||
{ name: { exists: true } },
|
||||
],
|
||||
},
|
||||
})
|
||||
return payload.findGlobal({
|
||||
depth: 2,
|
||||
slug: 'homepage',
|
||||
locale,
|
||||
}) as Promise<Homepage>
|
||||
},
|
||||
)
|
||||
|
||||
if (published.docs.length > 0) {
|
||||
return published.docs
|
||||
}
|
||||
return []
|
||||
}
|
||||
const getPublishedProducts = cacheCmsQuery<[Locale], Product[]>(
|
||||
['published-products'],
|
||||
async (locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
const published = await payload.find({
|
||||
collection: 'products',
|
||||
depth: 1,
|
||||
limit: 100,
|
||||
locale,
|
||||
sort: 'order',
|
||||
where: {
|
||||
and: [
|
||||
{ docLocale: { equals: locale } },
|
||||
{ status: { equals: VISIBLE_PRODUCT_STATUS } },
|
||||
{ name: { exists: true } },
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
if (published.docs.length > 0) {
|
||||
return published.docs
|
||||
}
|
||||
|
||||
return []
|
||||
},
|
||||
)
|
||||
|
||||
function getTemplateProductHrefs(products: Product[], locale: Locale) {
|
||||
return products
|
||||
@@ -148,23 +157,26 @@ function getTemplateProductHrefs(products: Product[], locale: Locale) {
|
||||
.map((product) => `/${locale}/products/${product.slug}`)
|
||||
}
|
||||
|
||||
async function getLatestLocalNews(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const result = await payload.find({
|
||||
collection: 'news',
|
||||
depth: 1,
|
||||
limit: 6,
|
||||
locale,
|
||||
sort: '-publishedAt',
|
||||
where: {
|
||||
docLocale: {
|
||||
equals: locale,
|
||||
const getLatestLocalNews = cacheCmsQuery<[Locale], News[]>(
|
||||
['latest-local-news'],
|
||||
async (locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
const result = await payload.find({
|
||||
collection: 'news',
|
||||
depth: 1,
|
||||
limit: 6,
|
||||
locale,
|
||||
sort: '-publishedAt',
|
||||
where: {
|
||||
docLocale: {
|
||||
equals: locale,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
return result.docs
|
||||
}
|
||||
return result.docs
|
||||
},
|
||||
)
|
||||
|
||||
function getLocalNewsHighlights(items: Homepage['newsHighlights']) {
|
||||
return (items || []).filter((item): item is News => typeof item === 'object')
|
||||
|
||||
@@ -3,6 +3,7 @@ import { notFound } from 'next/navigation'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { ALL_PRODUCTS_FALLBACK } from '@/lib/fallback-data'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { ACCESSIBLE_PRODUCT_STATUSES } from '@/lib/product-status'
|
||||
import { getProductSeriesDefault } from '@/lib/product-series-defaults'
|
||||
@@ -336,7 +337,7 @@ function ProductSpecificationsSection({
|
||||
)
|
||||
}
|
||||
|
||||
async function getProductPageData(slug: string, locale: Locale) {
|
||||
async function getProductPageDataUncached(slug: string, locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
const products = await payload.find({
|
||||
@@ -455,6 +456,11 @@ async function getProductPageData(slug: string, locale: Locale) {
|
||||
return { downloads, news: relatedNews, overviewMedia, product, reviews: reviews.docs, videos: videos.docs }
|
||||
}
|
||||
|
||||
const getProductPageData = cacheCmsQuery<[string, Locale], Awaited<ReturnType<typeof getProductPageDataUncached>>>(
|
||||
['product-page-data'],
|
||||
getProductPageDataUncached,
|
||||
)
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -3,6 +3,7 @@ import Link from 'next/link'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { getProductSeriesDefault } from '@/lib/product-series-defaults'
|
||||
import { VISIBLE_PRODUCT_STATUS } from '@/lib/product-status'
|
||||
@@ -100,7 +101,7 @@ function normalizeCategory(category: number | ProductCategory | null | undefined
|
||||
return getDefaultSeriesCopy(getCategoryKeyFromSlug(slug), locale)
|
||||
}
|
||||
|
||||
async function getProductsPageData(locale: Locale) {
|
||||
async function getProductsPageDataUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const result = await payload.find({
|
||||
collection: 'products',
|
||||
@@ -162,6 +163,43 @@ async function getProductsPageData(locale: Locale) {
|
||||
}))
|
||||
}
|
||||
|
||||
const getProductsPageData = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getProductsPageDataUncached>>>(
|
||||
['products-page-data'],
|
||||
getProductsPageDataUncached,
|
||||
)
|
||||
|
||||
const getProductsPageSettings = cacheCmsQuery(
|
||||
['products-page-global'],
|
||||
async (locale: Locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
return payload.findGlobal({
|
||||
depth: 1,
|
||||
slug: 'productsPage',
|
||||
locale,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
const getProductCategories = cacheCmsQuery<[Locale], ProductCategory[]>(
|
||||
['product-categories'],
|
||||
async (locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
const categories = await payload.find({
|
||||
collection: 'productCategories',
|
||||
depth: 0,
|
||||
limit: 50,
|
||||
locale,
|
||||
sort: 'order',
|
||||
where: {
|
||||
and: [{ docLocale: { equals: locale } }, { name: { exists: true } }],
|
||||
},
|
||||
})
|
||||
|
||||
return categories.docs
|
||||
},
|
||||
)
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
@@ -187,25 +225,13 @@ export default async function ProductsPage({
|
||||
const { locale } = await params
|
||||
setRequestLocale(locale)
|
||||
|
||||
const products = await getProductsPageData(locale)
|
||||
const payload = await getPayloadClient()
|
||||
const page = await payload.findGlobal({
|
||||
depth: 1,
|
||||
slug: 'productsPage',
|
||||
locale,
|
||||
})
|
||||
const categories = await payload.find({
|
||||
collection: 'productCategories',
|
||||
depth: 0,
|
||||
limit: 50,
|
||||
locale,
|
||||
sort: 'order',
|
||||
where: {
|
||||
and: [{ docLocale: { equals: locale } }, { name: { exists: true } }],
|
||||
},
|
||||
})
|
||||
const [products, page, categories] = await Promise.all([
|
||||
getProductsPageData(locale),
|
||||
getProductsPageSettings(locale),
|
||||
getProductCategories(locale),
|
||||
])
|
||||
const categoryMap = new Map(
|
||||
categories.docs.map((category) => [category.slug, normalizeCategory(category, category.slug, locale)]),
|
||||
categories.map((category) => [category.slug, normalizeCategory(category, category.slug, locale)]),
|
||||
)
|
||||
const groups = new Map<string, { series: ProductSeries; items: ProductCard[] }>()
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { VideoModalGrid, type VideoModalGridItem } from '@/components/site/video-modal-grid'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates, trimDescription } from '@/lib/seo'
|
||||
import { normalizeUploadUrl } from '@/lib/upload-url'
|
||||
@@ -58,7 +59,7 @@ function truncateSourceName(value: string | null | undefined) {
|
||||
return chars.length > 20 ? `${chars.slice(0, 20).join('')}...` : source
|
||||
}
|
||||
|
||||
async function getReviewsPageData(locale: Locale) {
|
||||
async function getReviewsPageDataUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const [videos, reviews] = await Promise.all([
|
||||
payload.find({
|
||||
@@ -95,7 +96,12 @@ async function getReviewsPageData(locale: Locale) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getReviewsPageSettings(locale: Locale) {
|
||||
const getReviewsPageData = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getReviewsPageDataUncached>>>(
|
||||
['reviews-page-data'],
|
||||
getReviewsPageDataUncached,
|
||||
)
|
||||
|
||||
async function getReviewsPageSettingsUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const fallback = {
|
||||
description:
|
||||
@@ -141,6 +147,11 @@ async function getReviewsPageSettings(locale: Locale) {
|
||||
}
|
||||
}
|
||||
|
||||
const getReviewsPageSettings = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getReviewsPageSettingsUncached>>>(
|
||||
['reviews-page-global'],
|
||||
getReviewsPageSettingsUncached,
|
||||
)
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -3,6 +3,7 @@ import Link from 'next/link'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { VISIBLE_PRODUCT_STATUS } from '@/lib/product-status'
|
||||
import { renderRichText } from '@/lib/render-rich-text'
|
||||
@@ -13,7 +14,7 @@ import { SupportContactForm } from './support-contact-form'
|
||||
|
||||
export const revalidate = 300
|
||||
|
||||
async function getContactPageData(locale: Locale) {
|
||||
async function getContactPageDataUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
const [page, products] = await Promise.all([
|
||||
@@ -40,6 +41,11 @@ async function getContactPageData(locale: Locale) {
|
||||
return { page, products: products.docs }
|
||||
}
|
||||
|
||||
const getContactPageData = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getContactPageDataUncached>>>(
|
||||
['support-contact-page-data'],
|
||||
getContactPageDataUncached,
|
||||
)
|
||||
|
||||
function getContactPageTitle(rawTitle: string | null | undefined, locale: Locale) {
|
||||
const normalized = rawTitle?.trim()
|
||||
if (!normalized) return ''
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates, extractRichTextPlainText } from '@/lib/seo'
|
||||
import { normalizeUploadUrl } from '@/lib/upload-url'
|
||||
@@ -125,22 +126,25 @@ function getFaqHeroImageUrl(settings: FaqPageSettings) {
|
||||
return normalizeUploadUrl(settings.hero?.imageUrl?.trim() || null)
|
||||
}
|
||||
|
||||
async function getFaqPageSettings(locale: Locale): Promise<FaqPageSettings> {
|
||||
const payload = await getPayloadClient()
|
||||
const getFaqPageSettings = cacheCmsQuery<[Locale], FaqPageSettings>(
|
||||
['faq-page-global'],
|
||||
async (locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
try {
|
||||
const faqPayload = payload as unknown as PayloadWithFaqGlobal
|
||||
return await faqPayload.findGlobal({
|
||||
depth: 1,
|
||||
locale,
|
||||
slug: 'faqPage',
|
||||
})
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
try {
|
||||
const faqPayload = payload as unknown as PayloadWithFaqGlobal
|
||||
return await faqPayload.findGlobal({
|
||||
depth: 1,
|
||||
locale,
|
||||
slug: 'faqPage',
|
||||
})
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async function getFaqPageData(locale: Locale) {
|
||||
async function getFaqPageDataUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const result = await payload.find({
|
||||
collection: 'faqs',
|
||||
@@ -164,6 +168,11 @@ async function getFaqPageData(locale: Locale) {
|
||||
return [...groups.entries()].map(([group, faqs]) => ({ faqs, group }))
|
||||
}
|
||||
|
||||
const getFaqPageData = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getFaqPageDataUncached>>>(
|
||||
['faq-page-data'],
|
||||
getFaqPageDataUncached,
|
||||
)
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { SiteIcon } from '@/components/site/site-icons'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { renderRichText } from '@/lib/render-rich-text'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates, extractRichTextPlainText, trimDescription } from '@/lib/seo'
|
||||
@@ -17,14 +18,17 @@ type SupportEntry = NonNullable<SupportPageData['primaryEntries']>[number] & {
|
||||
iconKey?: string | null
|
||||
}
|
||||
|
||||
async function getSupportPageData(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const getSupportPageData = cacheCmsQuery(
|
||||
['support-page-global'],
|
||||
async (locale: Locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
return payload.findGlobal({
|
||||
slug: 'supportPage',
|
||||
locale,
|
||||
})
|
||||
}
|
||||
return payload.findGlobal({
|
||||
slug: 'supportPage',
|
||||
locale,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
function getSupportPageTitle(rawTitle: string | null | undefined, locale: Locale) {
|
||||
const normalized = rawTitle?.trim()
|
||||
|
||||
@@ -3,6 +3,7 @@ import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { VideoModalGrid, type VideoModalGridItem } from '@/components/site/video-modal-grid'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates, trimDescription } from '@/lib/seo'
|
||||
import { normalizeUploadUrl } from '@/lib/upload-url'
|
||||
@@ -54,7 +55,7 @@ const FALLBACK_VIDEOS: TutorialVideo[] = [
|
||||
},
|
||||
]
|
||||
|
||||
async function getTutorialPageData(locale: Locale) {
|
||||
async function getTutorialPageDataUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const [page, videos] = await Promise.all([
|
||||
payload.findGlobal({
|
||||
@@ -87,6 +88,11 @@ async function getTutorialPageData(locale: Locale) {
|
||||
}
|
||||
}
|
||||
|
||||
const getTutorialPageData = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getTutorialPageDataUncached>>>(
|
||||
['support-tutorial-page-data'],
|
||||
getTutorialPageDataUncached,
|
||||
)
|
||||
|
||||
function getTutorialTitle(tutorial: TutorialSettings | null | undefined, locale: Locale) {
|
||||
return tutorial?.hero?.title?.trim() || (locale === 'zh' ? '视频教程' : 'Video Tutorials')
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import Link from 'next/link'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { renderRichText } from '@/lib/render-rich-text'
|
||||
import { buildLocaleAlternates, extractRichTextPlainText, trimDescription } from '@/lib/seo'
|
||||
@@ -11,14 +12,17 @@ import type { WarrantyPage as WarrantyPageType } from '@/payload-types'
|
||||
|
||||
export const revalidate = 300
|
||||
|
||||
async function getWarrantyPageData(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const getWarrantyPageData = cacheCmsQuery(
|
||||
['warranty-page-global'],
|
||||
async (locale: Locale) => {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
return payload.findGlobal({
|
||||
slug: 'warrantyPage',
|
||||
locale,
|
||||
})
|
||||
}
|
||||
return payload.findGlobal({
|
||||
slug: 'warrantyPage',
|
||||
locale,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
function getWarrantyPageTitle(rawTitle: string | null | undefined, locale: Locale) {
|
||||
const normalized = rawTitle?.trim()
|
||||
|
||||
@@ -3,6 +3,7 @@ import Link from 'next/link'
|
||||
import { setRequestLocale } from 'next-intl/server'
|
||||
import type { Locale } from '@/i18n/config'
|
||||
import { PageHero } from '@/components/site/page-hero'
|
||||
import { cacheCmsQuery } from '@/lib/cms-cache'
|
||||
import { getPayloadClient } from '@/lib/payload'
|
||||
import { buildAbsoluteUrl, buildLocaleAlternates } from '@/lib/seo'
|
||||
import { normalizeUploadUrl } from '@/lib/upload-url'
|
||||
@@ -292,7 +293,7 @@ function getMapPoints(dealers: Dealer[]) {
|
||||
return [...grouped.values()].sort((left, right) => left.region.localeCompare(right.region))
|
||||
}
|
||||
|
||||
async function getDealersPageSettings(locale: Locale) {
|
||||
async function getDealersPageSettingsUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
|
||||
try {
|
||||
@@ -348,7 +349,12 @@ async function getDealersPageSettings(locale: Locale) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getDealersPageData(locale: Locale) {
|
||||
const getDealersPageSettings = cacheCmsQuery<
|
||||
[Locale],
|
||||
Awaited<ReturnType<typeof getDealersPageSettingsUncached>>
|
||||
>(['dealers-page-global'], getDealersPageSettingsUncached)
|
||||
|
||||
async function getDealersPageDataUncached(locale: Locale) {
|
||||
const payload = await getPayloadClient()
|
||||
const result = await payload.find({
|
||||
collection: 'dealers',
|
||||
@@ -381,6 +387,11 @@ async function getDealersPageData(locale: Locale) {
|
||||
}
|
||||
}
|
||||
|
||||
const getDealersPageData = cacheCmsQuery<[Locale], Awaited<ReturnType<typeof getDealersPageDataUncached>>>(
|
||||
['dealers-page-data'],
|
||||
getDealersPageDataUncached,
|
||||
)
|
||||
|
||||
function DealerTabs({
|
||||
activeTab,
|
||||
locale,
|
||||
@@ -677,8 +688,10 @@ export default async function WhereToBuyPage({
|
||||
const query = await searchParams
|
||||
setRequestLocale(locale)
|
||||
|
||||
const { dealerDocs, dealerGroups, storeDocs } = await getDealersPageData(locale)
|
||||
const settings = await getDealersPageSettings(locale)
|
||||
const [{ dealerDocs, dealerGroups, storeDocs }, settings] = await Promise.all([
|
||||
getDealersPageData(locale),
|
||||
getDealersPageSettings(locale),
|
||||
])
|
||||
const hasDealers = dealerDocs.length > 0
|
||||
const hasStores = storeDocs.length > 0
|
||||
const shouldShowTabs = hasDealers && hasStores
|
||||
|
||||
Reference in New Issue
Block a user