게시물 상세 이동 지연 개선 및 전체 목록 조회 제거 (v1.10.37)
- 본문만 블로킹 조회, 태그·광고는 lazy로 전환 - 이전·다음 글을 상세 API에서 window 함수로 계산해 응답에 포함 - 전체 게시물(본문 포함) 조회 제거, 광고 site-settings 캐시 재사용 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1085,6 +1085,73 @@ export const getPostBySlug = async (slug, { includeMembership = false } = {}) =>
|
||||
return rows[0] ? mapPostRow(rows[0]) : null
|
||||
}
|
||||
|
||||
/**
|
||||
* 공개 게시물 상세의 이전(더 최신)·다음(더 예전) 글을 조회한다.
|
||||
* 목록과 같은 정렬(발행일 DESC) 기준으로 인접 글의 제목·슬러그만 반환한다.
|
||||
* @param {string} slug - 기준 게시물 슬러그
|
||||
* @param {{ includeMembership?: boolean }} [options] - 조회 옵션
|
||||
* @returns {Promise<{ previous: { title: string, slug: string } | null, next: { title: string, slug: string } | null }>} 인접 글
|
||||
*/
|
||||
export const getAdjacentPosts = async (slug, { includeMembership = false } = {}) => {
|
||||
const sql = getPostgresClient()
|
||||
|
||||
if (!sql) {
|
||||
const samplePosts = getSamplePosts()
|
||||
.filter((post) => post.status === 'published' && (!post.publishedAt || new Date(post.publishedAt) <= new Date()))
|
||||
.sort((left, right) => {
|
||||
const leftTime = new Date(left.publishedAt || left.createdAt || 0).getTime()
|
||||
const rightTime = new Date(right.publishedAt || right.createdAt || 0).getTime()
|
||||
return rightTime - leftTime
|
||||
})
|
||||
const index = samplePosts.findIndex((post) => post.slug === slug)
|
||||
if (index === -1) {
|
||||
return { previous: null, next: null }
|
||||
}
|
||||
const toNeighbor = (post) => (post ? { title: post.title, slug: post.slug } : null)
|
||||
return {
|
||||
previous: index > 0 ? toNeighbor(samplePosts[index - 1]) : null,
|
||||
next: index < samplePosts.length - 1 ? toNeighbor(samplePosts[index + 1]) : null
|
||||
}
|
||||
}
|
||||
|
||||
const rows = await sql`
|
||||
WITH ordered AS (
|
||||
SELECT
|
||||
posts.slug,
|
||||
posts.title,
|
||||
LAG(posts.slug) OVER w AS previous_slug,
|
||||
LAG(posts.title) OVER w AS previous_title,
|
||||
LEAD(posts.slug) OVER w AS next_slug,
|
||||
LEAD(posts.title) OVER w AS next_title
|
||||
FROM posts
|
||||
WHERE (
|
||||
posts.status = 'published'
|
||||
OR (${includeMembership} = true AND posts.status = 'members')
|
||||
)
|
||||
AND (
|
||||
posts.status = 'members'
|
||||
OR posts.published_at IS NULL
|
||||
OR posts.published_at <= now()
|
||||
)
|
||||
WINDOW w AS (ORDER BY posts.published_at DESC NULLS LAST, posts.created_at DESC)
|
||||
)
|
||||
SELECT previous_slug, previous_title, next_slug, next_title
|
||||
FROM ordered
|
||||
WHERE slug = ${slug}
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
const row = rows[0]
|
||||
if (!row) {
|
||||
return { previous: null, next: null }
|
||||
}
|
||||
|
||||
return {
|
||||
previous: row.previous_slug ? { title: row.previous_title, slug: row.previous_slug } : null,
|
||||
next: row.next_slug ? { title: row.next_title, slug: row.next_slug } : null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 공개 고정 페이지 목록 조회
|
||||
* @param {{ listedOnly?: boolean, limitPerSection?: number|null }} [options] - 조회 옵션
|
||||
|
||||
Reference in New Issue
Block a user