/

開始使用 Next.js:教學指南

開始使用 Next.js:教學指南

Next.js 是一個非常受歡迎的 Node.js 框架,它可以方便地進行服務器端的 React 渲染,並提供許多其他令人驚喜的功能。

Introduction

在使用由 React 驅動的現代 JavaScript 應用程式時感到很棒,直到你意識到與在客戶端渲染所有內容相關的一些問題。

首先,頁面需要更長的時間才能對用戶顯示,因為在內容加載之前,必須加載所有 JavaScript,然後應用程式需要運行以確定要在頁面上顯示什麼。

其次,如果你正在構建一個公開可用的網站,你將會遇到搜索引擎優化(SEO)問題。搜索引擎越來越善於運行和索引 JavaScript 應用程式,但最好還是能夠將內容發送給它們,而不是讓它們自己解決。

解決這些問題的方法是進行服務器端渲染,也稱為靜態預渲染

Next.js 是一個 React 框架,可以以非常簡單的方式完成所有這些工作,但它並不僅限於此。它被創建者稱為零配置、單命令工具鏈,可用於 React 應用程式。

它提供了一個通用結構,允許你輕鬆構建前端 React 應用程式,並為你提供透明的服務器端渲染能力。

主要功能

以下是一個非詳盡的 Next.js 主要功能清單:

  • 熱加載: 當檢測到任何變更時,Next.js 會重新載入頁面。
  • 自動路由: 任何URL都會映射到文件系統,即放在pages文件夾中的文件,你不需要任何配置(當然你也可以進行自定義配置)。
  • 單文件組件: 使用完全集成的 styled-jsx,Next.js 讓添加與組件相關的樣式變得非常容易。
  • 服務器端渲染: 你可以(可選地)在服務器端渲染 React 組件,在將 HTML 發送給客戶端之前進行渲染。
  • 生態系統相容性: Next.js 與其他 JavaScript、Node 和 React 生態系統相容。
  • 自動代碼拆分: 只渲染頁面所需的庫和 JavaScript,不多不少。
  • 預取資源: Link 組件,用於鏈接不同的頁面,支持 prefetch 屬性,可在後台自動預取頁面資源(包括由於代碼拆分而丟失的代碼)。
  • 動態組件: 你可以動態地引入 JavaScript 模塊和 React 組件 (https://github.com/vercel/next.js#dynamic-import)。
  • 靜態導出: 使用 next export 命令,Next.js 允許你從應用程式導出一個完全靜態的網站。

安裝

Next.js 支持所有主要平台:Linux、macOS、Windows。

使用 npm 輕鬆開始 Next.js 項目:

1
npm install next react react-dom

入門

創建一個包含以下內容的 package.json 文件:

1
2
3
4
5
{
"scripts": {
"dev": "next"
}
}

現在運行以下命令:

1
npm run dev

該腳本將引發錯誤,因為找不到 pages 文件夾。這是 Next.js 運行所需的唯一文件夾。

創建一個空的 pages 文件夾,然後再次運行該命令,Next.js 將在 localhost:3000 上啟動一個服務器。

現在轉到該網址,你將看到一個友好的 404 頁面,並具有漂亮的乾淨設計。

Next.js 返回的 404 頁面

Next.js 還處理其他錯誤類型,例如 500 錯誤。

創建頁面

pages 文件夾中創建一個 index.js 文件,其中包含一個簡單的 React 函數組件:

1
2
3
4
5
export default () => (
<div>
<p>Hello World!</p>
</div>
)

如果你訪問 localhost:3000,將自動渲染此組件。

為什麼這是如此簡單?

Next.js 使用聲明式的頁面結構,其基於文件系統結構。

頁面位於 pages 文件夾中,頁面 URL 由頁面文件名確定。文件系統是頁面 API。

服務器端渲染

在頁面源代碼中打開 檢視 -> 開發人員 -> 查看源代碼(使用 Chrome)。

如你所見,由組件生成的 HTML 直接包含在頁面源碼中。它不是在客戶端渲染,而是在服務器端渲染。

Next.js 團隊希望為開發人員提供一個類似於創建基本 PHP 項目時所獲得的服務器渲染頁面的開發體驗,例如,你只需放置 PHP 文件並調用它們,它們就會以頁面的形式顯示出來。當然,內部實現當然很不同,但易於使用的方式是顯而易見的。

添加第二個頁面

現在,讓我們創建另一個頁面,在 pages/contact.js 中添加以下內容:

1
2
3
4
5
6
7
export default () => (
<div>
<p>
<a href='mailto:[[email protected]](/cdn-cgi/l/email-protection)'>聯繫我們!</a>
</p>
</div>
)

如果你將瀏覽器指向 localhost:3000/contact,將顯示該頁面。可見,該頁面也已進行了服務器端渲染。

熱加載

請注意,在加載第二個頁面時,你無需重新啟動 npm 進程。Next.js 會在內部自動處理此操作。

客戶端渲染

服務器端渲染非常方便,因為它可以加速頁面加載並改善用戶體驗,但在瀏覽網站時,客戶端渲染對於加快頁面加載並提高用戶體驗非常重要。

Next.js 提供了一個 Link 組件,你可以使用它來建立鏈接。試著將上面的兩個頁面連接起來。

index.js 更改為以下代碼:

1
2
3
4
5
6
7
8
9
10
import Link from 'next/link'

export default () => (
<div>
<p>Hello World!</p>
<Link href='/contact'>
<a>聯繫我!</a>
</Link>
</div>
)

現在返回瀏覽器,並點擊此鏈接。你會看到 Contact 頁面立即加載,而不需要刷新頁面。

這是客戶端導航正確工作的結果,完全支持 History API,這意味著你的用戶返回鍵不會失效。

如果你現在 cmd+點擊 驗證鏈接,將以新標簽頁面打開相同的 Contact 頁面,但這次是服務器端渲染。

動態頁面

Next.js 的一個很好的用例是博客,因為這是所有開發人員都熟悉的內容,同時它也很適合作為處理動態頁面的簡單示例。

動態頁面是一個沒有固定內容的頁面,而是基於某些參數顯示某些數據。

index.js 更改為:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Link from 'next/link'

const Post = (props) => (
<li>
<Link href={`/post?title=${props.title}`}>
<a>{props.title}</a>
</Link>
</li>
)

export default () => (
<div>
<h2>我的博客</h2>
<ul>
<li>
<Post title='另一篇文章' />
<Post title='第二篇文章' />
<Post title='Hello, world!' />
</li>
</ul>
</div>
)

這將創建一系列帖子,並將標題查詢參數填入帖子標題中:

帖子列表

現在在 pages 文件夾中創建一個 post.js 文件,並添加以下內容:

1
export default (props) => <h1>{props.url.query.title}</h1>

現在點擊一個帖子,將在 h1 標籤中呈現該帖子的標題:

單篇帖子

你可以使用不帶查詢參數的清晰 URL。Next.js 的 Link 組件通過接受 as 屬性來幫助我們傳遞一個簡略標識:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Link from 'next/link'

const Post = (props) => (
<li>
<Link as={`/${props.slug}`} href={`/post?title=${props.title}`}>
<a>{props.title}</a>
</Link>
</li>
)

export default () => (
<div>
<h2>我的博客</h2>
<ul>
<li>
<Post slug='yet-another-post' title='另一篇文章' />
<Post slug='second-post' title='第二篇文章' />
<Post slug='hello-world' title='Hello, world!' />
</li>
</ul>
</div>
)

CSS-in-JS

Next.js 默認提供對 styled-jsx 的支持,這是由相同開發團隊提供的一種 CSS-in-JS 解決方案,但你也可以使用任何你喜歡的庫,比如 Tailwind CSS。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export default () => (
<div>
<p>
<a href='mailto:[[email protected]](/cdn-cgi/l/email-protection)'>聯繫我們!</a>
<style jsx>{`
p {
font-family: 'Courier New';
}
a {
text-decoration: none;
color: black;
}
a:hover {
opacity: 0.8;
}
`}</style>
</div>
)

樣式僅作用於該組件,但你也可以在 style 元素中添加 global 以編輯全局樣式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default () => (
<div>
<p>
<a href='mailto:[[email protected]](/cdn-cgi/l/email-protection)'>聯繫我們!</a>
</p>
<style jsx global>{`
body {
font-family: 'Benton Sans', 'Helvetica Neue';
margin: 2em;
}
h2 {
font-style: italic;
color: #373fff;
}
`}</style>
</div>
)

導出靜態網站

Next.js 應用程式可以輕鬆導出為靜態網站,並可以在超快的靜態網站主機上部署,例如 Vercel(由致力於 Next.js 開發的同一團隊開發),但也包括 NetlifyCloudflare PagesFirebase Hosting,而無需設置 Node 環境。

部署到 Vercel

如果你的網站不僅僅是一個靜態網站,並且使用 API 路由,我強烈建議使用 Vercel。

Vercel 是 Next.js 背後的公司,並提供專為 Next.js 應用程式量身定制的出色托管服務。

Vercel 是任何網站的理想托管服務,特別是當涉及到 Next.js 時,你可以使用 API 路由作為無服務器函數进行部署。

其他平台(例如 Netlify)也有這種方式可以部署具有 API 路由的 Next.js 應用程式(請參閱 https://docs.netlify.com/integrations/frameworks/next-js/),但在 Vercel 上,Next.js 是一位頂尖公民。

你有自動部署為無服務器函數的 API 路由,並且可以更精細地控制、查看日誌,等等。

如果你使用 Next.js,你一定要試試看 Vercel。

了解更多關於 Next.js

請查看我免費的 Next.js 手冊