Pada bagian sebelumnya kita sudah berhasil melakukan requirement minimal dan berhasil menjalankan blog yang kita buat. Pada bagian ini kita akan membahas tentang menulis, membaca dan menampilkan artikel.
Buatlah direktori 'posts/' pada root directory project Anda. Salinlah artikel di bawah ini dan simpan ke 'posts/contoh-1.md'
---
title: 'Contoh Artikel'
date: '2022-06-01'
---
Ini adalah contoh pertama sebuah artikel blog yang disimpan dalam format **markdown**.
Kemudian, salin pula artikel di bawah ini dan simpan ke 'posts/contoh-2.md'
---
title: 'Artikel kedua'
date: '2022-05-22'
---
### Link Terkait
- [NextJs](https://nextjs.org/)
- [TypeScript](https://www.typescriptlang.org/)
Selanjutnya kita akan merubah file 'pages/index.tsx' untuk melakukan:
Untuk itu kita memerlukan mengimplementasikan 'getStaticProps'.
Pertama-tama, kita perlu melakukan instalasi
yarn add gray-matter
yarn add remark
yarn add remark-html
Selanjutnya, kita akan membuat library untuk mendapatkan 'fetch' data dari sistem file.
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { remark } from 'remark'
import html from 'remark-html'
const postsDirectory = path.join(process.cwd(), 'posts')
// if count parameter exist then return count of posts
export function getSortedPostsData(count?: number) {
// Get file names under /posts
const fileNames = fs.readdirSync(postsDirectory)
const allPostsData = fileNames.map(fileName => {
// Remove ".md" from file name to get id
const id = fileName.replace(/\.md$/, '')
// Read markdown file as string
const fullPath = path.join(postsDirectory, fileName)
const fileContents = fs.readFileSync(fullPath, 'utf8')
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents)
// Combine the data with the id
return {
id,
...(matterResult.data as { date: string; title: string })
}
})
// Sort posts by date
if (count) {
return allPostsData.sort((a, b) => {
if (a.date < b.date) {
return 1
} else {
return -1
}
}).slice(0, count)
} else {
return allPostsData.sort((a, b) => {
if (a.date < b.date) {
return 1
} else {
return -1
}
})
}
}
export function getAllPostIds() {
const fileNames = fs.readdirSync(postsDirectory)
return fileNames.map(fileName => {
return {
params: {
id: fileName.replace(/\.md$/, '')
}
}
})
}
export async function getPostData(id: string) {
const fullPath = path.join(postsDirectory, `${id}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents)
// Use remark to convert markdown into HTML string
const processedContent = await remark()
.use(html)
.process(matterResult.content)
const contentHtml = processedContent.toString()
return {
id,
contentHtml,
...(matterResult.data as { date: string; title: string; imageUrl: string })
}
}
Library di atas mempunya beberapa fungsi
Ubahlah file 'pages/index.tsx' dengan kode berikut:
import { getSortedPostsData } from "../lib/posts";
import Link from "next/link";
import { GetStaticProps } from "next";
import Image from "next/image";
export default function Home({
allPostsData,
}: {
allPostsData: {
date: string;
title: string;
id: string;
}[];
}) {
return (
<main>
<div className="text-3xl text-center my-12 font-bold text-gray-600">
<h1>My Blog</h1>
</div>
<div className="w-4/5 mx-auto">
<h3 className="text-xl text-justify text-indigo-600 font-semibold">Daftar Artikel:</h3>
<ul>
{allPostsData.map(({ id, date, title }) => (
<li key={id}>
<Link href="/posts/[id]" as={`/posts/${id}`}>
<a className="text-blue-500">{title}</a>
</Link>
<br />
<small className="text-sm text-gray-400">{date}</small>
</li>
))}
</ul>
</div>
</main>
);
}
export const getStaticProps: GetStaticProps = async () => {
const allPostsData = getSortedPostsData();
return {
props: {
allPostsData,
},
};
};
Perhatikan fungsi:
Untuk melihat hasilnya jalankan perintah
yarn dev
Kemudian, buka browser anda dan akses 'localhost:3000/'
tampilan localhost:3000
Kita telah berhasil menampilkan daftar file markdown, selanjutnya kita memerlukan laman post untuk menampilkan data post berdasarkan id. Disini, kita memerlukan rute dinamis (dynamic routes) dimana URL yang akan digunakan adalah http://localhost:3000/posts/[id] dimana id diambil dari nama file markdown (contoh http://localhost:3000/posts/contoh-1).
Buatlah direktori 'pages/posts' dan buatlah file 'pages/posts/[id].tsx' (termasuk tanda kurung siku [], sebagai nama file, nextjs akan membaca ini sebagai rute dinamis) dan tempelkan baris kode di bawah ini!
import { getAllPostIds, getPostData } from "../../lib/posts";
import { GetStaticProps, GetStaticPaths } from "next";
import Link from "next/link";
export default function Post({
postData,
}: {
postData: {
title: string;
date: string;
contentHtml: string;
};
}) {
return (
<main>
<div className="text-3xl text-center my-12 font-bold text-gray-600">
<h1>My Blog</h1>
</div>
<div className="w-4/5 mx-auto">
<article>
<h1>{postData.title}</h1>
<div className="text-gray-600">Tanggal: {postData.date}</div>
<div
className="pt-4 text-justify"
dangerouslySetInnerHTML={{ __html: postData.contentHtml }}
/>
<div className="my-4">
<Link href="/">
<a className="text-xl font-bold text-gray-600">ā back to home</a>
</Link>
</div>
</article>
</div>
</main>
);
}
export const getStaticPaths: GetStaticPaths = async () => {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
};
export const getStaticProps: GetStaticProps = async ({ params }) => {
const postData = await getPostData(params?.id as string);
return {
props: {
postData,
},
};
};
Perhatikan fungsi di atas:
tampilan post
Sampai disini kita telah berhasil membuat fungsi-fungsi dasar dari sebuah blog. Anda dapat melakukan modifikasi dengan menggunakan tailwindcss untuk mendapatkan tampilan yang Anda inginkan.
Adapun langkah berikutnya adalah melakukan deploy blog kita yang akan dibahas pada artikel berikutnya.
Semoga artikel ini bermanfaat bagi teman-teman yang sedang belajar nextjs.