使用 Next.js 搭建個人博客

最近把博客從 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 項目中使用的教程典尾,具體參考官方文檔就好了:

當然你也可以完全不使用 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 新建一個項目探膊,授權并選擇對應的代碼倉庫后,它就會自動拉取代碼并部署了待榔,并且在代碼有更新時自動進行重新部署逞壁。

參考鏈接

原文地址:使用 Next.js 搭建個人博客

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锐锣,隨后出現(xiàn)的幾起案子猾担,更是在濱河造成了極大的恐慌,老刑警劉巖刺下,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绑嘹,死亡現(xiàn)場離奇詭異,居然都是意外死亡橘茉,警方通過查閱死者的電腦和手機工腋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來畅卓,“玉大人擅腰,你說我怎么就攤上這事∥膛耍” “怎么了趁冈?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拜马。 經(jīng)常有香客問我渗勘,道長,這世上最難降的妖魔是什么俩莽? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任旺坠,我火速辦了婚禮,結果婚禮上扮超,老公的妹妹穿的比我還像新娘取刃。我一直安慰自己,他們只是感情好出刷,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布璧疗。 她就那樣靜靜地躺著,像睡著了一般馁龟。 火紅的嫁衣襯著肌膚如雪崩侠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天屁柏,我揣著相機與錄音啦膜,去河邊找鬼有送。 笑死,一個胖子當著我的面吹牛僧家,可吹牛的內(nèi)容都是我干的雀摘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼八拱,長吁一口氣:“原來是場噩夢啊……” “哼阵赠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肌稻,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤清蚀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后爹谭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枷邪,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年诺凡,在試婚紗的時候發(fā)現(xiàn)自己被綠了东揣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡腹泌,死狀恐怖嘶卧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凉袱,我是刑警寧澤芥吟,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站专甩,受9級特大地震影響钟鸵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜配深,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一携添、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧篓叶,春花似錦、人聲如沸羞秤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘾蛋。三九已至俐镐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哺哼,已是汗流浹背佩抹。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工叼风, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棍苹。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓无宿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枢里。 傳聞我的和親對象是個殘疾皇子孽鸡,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容