contentlayer 参考使用


当前contentlayer 主要支持next,以下是使用next 的试用

创建项目

  • 创建next 项目
npx create-next-app contentlayer-demo
  • 安装contentlayer
cd contentlayer-demo
yarn add contentlayer next-contentlayer  date-fns
  • 项目配置
    包含了next 以及ts
    next 配置 next.config.js
 
/** @type {import('next').NextConfig} */
const { withContentlayer } = require('next-contentlayer')
 
module.exports = withContentlayer({
  reactStrictMode: true,
})

contentlayer.config.js

import { defineDocumentType, makeSource } from 'contentlayer/source-files'
 
export const Post = defineDocumentType(() => ({
  name: 'Post',
  filePathPattern: `**/*.md`,
  fields: {
    title: {
      type: 'string',
      description: 'The title of the post',
      required: true,
    },
    date: {
      type: 'date',
      description: 'The date of the post',
      required: true,
    },
  },
  computedFields: {
    url: {
      type: 'string',
      resolve: (post) => `/posts/${post._raw.flattenedPath}`,
    },
  },
}))
 
export default makeSource({
  contentDirPath: 'posts',
  documentTypes: [Post],
})
  • 创建md文件
    参考结构


post 路由定义
[slug].js

 
import Head from 'next/head'
import Link from 'next/link'
import { format, parseISO } from 'date-fns'
import { allPosts } from '../../.contentlayer/generated'
 
export async function getStaticPaths() {
  const paths = allPosts.map((post) => post.url)
  return {
    paths,
    fallback: false,
  }
}
 
export async function getStaticProps({ params }) {
  const post = allPosts.find((post) => post._raw.flattenedPath === params.slug)
  return {
    props: {
      post,
    },
  }
}
 
const PostLayout = ({ post }) => {
  return (
    <>
      <Head>
        <title>{post.title}</title>
      </Head>
      <article className="mx-auto max-w-2xl py-16">
        <div className="mb-6 text-center">
          <Link href="/">
            <a className="text-center text-sm font-bold uppercase text-blue-700">Home</a>
          </Link>
        </div>
        <div className="mb-6 text-center">
          <h1 className="mb-1 text-3xl font-bold">{post.title}</h1>
          <time dateTime={post.date} className="text-sm text-slate-600">
            {format(parseISO(post.date), 'LLLL d, yyyy')}
          </time>
        </div>
        <div className="cl-post-body" dangerouslySetInnerHTML={{ __html: post.body.html }} />
      </article>
    </>
  )
}
 
export default PostLayout

index.js 定义

import Head from 'next/head'
import Link from "next/link"
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { compareDesc, format, parseISO } from 'date-fns'
import { allPosts } from '../.contentlayer/generated'
 
export async function getStaticProps() {
  const posts = allPosts.sort((a, b) => {
    return compareDesc(new Date(a.date), new Date(b.date))
  })
  return { props: { posts } }
}
 
function PostCard(post) {
  return (
    <div className="mb-6">
      <time dateTime={post.date} className="block text-sm text-slate-600">
        {format(parseISO(post.date), 'LLLL d, yyyy')}
      </time>
      <h2 className="text-lg">
        <Link href={post.url}>
          <a className="text-blue-700 hover:text-blue-900">{post.title}</a>
        </Link>
      </h2>
    </div>
  )
}
 
export default function Home({ posts }) {
  return (
    <div className="mx-auto max-w-2xl py-16 text-center">
      <Head>
        <title>Contentlayer Blog Example</title>
      </Head>
 
      <h1 className="mb-8 text-3xl font-bold">Contentlayer Blog Example</h1>
 
      {posts.map((post, idx) => (
        <PostCard key={idx} {...post} />
      ))}
    </div>
  )
}

启动&效果

  • 启动
yarn dev
  • 效果


说明

官方文档的一些内容与实际是有差异的,但是通过此可以整体的体验下contentlayer的优势

参考资料

https://www.contentlayer.dev/docs/getting-started