動(dòng)手練一練,使用 React 和 Next.js 做一個(gè)簡單的博客網(wǎng)站(上)

作者:Craig Bucklere
原文:Build a Blog with React and Next.js(sitepoint)
字?jǐn)?shù):3713 字 (非直譯,有添加部分)
閱讀: 8分鐘
開篇語
大家好,如果要做一個(gè)博客網(wǎng)站,你會選擇什么前端技術(shù)呢?本篇文章,我將和大家一起使用 React 和 Next.js 技術(shù)從0到1創(chuàng)建一個(gè)博客網(wǎng)站,通過本案例,你將會學(xué)習(xí)到 Next.js 的以下內(nèi)容:
如何創(chuàng)建一個(gè)基本的頁面 如何通過已有的 Markdown 文檔生成現(xiàn)有網(wǎng)站的內(nèi)容 靜態(tài)頁面導(dǎo)出(static generation) 如何使用服務(wù)端渲染技術(shù)(server-side rendering) 客戶端激活 (暫且這么翻譯,client-side hydration) 編譯、構(gòu)建博客網(wǎng)站
一、什么是Next.js?
Next.js是一個(gè)基于 React 的應(yīng)用框架,使用它可以快速上手開發(fā) React 應(yīng)用,而不是先花很多時(shí)間和精力去折騰各種開發(fā)工具,除了以上特點(diǎn),使用其構(gòu)建網(wǎng)站還有以下特點(diǎn):
在某些情況下,可以使用SSG(Static Site Generation)技術(shù)生成靜態(tài)網(wǎng)站,如果網(wǎng)站頁面數(shù)據(jù)都可以預(yù)先確定,不需要在運(yùn)行時(shí)再從其它地方獲取內(nèi)容,那么甚至可以將整個(gè) NextJS 應(yīng)用導(dǎo)出為一個(gè)靜態(tài)網(wǎng)站。 Next.Js 將每個(gè)頁面單獨(dú)打包,打開首頁時(shí)會加載應(yīng)用基礎(chǔ)代碼和首頁代碼,其它頁面代碼只會在打開時(shí)才去加載,這對于大型應(yīng)用來說非常有用。并且 NextJS 還支持頁面預(yù)加載,在鏈接頁面時(shí)可以選擇是否在打開本頁時(shí)就預(yù)先獲取被鏈接頁面的代碼,這樣打開鏈接時(shí)就不需要再發(fā)送網(wǎng)絡(luò)請求,直接渲染! Next.js 同時(shí)提供 SSR 技術(shù)渲染頁面,在服務(wù)器上運(yùn)行頁面邏輯和呈現(xiàn)可以避免向客戶端發(fā)送大量JavaScript,這有助于實(shí)現(xiàn)快速的交互時(shí)間 (TTI);同時(shí)利用搜索引擎(SEO)優(yōu)化,搜索引擎來抓取頁面的時(shí)候,服務(wù)端會返回生成好的 HTML 內(nèi)容,因此網(wǎng)站內(nèi)容能夠被收錄,這一點(diǎn)對做內(nèi)容的博客網(wǎng)站至關(guān)重要。
二、本案例展示
如下視頻展示,我們基于現(xiàn)有的 Markdown 文件生成博客內(nèi)容,并且在博客列表頁面顯示所有的文件列表,同時(shí)支持黑暗模式預(yù)覽。
三、初始項(xiàng)目,安裝 Next.js 和 React
雖然 Next.js 提供 create-next-app 工具來快速創(chuàng)建 Next.js 項(xiàng)目,但是對于一個(gè)簡單的博客網(wǎng)站,我覺得沒有必要,因?yàn)槲覀兪止ひ瞥?xiàng)目中不必要的依賴就要花不少時(shí)間,我們還是從一個(gè)文件夾開始創(chuàng)建一個(gè)空項(xiàng)目吧!
1、首先像常規(guī)的 Node 項(xiàng)目一樣,創(chuàng)建一個(gè)文件夾和初始化一個(gè) package.json 文件,打開控制臺,輸入以下命令腳本:
mkdir mysite
cd mysite
npm init
2、接下來安裝 Next.js 和 React 依賴
npm i --save next react react-dom
3、腳本運(yùn)行完成后,你的 package.json 也許會這樣(版本號也許會有差異性):
{
"name": "前端達(dá)人的博客網(wǎng)站",
"version": "1.0.0",
"description": "A basic site and blog powered by Next.js.",
"main": "index.js",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"author": "阿森",
"license": "MIT",
"dependencies": {
"next": "^10.0.0",
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}
四、創(chuàng)建首頁
Next.js 具有文件路由的功能,任何創(chuàng)建在 pages 文件下的 React 的組件文件都會被渲染成頁面,我們可以在瀏覽器輸入文件名前綴可以直接訪問(index.js 文件除外,輸入 / 進(jìn)行訪問),比如我們在 pages 目錄下創(chuàng)建了 about.js 文件,我們在瀏覽器里輸入 /about 就可以直接訪問。
我們使用JSX語法,在pages目錄下創(chuàng)建 index.js 文件,示例代碼如下:
export default function Home() {
return (
<>
<h1>Next.js starter site</h1>
<p>This is a demonstration blog using <a href="https://nextjs.org/">Next.js</a>.</p>
</>
);
}
是不是想預(yù)覽下頁面效果呢,在控制臺輸入 npm run dev(或者npx next dev) 命令,然后在瀏覽器里輸入 http:// localhost:3000/ 就可以預(yù)覽頁面。

接下來你可以pages目錄下創(chuàng)建簡單的頁面進(jìn)行嘗試,路由將會根據(jù)文件名動(dòng)態(tài)生成,比如:
pages/index.js 對應(yīng)根路徑 / pages/contact.js 對應(yīng)頁面路徑: /contact pages/about.js 對應(yīng)頁面路徑:/about pages/about/privacy.js 對應(yīng)頁面路徑 /about/privacy
五、添加頁面鏈接
在 Next.js 項(xiàng)目里你可以使用 a 標(biāo)簽實(shí)現(xiàn)頁面之間的跳轉(zhuǎn)功能,但是會導(dǎo)致瀏覽器整個(gè)頁面的刷新。除此之外,你還可以引用 Link 組件實(shí)現(xiàn)頁面的跳轉(zhuǎn),Next.js 會以局部渲染的方式進(jìn)行刷新,示例代碼如下:
import Link from 'next/link';
export default function Home() {
return (
<>
<h1>Next.js starter site</h1>
<p>This is a demonstration blog using <a href="https://nextjs.org/">Next.js</a>.</p>
<p>Find out more <Link href="/about"><a>about us...</a></Link></p>
</>
);
}
當(dāng)點(diǎn)擊 /about 鏈接時(shí),Next.js 會以 Ajax 的方式加載內(nèi)容一次,并緩存起來,并在頁面中呈現(xiàn)它。
六、添加頁面標(biāo)題和描述
接下來我們要為每個(gè)頁面添加個(gè)性化的標(biāo)題和meta描述呢,我們可以使用 <Head> 組件,示例代碼如下:
import Head from 'next/head';
import Link from 'next/link';
export default function Home() {
return (
<>
<Head>
<title>Next.js starter site</title>
<meta
name="description"
content="An example Next.js site."
/>
</Head>
<h1>Next.js starter site</h1>
<p>This is a demonstration blog using <a href="https://nextjs.org/">Next.js</a>.</p>
<p>Find out more <Link href="/about"><a>about us...</a></Link></p>
</>
);
}
七、添加靜態(tài)資源文件夾
做博客網(wǎng)站自然少不了漂亮的圖片,我們新建一個(gè) public 文件夾,用于放置一些靜態(tài)資源,比如 icons、robots.txt、圖片等。我們通常會在其目錄下新建個(gè) images目錄,放置博客的圖片,在頁面里,我們可以使用 "/images/圖片名" 路徑引用圖片。
八、創(chuàng)建頁面模板
一個(gè)網(wǎng)站,比如頁面的頭部、底部大部分都是一樣的,因此我們需要把這些公共部分抽離出來,Next.js 可以使用React的方式進(jìn)行創(chuàng)建。
1、接下來我們在根目錄創(chuàng)建 components 文件夾,然后創(chuàng)建 layouts.js 文件,定義
import Header from './header';
import Footer from './footer';
export default function Layout({ children, hero }) {
return (
<>
<Header hero={ hero } />
<main>{ children }</main>
<Footer />
</>
);
children 大家一定不會陌生,在其他頁面引入
2、繼續(xù)在 components 目錄下創(chuàng)建 header.js 文件,組件里包含了首頁鏈接、博客LOGO及橫幅大圖,示例代碼如下:
import Link from 'next/link';
export default function Header({ hero }) {
hero = '/images/' + (hero || 'orb.jpg');
return (
<header>
<p className="logo">
<Link href="/"><a>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="50" height="50">
<path d="M10.394 2.08a1 1 0 00-.788 0l-7 3a1 1 0 000 1.84L5.25 8.051a.999.999 0 01.356-.257l4-1.714a1 1 0 11.788 1.838L7.667 9.088l1.94.831a1 1 0 00.787 0l7-3a1 1 0 000-1.838l-7-3zM3.31 9.397L5 10.12v4.102a8.969 8.969 0 00-1.05-.174 1 1 0 01-.89-.89 11.115 11.115 0 01.25-3.762zM9.3 16.573A9.026 9.026 0 007 14.935v-3.957l1.818.78a3 3 0 002.364 0l5.508-2.361a11.026 11.026 0 01.25 3.762 1 1 0 01-.89.89 8.968 8.968 0 00-5.35 2.524 1 1 0 01-1.4 0zM6 18a1 1 0 001-1v-2.065a8.935 8.935 0 00-2-.712V17a1 1 0 001 1z"></path>
</svg>
Next.js starter
</a></Link>
</p>
<figure>
<img src={ hero } width="400" height="300" alt="decoration" />
</figure>
</header>
);
}
3、繼續(xù)創(chuàng)建底部組件,在 components 目錄下創(chuàng)建 footer.js 文件,包含了一個(gè) Github 的鏈接和圖標(biāo),示例代碼如下:
export default function Footer() {
return (
<footer>
<p className="github">
<a href="https://github.com/sitepoint-editors/nextjs-starter">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="50" height="50">
<path d="M256 32C132.3 32 32 134.9 32 261.7a229.3 229.3 0 00153.2 217.9 17.6 17.6 0 003.8.4c8.3 0 11.5-6.1 11.5-11.4l-.3-39.1a102.4 102.4 0 01-22.6 2.7c-43.1 0-52.9-33.5-52.9-33.5-10.2-26.5-24.9-33.6-24.9-33.6-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8 11.2 19.6 26.2 25.1 39.6 25.1a63 63 0 0025.6-6c2-14.8 7.8-24.9 14.2-30.7-49.7-5.8-102-25.5-102-113.5 0-25.1 8.7-45.6 23-61.6a84.6 84.6 0 012.2-60.8 18.6 18.6 0 015-.5c8.1 0 26.4 3.1 56.6 24.1a208.2 208.2 0 01112.2 0c30.2-21 48.5-24.1 56.6-24.1a18.6 18.6 0 015 .5 84.6 84.6 0 012.2 60.8 90.3 90.3 0 0123 61.6c0 88.2-52.4 107.6-102.3 113.3 8 7.1 15.2 21.1 15.2 42.5 0 30.7-.3 55.5-.3 63 0 5.4 3.1 11.5 11.4 11.5a19.4 19.4 0 004-.4A229.2 229.2 0 00480 261.7C480 134.9 379.7 32 256 32z"/>
</svg>
https://github.com/sitepoint-editors/nextjs-starter
</a>
</p>
</footer>
);
}
4、接下來我們來更新首頁的代碼(pages/index.js),引入
import Layout from '../components/layout';
import Head from 'next/head';
import Link from 'next/link';
export default function Home() {
return (
<Layout>
<Head>
<title>Next.js starter site</title>
</Head>
<h1>Next.js starter site</h1>
<p>This is a demonstration blog using <a href="https://nextjs.org/">Next.js</a>.</p>
<p>Find out more <Link href="/about"><a>about us...</a></Link></p>
</Layout>
);
}
5、最后我們用同樣的方式更新 pages/about.js 文件,稍微不同的是,我們通過 hero 屬性更改橫幅大圖。
import Layout from '../components/layout';
import Head from 'next/head';
export default function Home() {
return (
<Layout hero="keyboard.jpg">
<Head>
<title>About us</title>
</Head>
<h1>About us</h1>
<p>Some information about us.</p>
</Layout>
);
最后,重新運(yùn)行 npm run dev 命令重啟網(wǎng)站,一切正常的話,在瀏覽器輸入http://localhost:3000/ ,你將會看到如下效果。

未完待續(xù)
今天的案例就介紹到這里,想必大家對 Next.js 已有一個(gè)初步的認(rèn)識,下一篇文章我們將一起學(xué)習(xí)基于現(xiàn)有的 MarkDown 文章生成動(dòng)態(tài)路由和靜態(tài)頁面生成器的知識(Static Generation),同時(shí)為博客網(wǎng)站添加上漂亮的樣式,敬請大家期待...
