应用 Next.js 搭建集体博客

现阶段有十分十分多的动态博客生成工具(site generators),Hexo、VuePress、Docusaurus 等等,根本只需把 markdown 文件配置到指定目录,无需编写其余代码即可建站。

本文记录一下应用 next.js 从 0 到 1 搭建一个博客网站的流程。

初始化我的项目

应用 blog-starter-typescript 作为模板创立一个我的项目

npx create-next-app my-blog --use-yarn --example "https://github.com/vercel/next.js/tree/canary/examples/blog-starter-typescript"

模版 example 是个大仓库,蕴含了 next.js 与各种技术集成的样例

目录构造

.├── @types├── README.md├── _posts # 博客 .md 文件│   ├── dynamic-routing.md│   ├── hello-world.md│   └── preview.md├── components├── lib # 解析 .md 文件,提取文章数据│   ├── api.ts│   ├── constants.ts│   └── markdownToHtml.ts├── next-env.d.ts├── package.json├── pages # blog 各个页面│   ├── _app.tsx # 自定义初始化页面│   ├── _document.tsx #自定义 html body│   ├── index.tsx│   └── posts├── postcss.config.js├── public├── styles├── tailwind.config.js├── tsconfig.json└── types

模版是简略的 blog 样例,蕴含读取解析 markdown 文件、加载文章数据、生成首页、生成 blog 文章页面。

用到的 npm 包:

  • gray-matter 解决 yaml front matter
  • remark 解析 markdown,把 markdown 转成 ast
  • remark-html 把 ast 转成 html
  • tailwindcss 原子化款式 class,无需头疼组件 class 的命名

生成页面

生成的页面对应 pages 目录下的文件,页面的路由为文件路径名,例如 pages/about.tsx ,则页面路由为 /about

个别我的项目的目录都会有 src 目录,所以 next.js 也反对 src/pages 目录。

很显著,不可能为每篇 blog 文章都创立一个文件,那么就需用到动静路由(dynamic routes)

getStaticPaths

动静路由形如 pages/posts/[slug].tsx,而后就会生成 posts/1, posts/2,slug 能够了解为前端路由的门路参数 params。

页面需定义 getStaticPaths 办法,必须返回 params 参数。

// pages/posts/[slug].tsxconst Post = () => {...}export default Postexport async function getStaticPaths() {  const posts = getAllPosts(['slug'])  return {    paths: posts.map((post) => {      return {        params: {          slug: post.slug,        },      }    }),  }}

获取数据

getStaticProps

getStaticProps 会在服务端执行,因而能够应用 node api,读取文件系统,获取 markdown 内容。

返回值会作为页面组件的 props,入参为 getStaticPaths的返回值。

const Post = ({ post, morePosts }: Props) => {  return <Layout>...</Layout>;};export default Post;export async function getStaticProps({ params }) {  const post = getPostBySlug();  const content = await markdownToHtml(post.content || '');  return {    props: {      post: {        ...post,        content,      },    },  };}

定制化

在 pages 下还有 _app.tsx_document.tsx,这两个文件用于定制化页面。

next.js 默认应用 next/app 初始化页面,_app.tsx会代替next/app初始化页面,因而能够在 _app.tsx放一些公共逻辑,公共的布局,导入款式等。

import { AppProps } from 'next/app';import 'github-markdown-css/github-markdown-light.css';import '../styles/index.css';import Layout from '@/layout';export default function MyApp({ Component, pageProps }: AppProps) {  return (    <Layout>      <Component {...pageProps} />    </Layout>  );}

同样,_document.tsx 用于为 html、body 做定制化

import { Html, Head, Main, NextScript } from 'next/document';// 必须导入 Html、Head、Main、NextScript,不能省略export default function Document() {  return (    <Html>      <Head />      <body>        <Main />        <NextScript />      </body>    </Html>  );}

结语

一个 blog 的原型根本就搭建起来了,残余就是部署到动态托管服务上(Vercel、GitHub Page 等),另外能够参照 example,与其余技术集成,持续丑化 blog。

参考链接

  • Next.js 官网文档
  • 学习 Next.js