最近把博客從 Gatsby 遷移到了 Next.js反症,本文記錄一下使用 Next.js 從 0 到 1 搭建一個博客網(wǎng)站的流程,以及所使用到的一些技術 (npm包)。
Next.js vs Gatsby
Next.js 和 Gatsby 都是 React 生態(tài)內(nèi)比較優(yōu)秀的框架憔购,都追求極致的用戶體驗和開發(fā)體驗嚼蚀。兩者雖然都可以用來搭建博客網(wǎng)站遥倦,但兩者的定位還是有些許不同的献雅。
Gatsby 算是大而全的框架碉考,有自己的插件機制和生態(tài),各種功能都可以通過 npm 安裝對應的插件來快速實現(xiàn)挺身,但使用起來較繁瑣侯谁,概念較多,你需要去了解各種概念和插件的用法章钾;Next.js 屬于小而美(不意味著功能弱)的框架墙贱,有著 Vercel 產(chǎn)品一貫的美感,開箱即用贱傀,沒有太多自創(chuàng)的概念和插件用法惨撇,直接接入 npm 生態(tài)。
初始化項目
關于 Next.js 的使用和如何新建項目窍箍,參考官方文檔就好了串纺,本文不再贅述了丽旅。建議實際上手項目前先大致瀏覽一遍文檔椰棘,從而對 Next.js 有個大致的了解。
使用 TailwindCSS
TailwindCSS 是最近比較流行的一個 CSS 框架榄笙,它提供了大量 Utility-First 的原子類邪狞,幫你快速實現(xiàn)頁面樣式而無需手寫任何 CSS 文件。個人認為 TailwindCSS 有以下幾個有點:
- 快速開發(fā)茅撞,無需手寫 CSS帆卓;
- 可以保證項目整體設計風格的一致性,包括顏色米丘、邊距等剑令;
- 設計風格更靈活、易定制拄查,而不是像 Bootstrap 那樣一眼就能認出你的頁面是不是用的 Bootstrap吁津;
- 不需要再費盡腦汁給 class 起名了;
由于 TailwindCSS 是基于 PostCSS 實現(xiàn)的堕扶,并且 Next.js 默認內(nèi)置了 PostCSS 及一些配置項碍脏,所以在 Next.js 項目中使用時需要自定義 PostCSS 的配置文件。好在修改這些配置并不繁瑣稍算,并且 TailwindCSS 官方文檔提供了在 Next.js 項目中使用的教程典尾,具體參考官方文檔就好了:
- Install Tailwind CSS with Next.js (TailwindCSS 的文檔)
- Customizing PostCSS Config (Next.js 的文檔)
當然你也可以完全不使用 TailwindCSS,Next.js 支持 CSS Modules糊探、Sass/Less钾埂、CSS in JS 等多種方式河闰,可根據(jù)自己的喜好進行選擇。不過強烈建議你嘗試一下 TailwindCSS褥紫,真的很好用淤击。
獲取數(shù)據(jù)
項目搭建好就需要獲取數(shù)據(jù)了,也就是頁面上展示的博客內(nèi)容故源。我沒有使用其他 CMS 來管理這些數(shù)據(jù)污抬,而是直接寫 Markdown 文件,保存在項目的 content
目錄下绳军,然后在項目編譯階段讀取寫這些文件來生成靜態(tài)頁面印机。
Next.js 支持服務端渲染,同時也支持直接導出靜態(tài)文件门驾。
getStaticProps
Next.js 中所有頁面都是默認導出一個 React 組件射赛,如果需要在編譯期間獲取組件所需的數(shù)據(jù),那就再具名導出一個 getStaticProps
函數(shù)奶是,Next.js 會在編譯期間執(zhí)行該函數(shù)楣责,并將函數(shù)返回的數(shù)據(jù)以 props 的形式注入到頁面組件中。
博客中主要是兩個頁面聂沙,一個是首頁秆麸,展示文章列表;一個是文章頁及汉,展示文章具體內(nèi)容沮趣。以首頁為例,代碼大致如下:
export default function Home({ posts }) {
// 省略頁面組件內(nèi)容
}
export async function getStaticProps() {
const posts = getPostList();
return {
props: { posts }
};
}
文章頁同理坷随,在 getStaticProps
中獲取文章詳情即可房铭。
getStaticPaths
文章的數(shù)目不是固定的,所以我們的文章頁本質(zhì)上是一個共用的模板温眉,通過路由來區(qū)分具體展示哪篇文章缸匪,在代碼中,文章頁位于 pages/post/[slug].jsx
类溢,slug 作為路由參數(shù)凌蔬。
但是在編譯期間,Next.js 并不知道你有多少篇文章豌骏,需要生成多少個靜態(tài)頁龟梦。這時候我們就需要用 getStaticPaths
來告訴 Next.js 共有多少個頁面需要生成,同 getStaticProps
一樣窃躲,在頁面文件中具名導出一個 getStaticPaths
函數(shù)就行了计贰。
getStaticPaths
需要返回一個對象數(shù)組,每一條表示一個頁面蒂窒,包含該頁面的一些參數(shù)躁倒,我們這里只需要一個名為 slug
的路由參數(shù)就行了荞怒。具體返回值的格式參考 Next.js 的官方文檔。
文章頁的大致代碼如下:
export default function PostItem({ post }) {
// 省略頁面組件內(nèi)容
}
export async function getStaticProps({ params }) {
const post = await getPostBySlug(params.slug);
return {
props: { post }
};
}
export async function getStaticPaths() {
const slugList = getPostSlugList();
return {
paths: slugList.map((slug) => ({
params: { slug }, // 這個 params 可以在 getStaticProps 的參數(shù)中獲取到
})),
fallback: false,
};
}
Markdown 解析
文章是以純文本的形式保存的秧秉,上述偽代碼中的 getPostList
褐桌、getPostBySlug
等函數(shù)是讀取文件并解析后返回一定格式的對象。讀取文件是通過 Node.js 的 fs 模塊實現(xiàn)的象迎,沒什么好說的荧嵌。
文章的 Markdown 文件格式如下:
---
title: 文章標題
date: 2021-01-31 12:01:54
---
這里是 Markdown 格式的文章內(nèi)容
可以看到上面是 yaml 格式的 Front Matter,用來寫一些文章信息砾淌,標題啦撮、日期等,都可以根據(jù)自己喜好來自定汪厨;下面是 Markdown 格式的文章內(nèi)容赃春。
這里用到兩個 npm 包來解析 Markdown 文件:
- 使用 gray-matter 把 Front Matter 和文章內(nèi)容分離,并將 Front Matter 解析為 JS 對象劫乱;
- 使用 remark 將上一步分離出的文章內(nèi)容解析為 HTML 格式织中,使用 remark 時需要用到多個相關插件,稍微麻煩了一點衷戈;
使用 remark 時狭吼,可以使用 remark-prism 實現(xiàn)代碼高亮,記得在文章頁導入一個 prism 的主題 CSS 文件脱惰,不然文章中插入的代碼沒有高亮搏嗡。
其他
頁面布局
博客所有頁面的布局都是統(tǒng)一的,比如頂部導航和底部版權信息在所有頁面都顯示拉一,在每個頁面都寫一遍肯定是不現(xiàn)實的,這時候就可以通過自定義 App 來實現(xiàn)統(tǒng)一的布局旧乞,在 pages
目錄下新建一個 _app.jsx
即可蔚润。具體參考官方文檔或本項目源碼。
Google Analytics
博客使用 Google Analytics 來做訪問統(tǒng)計尺栖,按照 Google 的文檔提示嫡纠,需要在所有頁面的 head
標簽中插入兩個 script
標簽。_app.jsx
是用來自定義 body
標簽內(nèi)的內(nèi)容的延赌,顯然不適合用它來實現(xiàn)除盏,這時候就可以通過自定義 Document 來實現(xiàn)這個需求了。具體參考官方文檔或本項目源碼挫以。
部署
Next.js 是由 Vercel 開發(fā)的者蠕,所以把項目部署到 Vercel 再合適不過了,而且很簡單掐松、很方便踱侣,并且對個人用戶有一定的免費額度粪小,對于個人博客來說完全足夠了。
首先把代碼上傳到 GitHub抡句,然后在 Vercel 新建一個項目探膊,授權并選擇對應的代碼倉庫后,它就會自動拉取代碼并部署了待榔,并且在代碼有更新時自動進行重新部署逞壁。
參考鏈接
- 本博客源碼倉庫
- Install Tailwind CSS with Next.js
- Customizing PostCSS Config
- Data Fetching
- Next.js 官方文檔
- TailwindCSS 官方文檔
- gray-matter
- remark
- Prism
- Next.js on Vercel
原文地址:使用 Next.js 搭建個人博客