從前面的文章中,我們已經知道如何渲染一篇文章,接下來只要如法泡製,就能建立一個索引頁面列出部落格中所有的文章了。
import Container from '@module/essence/components/Container'import Heading from '@module/essence/components/Heading'import { getPosts } from '../../utils/post'
const BlogPostIndexPage = ({ posts }) => { return ( <Container> {posts.map((post) => ( <Link key={post.slug} fluid href={`/blog/${post.slug}`}> <Heading size="m">{post.frontMatter.title}</Heading> </Link> ))} </Container> )}
export const getStaticProps = ({ params }) => { return { props: { posts: getPosts() }, }}
export default BlogPostIndexPage
當文章數量不多時,或許唯一的索引頁面是一個可行的做法,但隨著部落格的經營,文章只會增加不會減少,如果文章數量達到某個規模時,勢必要採取某些方法讓這個索引頁面不要過度膨脹。目前這個階段,我傾向使用分頁來管理,因為對於讀者來說,仍然有辦法透過前往不同的分頁來瀏覽完所有文章。如果文章再成長到下一個規模時,或許就要捨棄分頁,改用關鍵字搜尋了,但分頁機制對於目前的部落格規模來說已經十分足夠!
我的實作方式是建立每一個分頁的路由頁面,並且擴充 utility functions 以支援分頁計算。
路由
import Container from '@module/essence/components/Container'import Heading from '@module/essence/components/Heading'import Label from '@module/essence/components/Label'import { getPosts, getPostsByPageSizeAndPageId } from '../../../utils/post'
const BlogPostIndexPage = ({ posts, pagination }) => { return ( <Container> {posts.map((post) => ( <Link key={post.slug} fluid href={`/blog/${post.slug}`}> <Heading size="m">{post.frontMatter.title}</Heading> </Link> ))} <Label size="m"> 第{pagination.pageId}頁,共{pagination.pageCount}頁 </Label> </Container> )}
export async function getStaticPaths() { const BLOG_PAGE_SIZE = 10 const posts = await getPosts() const pageCount = Math.ceil(posts.length / BLOG_PAGE_SIZE) return { paths: Array(pageCount) .fill(0) .map((_, pageIndex) => { const pageId = `${pageIndex + 1}` return { params: { pageId, }, } }), fallback: false, // can also be true or 'blocking' }}
export const getStaticProps = ({ params }) => { const BLOG_PAGE_SIZE = 10 const posts = getPosts() const pageCount = Math.ceil(posts.length / BLOG_PAGE_SIZE) const { pageId } = params const currentPagedPosts = getPostsByPageSizeAndPageId(BLOG_PAGE_SIZE, pageId) return { props: { posts: currentPagedPosts, pagination: { pageSize: BLOG_PAGE_SIZE, pageCount, pageId, }, }, }}
export default BlogPostIndexPage
分頁計算 utility functions
只要能夠知道所有文章的數量,以及每頁文章數量,就能進行分頁計算,或是拿到屬於特定頁面的文章列表,此外,我還打算使用文章發佈日期進行排序。因此我們可以在 utility functions 實作 與 兩個函數:
export const getPosts = () => { // ...}
export const getSortedPosts = () => { const posts = getPosts() const sortedPosts = posts.sort((a, b) => { if (a.frontMatter.publishDate < b.frontMatter.publishDate) { return 1 } else if (a.frontMatter.publishDate > b.frontMatter.publishDate) { return -1 } else { return 0 } }) return sortedPosts}
export const getPostsByPageSizeAndPageId = (pageSize, pageId) => { const sortedPosts = getSortedPosts() const offset = pageSize * (parseInt(pageId) - 1) return sortedPosts.slice(offset, offset + pageSize)}
如此一來,我們基本上已經滿足一個部落格所需要的最低功能了:
相信讀者們也已具備足夠的知識,可以開始動手客製出自己的部落格,展開屬於自己的旅程了!關於功能性的講解在此先告一段落,後續文章將會開始介紹偏向營運層面以及閱讀體驗的功能,歡迎有興趣繼續鑽研的朋友一起看下去。