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:
Sasha
2024-11-25 17:02:27 +02:00
committed by GitHub
parent 150c55de79
commit aa1d300062
20 changed files with 83 additions and 31 deletions

View File

@@ -94,6 +94,7 @@ const queryPageBySlug = cache(async ({ slug }: { slug: string }) => {
collection: 'pages',
draft,
limit: 1,
pagination: false,
overrideAccess: draft,
where: {
slug: {

View File

@@ -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,

View File

@@ -87,6 +87,7 @@ const queryPostBySlug = cache(async ({ slug }: { slug: string }) => {
draft,
limit: 1,
overrideAccess: draft,
pagination: false,
where: {
slug: {
equals: slug,

View File

@@ -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 (

View File

@@ -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

View File

@@ -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>
)}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -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) => {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 (

View File

@@ -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

View File

@@ -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>
)}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -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) => {