feat(templates): website template performance improvements (#9466)
- Uses `pagination: false` where we don't need `totalDocs`. - in `preview/route.ts` uses `depth: 0`, select of only ID to improve performance - in `search` uses `select` to select only needed properties - adds type safety best practices to collection configs with `defaultPopulate` - uses `payload.count` to resolve SSG `pageNumber`s
This commit is contained in:
@@ -94,6 +94,7 @@ const queryPageBySlug = cache(async ({ slug }: { slug: string }) => {
|
||||
collection: 'pages',
|
||||
draft,
|
||||
limit: 1,
|
||||
pagination: false,
|
||||
overrideAccess: draft,
|
||||
where: {
|
||||
slug: {
|
||||
|
||||
@@ -67,8 +67,13 @@ export async function GET(
|
||||
// Verify the given slug exists
|
||||
try {
|
||||
const docs = await payload.find({
|
||||
collection: collection,
|
||||
collection,
|
||||
draft: true,
|
||||
limit: 1,
|
||||
// pagination: false reduces overhead if you don't need totalDocs
|
||||
pagination: false,
|
||||
depth: 0,
|
||||
select: {},
|
||||
where: {
|
||||
slug: {
|
||||
equals: slug,
|
||||
|
||||
@@ -87,6 +87,7 @@ const queryPostBySlug = cache(async ({ slug }: { slug: string }) => {
|
||||
draft,
|
||||
limit: 1,
|
||||
overrideAccess: draft,
|
||||
pagination: false,
|
||||
where: {
|
||||
slug: {
|
||||
equals: slug,
|
||||
|
||||
@@ -19,6 +19,12 @@ export default async function Page() {
|
||||
depth: 1,
|
||||
limit: 12,
|
||||
overrideAccess: false,
|
||||
select: {
|
||||
title: true,
|
||||
slug: true,
|
||||
categories: true,
|
||||
meta: true,
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
@@ -71,20 +71,17 @@ export async function generateMetadata({ params: paramsPromise }: Args): Promise
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const payload = await getPayload({ config: configPromise })
|
||||
const posts = await payload.find({
|
||||
const { totalDocs } = await payload.count({
|
||||
collection: 'posts',
|
||||
depth: 0,
|
||||
limit: 10,
|
||||
draft: false,
|
||||
overrideAccess: false,
|
||||
})
|
||||
|
||||
const totalPages = Math.ceil(totalDocs / 10)
|
||||
|
||||
const pages: { pageNumber: string }[] = []
|
||||
|
||||
if (posts.totalPages) {
|
||||
for (let i = 1; i <= posts.totalPages; i++) {
|
||||
pages.push({ pageNumber: String(i) })
|
||||
}
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
pages.push({ pageNumber: String(i) })
|
||||
}
|
||||
|
||||
return pages
|
||||
|
||||
@@ -7,6 +7,7 @@ import React from 'react'
|
||||
import { Post } from '@/payload-types'
|
||||
import { Search } from '@/search/Component'
|
||||
import PageClient from './page.client'
|
||||
import { CardPostData } from '@/components/Card'
|
||||
|
||||
type Args = {
|
||||
searchParams: Promise<{
|
||||
@@ -21,6 +22,14 @@ export default async function Page({ searchParams: searchParamsPromise }: Args)
|
||||
collection: 'search',
|
||||
depth: 1,
|
||||
limit: 12,
|
||||
select: {
|
||||
title: true,
|
||||
slug: true,
|
||||
categories: true,
|
||||
meta: true,
|
||||
},
|
||||
// pagination: false reduces overhead if you don't need totalDocs
|
||||
pagination: false,
|
||||
...(query
|
||||
? {
|
||||
where: {
|
||||
@@ -62,7 +71,7 @@ export default async function Page({ searchParams: searchParamsPromise }: Args)
|
||||
</div>
|
||||
|
||||
{posts.totalDocs > 0 ? (
|
||||
<CollectionArchive posts={posts.docs as unknown as Post[]} />
|
||||
<CollectionArchive posts={posts.docs as CardPostData[]} />
|
||||
) : (
|
||||
<div className="container">No results found.</div>
|
||||
)}
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
} from '@payloadcms/plugin-seo/fields'
|
||||
import { getServerSideURL } from '@/utilities/getURL'
|
||||
|
||||
export const Pages: CollectionConfig = {
|
||||
export const Pages: CollectionConfig<'pages'> = {
|
||||
slug: 'pages',
|
||||
access: {
|
||||
create: authenticated,
|
||||
@@ -32,6 +32,7 @@ export const Pages: CollectionConfig = {
|
||||
},
|
||||
// This config controls what's populated by default when a page is referenced
|
||||
// https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property
|
||||
// Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'pagess'>
|
||||
defaultPopulate: {
|
||||
title: true,
|
||||
slug: true,
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import { slugField } from '@/fields/slug'
|
||||
import { getServerSideURL } from '@/utilities/getURL'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
export const Posts: CollectionConfig<'posts'> = {
|
||||
slug: 'posts',
|
||||
access: {
|
||||
create: authenticated,
|
||||
@@ -38,6 +38,7 @@ export const Posts: CollectionConfig = {
|
||||
},
|
||||
// This config controls what's populated by default when a post is referenced
|
||||
// https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property
|
||||
// Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'posts'>
|
||||
defaultPopulate: {
|
||||
title: true,
|
||||
slug: true,
|
||||
|
||||
@@ -8,10 +8,12 @@ import type { Post } from '@/payload-types'
|
||||
|
||||
import { Media } from '@/components/Media'
|
||||
|
||||
export type CardPostData = Pick<Post, 'slug' | 'categories' | 'meta' | 'title'>
|
||||
|
||||
export const Card: React.FC<{
|
||||
alignItems?: 'center'
|
||||
className?: string
|
||||
doc?: Post
|
||||
doc?: CardPostData
|
||||
relationTo?: 'posts'
|
||||
showCategories?: boolean
|
||||
title?: string
|
||||
|
||||
@@ -3,10 +3,10 @@ import React from 'react'
|
||||
|
||||
import type { Post } from '@/payload-types'
|
||||
|
||||
import { Card } from '@/components/Card'
|
||||
import { Card, CardPostData } from '@/components/Card'
|
||||
|
||||
export type Props = {
|
||||
posts: Post[]
|
||||
posts: CardPostData[]
|
||||
}
|
||||
|
||||
export const CollectionArchive: React.FC<Props> = (props) => {
|
||||
|
||||
@@ -21,6 +21,7 @@ export async function generateStaticParams() {
|
||||
draft: false,
|
||||
limit: 1000,
|
||||
overrideAccess: false,
|
||||
pagination: false,
|
||||
select: {
|
||||
slug: true,
|
||||
},
|
||||
@@ -47,7 +48,7 @@ export default async function Page({ params: paramsPromise }: Args) {
|
||||
const { slug = 'home' } = await paramsPromise
|
||||
const url = '/' + slug
|
||||
|
||||
let page: PageType | null
|
||||
let page: Pick<PageType, 'slug' | 'layout' | 'hero'> | null
|
||||
|
||||
page = await queryPageBySlug({
|
||||
slug,
|
||||
@@ -94,7 +95,13 @@ const queryPageBySlug = cache(async ({ slug }: { slug: string }) => {
|
||||
collection: 'pages',
|
||||
draft,
|
||||
limit: 1,
|
||||
pagination: false,
|
||||
overrideAccess: draft,
|
||||
select: {
|
||||
slug: true,
|
||||
hero: true,
|
||||
layout: true,
|
||||
},
|
||||
where: {
|
||||
slug: {
|
||||
equals: slug,
|
||||
|
||||
@@ -67,8 +67,12 @@ export async function GET(
|
||||
// Verify the given slug exists
|
||||
try {
|
||||
const docs = await payload.find({
|
||||
collection: collection,
|
||||
collection,
|
||||
draft: true,
|
||||
limit: 1,
|
||||
pagination: false,
|
||||
depth: 0,
|
||||
select: {},
|
||||
where: {
|
||||
slug: {
|
||||
equals: slug,
|
||||
|
||||
@@ -20,6 +20,7 @@ export async function generateStaticParams() {
|
||||
collection: 'posts',
|
||||
draft: false,
|
||||
limit: 1000,
|
||||
pagination: false,
|
||||
overrideAccess: false,
|
||||
select: {
|
||||
slug: true,
|
||||
@@ -87,6 +88,7 @@ const queryPostBySlug = cache(async ({ slug }: { slug: string }) => {
|
||||
draft,
|
||||
limit: 1,
|
||||
overrideAccess: draft,
|
||||
pagination: false,
|
||||
where: {
|
||||
slug: {
|
||||
equals: slug,
|
||||
|
||||
@@ -19,6 +19,12 @@ export default async function Page() {
|
||||
depth: 1,
|
||||
limit: 12,
|
||||
overrideAccess: false,
|
||||
select: {
|
||||
title: true,
|
||||
slug: true,
|
||||
categories: true,
|
||||
meta: true,
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
@@ -71,20 +71,17 @@ export async function generateMetadata({ params: paramsPromise }: Args): Promise
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const payload = await getPayload({ config: configPromise })
|
||||
const posts = await payload.find({
|
||||
const { totalDocs } = await payload.count({
|
||||
collection: 'posts',
|
||||
depth: 0,
|
||||
limit: 10,
|
||||
draft: false,
|
||||
overrideAccess: false,
|
||||
})
|
||||
|
||||
const totalPages = Math.ceil(totalDocs / 10)
|
||||
|
||||
const pages: { pageNumber: string }[] = []
|
||||
|
||||
if (posts.totalPages) {
|
||||
for (let i = 1; i <= posts.totalPages; i++) {
|
||||
pages.push({ pageNumber: String(i) })
|
||||
}
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
pages.push({ pageNumber: String(i) })
|
||||
}
|
||||
|
||||
return pages
|
||||
|
||||
@@ -7,6 +7,7 @@ import React from 'react'
|
||||
import { Post } from '@/payload-types'
|
||||
import { Search } from '@/search/Component'
|
||||
import PageClient from './page.client'
|
||||
import { CardPostData } from '@/components/Card'
|
||||
|
||||
type Args = {
|
||||
searchParams: Promise<{
|
||||
@@ -21,6 +22,14 @@ export default async function Page({ searchParams: searchParamsPromise }: Args)
|
||||
collection: 'search',
|
||||
depth: 1,
|
||||
limit: 12,
|
||||
select: {
|
||||
title: true,
|
||||
slug: true,
|
||||
categories: true,
|
||||
meta: true,
|
||||
},
|
||||
// pagination: false reduces overhead if you don't need totalDocs
|
||||
pagination: false,
|
||||
...(query
|
||||
? {
|
||||
where: {
|
||||
@@ -62,7 +71,7 @@ export default async function Page({ searchParams: searchParamsPromise }: Args)
|
||||
</div>
|
||||
|
||||
{posts.totalDocs > 0 ? (
|
||||
<CollectionArchive posts={posts.docs as unknown as Post[]} />
|
||||
<CollectionArchive posts={posts.docs as CardPostData[]} />
|
||||
) : (
|
||||
<div className="container">No results found.</div>
|
||||
)}
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
} from '@payloadcms/plugin-seo/fields'
|
||||
import { getServerSideURL } from '@/utilities/getURL'
|
||||
|
||||
export const Pages: CollectionConfig = {
|
||||
export const Pages: CollectionConfig<'pages'> = {
|
||||
slug: 'pages',
|
||||
access: {
|
||||
create: authenticated,
|
||||
@@ -32,6 +32,7 @@ export const Pages: CollectionConfig = {
|
||||
},
|
||||
// This config controls what's populated by default when a page is referenced
|
||||
// https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property
|
||||
// Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'pages'>
|
||||
defaultPopulate: {
|
||||
title: true,
|
||||
slug: true,
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import { slugField } from '@/fields/slug'
|
||||
import { getServerSideURL } from '@/utilities/getURL'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
export const Posts: CollectionConfig<'posts'> = {
|
||||
slug: 'posts',
|
||||
access: {
|
||||
create: authenticated,
|
||||
@@ -38,6 +38,7 @@ export const Posts: CollectionConfig = {
|
||||
},
|
||||
// This config controls what's populated by default when a post is referenced
|
||||
// https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property
|
||||
// Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'posts'>
|
||||
defaultPopulate: {
|
||||
title: true,
|
||||
slug: true,
|
||||
|
||||
@@ -8,10 +8,12 @@ import type { Post } from '@/payload-types'
|
||||
|
||||
import { Media } from '@/components/Media'
|
||||
|
||||
export type CardPostData = Pick<Post, 'slug' | 'categories' | 'meta' | 'title'>
|
||||
|
||||
export const Card: React.FC<{
|
||||
alignItems?: 'center'
|
||||
className?: string
|
||||
doc?: Post
|
||||
doc?: CardPostData
|
||||
relationTo?: 'posts'
|
||||
showCategories?: boolean
|
||||
title?: string
|
||||
|
||||
@@ -3,10 +3,10 @@ import React from 'react'
|
||||
|
||||
import type { Post } from '@/payload-types'
|
||||
|
||||
import { Card } from '@/components/Card'
|
||||
import { Card, CardPostData } from '@/components/Card'
|
||||
|
||||
export type Props = {
|
||||
posts: Post[]
|
||||
posts: CardPostData[]
|
||||
}
|
||||
|
||||
export const CollectionArchive: React.FC<Props> = (props) => {
|
||||
|
||||
Reference in New Issue
Block a user