<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于 Next.js 的 SSR/SSG 方案

          共 9581字,需瀏覽 20分鐘

           ·

          2022-01-02 05:47

          最近在探索學(xué)習(xí)前端工程化相關(guān)內(nèi)容,在如今前后端分離的架構(gòu)下,為了提升首屏渲染速度和 SEO 效果,兜兜轉(zhuǎn)轉(zhuǎn),又回到了服務(wù)端渲染。

          本文主要是講講如何使用 Next.js 框架實(shí)現(xiàn)服務(wù)端渲染,將有效提升網(wǎng)頁(yè)的 SEO 和首屏渲染速度,說(shuō)不定哪天就用上了,是吧!

          一、服務(wù)端渲染(SSR)

          服務(wù)端渲染(SSR,Server Side Render)與客戶(hù)端渲染(CSR,Client Side Render)的核心區(qū)分點(diǎn)簡(jiǎn)單來(lái)說(shuō)就是完整的 HTML 文檔在服務(wù)端還是瀏覽器里組裝完成。

          SSR 的另一概念是同構(gòu)渲染,可以看看知乎中的討論:什么是前端的同構(gòu)渲染?[1]

          同構(gòu)渲染簡(jiǎn)單來(lái)說(shuō)就是一份代碼,服務(wù)端先通過(guò)服務(wù)端渲染(SSR),生成 HTML 以及初始化數(shù)據(jù),客戶(hù)端拿到代碼和初始化數(shù)據(jù)后,通過(guò)對(duì) HTML 的 DOM 進(jìn)行 patch 和事件綁定對(duì) DOM 進(jìn)行客戶(hù)端激活(client-side hydration),該整體過(guò)程叫同構(gòu)渲染。

          SSR 的原理,本文就不再贅述了,感興趣的朋友推薦閱讀這篇文章:《徹底理解服務(wù)端渲染 - SSR原理》

          二、Next.js

          Next.js[2] 是一款用于生產(chǎn)環(huán)境的 React 框架,無(wú)需配置,默認(rèn)提供了生產(chǎn)環(huán)境所需所有功能的最佳開(kāi)發(fā)實(shí)踐:支持靜態(tài)渲染和服務(wù)端渲染、支持 TypeScript、智能打包、路由預(yù)加載等功能。

          與此同時(shí),Next.js 還提供了如下開(kāi)箱即用的 SDK 輔助開(kāi)發(fā) Web 應(yīng)用:

          閱讀過(guò) SSR 原理一文可看到配置支持服務(wù)端渲染還是挺麻煩的,但借助 Next.js,可以很輕松的上手改造支持現(xiàn)有 Web 應(yīng)用服務(wù)端渲染。

          是否采用服務(wù)端渲染還得綜合考慮收益,服務(wù)端渲染畢竟會(huì)增加服務(wù)器的計(jì)算開(kāi)銷(xiāo),穩(wěn)定性相較于 CSR 差一些。

          三、創(chuàng)建 Next.js 應(yīng)用

          初始化一個(gè) Next.js 應(yīng)用可以直接通過(guò)腳手架快速完成:

          npx?create-next-app@latest?--ts
          #?or
          yarn?create?next-app?--typescript

          中途會(huì)要求輸入項(xiàng)目名,并自動(dòng)安裝所需的模塊

          執(zhí)行 yarn dev 后需要手動(dòng)再瀏覽器打開(kāi)網(wǎng)址:http://localhost:3000 ,即可看到如下頁(yè)面:

          首頁(yè)的內(nèi)容對(duì)應(yīng) ./pages/index.tsx 文件

          初始的目錄結(jié)構(gòu)如下:

          .
          ├──?pages?//?采用約定式路由(文件系統(tǒng)路由)
          │???├──?_app.tsx
          │???├──?api?//?API?目錄
          |??????├──?hello.ts
          │???└──?index.tsx?//?首頁(yè)
          ├──?public?//?公共資源
          │???├──?favicon.ico
          │???└──?vercel.svg
          ├──?styles?//?樣式
          │???├──?Home.module.css
          │???└──?globals.css
          ├──?next-env.d.ts?//?Next?相關(guān)的?TS?定義
          ├──?next.config.js?//?Next.js?自定義配置
          ├──?node_modules
          ├──?package.json
          ├──?tsconfig.json
          ├──?README.md
          └──?yarn.lock

          四、頁(yè)面路由

          通常我們的 Web 應(yīng)用是多頁(yè)面、多路由的,因此會(huì)涉及到在各個(gè)頁(yè)面之間跳轉(zhuǎn),因此有必要熟悉 Next.js 的路由使用方式。

          上述講到了 Next.js 是約定式路由,基于文件系統(tǒng),對(duì)應(yīng)到 ./pages 目錄下,當(dāng)添加頁(yè)面文件到 ./pages 目錄,Next.js 會(huì)自動(dòng)識(shí)別并將對(duì)應(yīng)文件注冊(cè)的路由上

          4.1 索引路由

          Next.js 會(huì)自動(dòng)將文件夾內(nèi)的 “index” 文件注冊(cè)為文件夾的主頁(yè)

          文件路徑對(duì)應(yīng)路由
          pages/index.tsx/
          pages/blog/index.tsx/blog

          4.2 嵌套路由

          Next.js 支持嵌套文件的路由,如果您創(chuàng)建嵌套文件夾結(jié)構(gòu),文件仍將自動(dòng)以相同方式路由解析。

          文件路徑對(duì)應(yīng)路由
          pages/blog/first-post.tsx/blog/first-post
          pages/dashboard/settings/username.tsx/dashboard/settings/username

          4.3 動(dòng)態(tài)參數(shù)路由

          常見(jiàn)于比如博客的文章詳情頁(yè)面,文章的 id 是動(dòng)態(tài)變化的,Next.js 中可以使用中括號(hào)解析到對(duì)應(yīng)的命名參數(shù)

          文件路徑對(duì)應(yīng)路由??
          pages/blog/[slug].js/blog/:slug/blog/hello-world
          pages/[username]/settings.js/:username/settings/foo/settings
          pages/post/[...all].js/post/*/post/2021/id/title

          更多關(guān)于動(dòng)態(tài)路由的解析可參閱:https://nextjs.org/docs/routing/dynamic-routes

          4.4 路由跳轉(zhuǎn)

          之前有提到 Next.js 中的路由預(yù)加載功能,需借助 Next.js 提供的 next/link,寫(xiě)法如下:

          <Link?href="/blog/hello-world">
          ??<a>第一篇文章a>
          Link>

          應(yīng)用頁(yè)面之間的跳轉(zhuǎn),可以用 標(biāo)簽包裹。

          屬性 href 的值是跳轉(zhuǎn)頁(yè)面的路徑字符串或 URL 對(duì)象:

          import?Link?from?'next/link'

          function?Articles({?articles?})?{
          ??return?(
          ????<ul>
          ??????{articles.map((article)?=>?(
          ????????<li?key={article.id}>
          ??????????<Link
          ????????????href={{
          ??????????????pathname:?'/article/[slug]',
          ??????????????query:?{?slug:?article.slug?},
          ????????????}}
          ??????????>

          ????????????<a>{article.title}a>

          ??????????Link>
          ????????li>
          ??????))}
          ????ul>
          ??)
          }

          export?default?Articles

          如有需要對(duì)路由通過(guò) js 跳轉(zhuǎn),則可以通過(guò) Next.js 提供的 next/router[3] 中的 useRouter[4] Hook。

          4.5 代碼拆分和預(yù)加載

          通過(guò) Next.js 的路由功能,可以自動(dòng)完成頁(yè)面按需加載當(dāng)前頁(yè)面所需的代碼,同時(shí)會(huì)自動(dòng)預(yù)加載頁(yè)面中屬于自身應(yīng)用的鏈接。

          這意味著在呈現(xiàn)主頁(yè)時(shí),最初不會(huì)提供其他頁(yè)面的代碼,同時(shí)可確保即使您有數(shù)百個(gè)頁(yè)面,主頁(yè)也能按需快速加載。

          僅加載您請(qǐng)求的頁(yè)面的代碼也意味著頁(yè)面變得獨(dú)立,如果某個(gè)頁(yè)面拋出錯(cuò)誤,應(yīng)用程序的其余部分仍然可以工作。

          在 Next.js 的生產(chǎn)版本中,每當(dāng) Link 組件出現(xiàn)在瀏覽器的視口中時(shí),Next.js 都會(huì)在后臺(tái)自動(dòng)預(yù)取鏈接頁(yè)面的代碼。當(dāng)您單擊鏈接時(shí),目標(biāo)頁(yè)面的代碼已在后臺(tái)加載,頁(yè)面轉(zhuǎn)換將近乎即時(shí)。

          五、靜態(tài)資源

          所有靜態(tài)資源都可以放到 ./public 目錄下,Next.js 會(huì)自動(dòng)為其中的文件注冊(cè)路由,按照文件系統(tǒng)的方式,與 Page 的路由類(lèi)似。

          5.1 圖片元素

          一般網(wǎng)頁(yè)中的圖片寫(xiě)法如下:

          <img?src="/images/logo.png"?alt="logo"?/>

          但這種寫(xiě)法會(huì)需要開(kāi)發(fā)者手動(dòng)去優(yōu)化,比如按需加載、錯(cuò)誤處理等。

          Next.js 考慮到這點(diǎn),為了減輕開(kāi)發(fā)者負(fù)擔(dān),于是提供了 next/image[5],開(kāi)箱即用。

          這里其實(shí)可以借鑒一下,別的項(xiàng)目中為了業(yè)務(wù)統(tǒng)一處理圖片,可以封裝一個(gè) Image 組件,提升研發(fā)效率。

          import?Image?from?'next/image'

          const?YourComponent?=?()?=>?(
          ??<Image
          ????src="/images/profile.jpg"?//?圖片文件路徑
          ????height={144}?//?具有正確縱橫比的所需尺寸
          ????width={144}
          ????alt="Image?Alt"
          ??/>

          )

          export?default?YourComponent;

          5.2 Meta 數(shù)據(jù)

          網(wǎng)頁(yè)的 Meta 數(shù)據(jù),也就是在 html->head 標(biāo)簽中的內(nèi)容

          Next.js 提供了 next/head[6] 用于聲明式編寫(xiě)網(wǎng)頁(yè)的 head 內(nèi)容。

          import?Link?from?'next/link'
          import?Head?from?'next/head'

          export?default?function?FirstPost()?{
          ??return?(
          ????<>
          ??????<Head>
          ????????<meta?charset="UTF-8"?/>
          ????????<title>First?Posttitle>

          ????????<link?rel="shortcut?icon"?href="/favicon.ico"?/>
          ????????<meta?name="keywords"?content="網(wǎng)頁(yè)關(guān)鍵詞"?/>
          ????????<meta?name="description"?content="網(wǎng)頁(yè)描述"?/>
          ????????<meta?name="author"?content="DYBOY,[email protected]"?/>
          ????????<meta?name="version"?content="1.0"?/>
          ????????<link?rel="stylesheet"?href="http://at.alicdn.com/t/font_2319527_hng3o947ocv.css"?/>
          ????????<link?rel="stylesheet"?href="/style/fancybox.css"?/>
          ????????<link?rel="stylesheet"?href="/style/app.css"?/>
          ????????<script?src="/scripts/jquery.js">script>
          ??????Head>
          ??????<h1>First?Posth1>
          ??????<h2>
          ????????<Link?href="/">
          ??????????<a>Back?to?homea>
          ????????Link>
          ??????h2>
          ????
          ??)
          }

          此外,若我們有需要修改 的訴求時(shí),可創(chuàng)建pages/_document.js 文件,并通過(guò)“自定義文檔[7]”的方式繼承并統(tǒng)一改造所有網(wǎng)頁(yè)輸出的公共內(nèi)容。

          5.3 JS 腳本文件

          例如我們使用了三方庫(kù) Jquery,雖然可以直接在 組件中直接寫(xiě):

          <script?src="/scripts/jquery.js">script>

          但是,這種方式包含腳本并不能明確說(shuō)明何時(shí)加載同一頁(yè)面上獲取的其他 JavaScript 代碼。如果某個(gè)特定腳本會(huì)阻塞渲染并且會(huì)延遲頁(yè)面內(nèi)容的加載,則會(huì)顯著影響性能。

          因此,可以通過(guò) next/script[8] 來(lái)優(yōu)化

          import?Link?from?'next/link'
          import?Head?from?'next/head'
          import?Script?from?'next/script'

          export?default?function?FirstPost()?{
          ??return?(
          ????<>
          ??????<Head>
          ????????<title>First?Posttitle>

          ??????Head>
          ??????<Script
          ????????src="/scripts/jquery.js"
          ????????strategy="lazyOnload"?//?設(shè)置?js?加載的方式
          ????????onLoad={()?=>

          ??????????//?js?腳本文件加載完成后的回調(diào)函數(shù)
          ??????????console.log(`script?loaded?correctly`)
          ????????}
          ??????/>
          ??????<h1>First?Posth1>

          ??????<h2>
          ????????<Link?href="/">
          ??????????<a>返回首頁(yè)a>

          ????????Link>
          ??????h2>
          ????</>
          ??)
          }

          5.4 CSS 文件

          Next.js 已經(jīng)內(nèi)置支持了 CSS 和 SASS,允許開(kāi)發(fā)者引入 .css.sass 文件方式引入樣式文件,同時(shí)還支持 Tailwind CSS。

          需要手動(dòng)安裝 SASS 模塊

          yarn?add?sass

          默認(rèn)還支持 CSS-in-JS,借助 styled-jsx[9] 這個(gè)模塊,可以直接在 React 組件中直接寫(xiě) CSS,同時(shí)限制作用域,不會(huì)影響其他組件。

          如果需要 CSS 模塊化[10],那么 CSS 文件命名應(yīng)當(dāng)為 *.module.css 格式。

          import?styles?from?'./layout.module.css'

          export?default?function?Layout({?children?})?{
          ??return?<div?className={styles.container}>{children}div>
          }

          全局 CSS 注入,則在根目錄的 ./styles 目錄編寫(xiě),同時(shí)也僅在 ./pages/_app.tsx 文件中引入全局樣式文件

          import?'../styles/globals.css'?//?引入全局樣式
          import?type?{?AppProps?}?from?'next/app'

          function?MyApp({?Component,?pageProps?}:?AppProps)?{
          ??return?<Component?{...pageProps}?/>
          }

          export?default?MyApp

          Next.js 使用 PostCSS[11] 編譯 CSS,自定義配置 PostCSS 的方式可參考:【自定義 PostCSS 配置[12]

          六、預(yù)渲染和數(shù)據(jù)獲取

          Next.js 支持:

          • 在服務(wù)端預(yù)渲染
          • 靜態(tài)頁(yè)面生成和服務(wù)端渲染
          • 有數(shù)據(jù)和無(wú)數(shù)據(jù)的靜態(tài)生成
          • 一些預(yù)定義的方法(生命周期函數(shù))注入數(shù)據(jù)

          6.1 預(yù)渲染

          默認(rèn)情況下,Next.js 預(yù)渲染每個(gè)頁(yè)面。這意味著 Next.js 會(huì)提前為每個(gè)頁(yè)面生成 HTML,預(yù)渲染可以帶來(lái)更好的性能和SEO。

          每個(gè)生成的 HTML 都與該頁(yè)面所需的最少 JavaScript 代碼相關(guān)聯(lián)。當(dāng)瀏覽器加載頁(yè)面時(shí),其 JavaScript 代碼會(huì)運(yùn)行并使頁(yè)面完全交互。

          預(yù)渲染和無(wú)預(yù)渲染的對(duì)比如下:

          6.2 靜態(tài)生成和服務(wù)端渲染

          Next.js 支持兩種形式的預(yù)渲染方式:靜態(tài)生成服務(wù)端渲染

          • 靜態(tài)生成: 在構(gòu)建時(shí)生成 HTML 的預(yù)渲染方法。然后在每個(gè)請(qǐng)求上重用預(yù)渲染的 HTML。
          • 服務(wù)器端渲染: 在每個(gè)請(qǐng)求上生成 HTML 的預(yù)渲染方法。

          6.3 獲取數(shù)據(jù)

          (1)靜態(tài)生成時(shí)獲取數(shù)據(jù)

          在服務(wù)端構(gòu)建生成靜態(tài)頁(yè)面之前,有時(shí)候需要獲取一些數(shù)據(jù),可以借助 getStaticProps 方法。

          頁(yè)面組件內(nèi),同時(shí)導(dǎo)出一個(gè) getStaticProps 方法:

          export?default?function?HomePage(props)?{?...?}

          //?導(dǎo)出異步獲取數(shù)據(jù)方法
          export?async?function?getStaticProps()?{
          ??//?獲取數(shù)據(jù),例如從數(shù)據(jù)庫(kù)、API、文件等
          ??const?data?=?...

          ??//?返回的參數(shù)將會(huì)按照?key?值賦值到?HomePage?組件的同名入?yún)⒅?/span>
          ??return?{
          ????props:?...
          ??}
          }

          注意,僅在頁(yè)面組件內(nèi)導(dǎo)出該方法

          (2)服務(wù)端渲染時(shí)獲取數(shù)據(jù)

          比如用戶(hù)的個(gè)人中心頁(yè)面,該頁(yè)面時(shí)不需要 SEO 優(yōu)化的,其數(shù)據(jù)通常需要實(shí)時(shí)更新獲取,因此采用 SSR 的方式,而 SSR 在服務(wù)端獲取數(shù)據(jù)可以借助 getServerSideProps 方法

          和構(gòu)建時(shí)獲取數(shù)據(jù)方法類(lèi)似:

          export?default?function?HomePage(props)?{?...?}

          //?導(dǎo)出異步獲取數(shù)據(jù)方法
          export?async?function?getServerSideProps()?{
          ??//?獲取數(shù)據(jù),例如從數(shù)據(jù)庫(kù)、API、文件等
          ??const?data?=?...

          ??//?返回的參數(shù)將會(huì)按照?key?值賦值到?HomePage?組件的同名入?yún)⒅?/span>
          ??return?{
          ????props:?...
          ??}
          }

          (3)客戶(hù)端渲染時(shí)獲取數(shù)據(jù)

          如果不需要“預(yù)渲染”時(shí)候獲取數(shù)據(jù),即不需要“靜態(tài)生成”和“服務(wù)端渲染”的時(shí)候獲取數(shù)據(jù),則可以在對(duì)應(yīng)頁(yè)面組件代內(nèi),編寫(xiě)網(wǎng)絡(luò)請(qǐng)求相關(guān)代碼。

          Next.js 團(tuán)隊(duì)提供了一個(gè)基于 React Hooks 的 useSWR 鉤子,推薦使用,該鉤子會(huì)處理緩存、重新驗(yàn)證、焦點(diǎn)跟蹤、間隔重新獲取等。

          一個(gè)簡(jiǎn)單的示例如下:

          import?useSWR?from?'swr'

          function?Profile()?{
          ??const?{?data,?error?}?=?useSWR('/api/user',?fetch)

          ??if?(error)?return?
          failed?to?load</div>
          ??if?(!data)?return?
          loading...div>
          ??return?
          hello?{data.name}!</div>
          }

          和一些封裝的請(qǐng)求 Hooks 類(lèi)似,useSWR 還支持自定義請(qǐng)求庫(kù),默認(rèn)使用的是 fetch 的 pollyfill 模塊(unfetch[13]),提供的中文官方的文檔也非常清晰,地址:https://swr.vercel.app/zh-CN/docs/getting-started

          七、動(dòng)態(tài)路由

          上面講到了預(yù)渲染,如果是動(dòng)態(tài)路由的預(yù)渲染該如何處理?這里需要依賴(lài)方法 getStaticPaths 獲得動(dòng)態(tài)路由需要生成頁(yè)面列表。

          //?./pages/post/[id].tsx
          import?Layout?from?'../../components/layout'

          export?default?function?Post({id,?article})?{
          ??return?(
          ??????<Layout>
          ??????????<Head>
          ??????????????<title>{article.title}title>

          ??????????Head>
          ??????????{article.title}
          ??????????<br?/>
          ??????????{id}
          ??????????<br?/>
          ??????????{article.date}
          ??????Layout>
          ???)
          }

          export?async?function?getStaticPaths()?{
          ??//?返回所有可能的文章?id?所對(duì)應(yīng)的列表
          ????const?paths?=?[
          ??????{
          ????????params:?{
          ??????????id:?'ssg-ssr'
          ????????}
          ??????},
          ??????{
          ????????params:?{
          ??????????id:?'pre-rendering'
          ????????}
          ??????}
          ????]
          ????
          ????return?{
          ????????paths,
          ????????fallback:?false,?//?如果在?paths?中?id?找不到對(duì)應(yīng)值,則指向?404?頁(yè)面
          ????}
          }

          export?async?function?getStaticProps({?params?})?{
          ??//?通過(guò)?params.id?獲取必要的文章數(shù)據(jù)?
          ??//?parmas?即路由中的參數(shù)對(duì)象
          ??const?article?=?getContentById(parmas.id);
          ??return?{
          ??????props:?{
          ??????????id,
          ??????????artcile,
          ??????}
          ??}
          }

          關(guān)于 fallback 可以參閱:fallback props[14]

          自建一個(gè) 404 頁(yè)面,文件路徑為:./pages/404.tsx

          export?default?function?Custom404()?{
          ??return?<h1>404?-?Page?Not?Foundh1>
          }

          八、BFF API

          在初始化的目錄結(jié)構(gòu)中的 ./pages/api/hello.ts 文件,就是一個(gè) API 頁(yè)面,他的路由和頁(yè)面路由相同

          import?type?{?NextApiRequest,?NextApiResponse?}?from?'next'

          type?Data?=?{
          ??name:?string
          }

          export?default?function?handler(
          ??req:?NextApiRequest,
          ??res:?NextApiResponse
          )?
          {
          ??res.status(200).json({?name:?'John?Doe'?})
          }

          ./pages/api/ 目錄下,前端開(kāi)發(fā)者編寫(xiě)人意的 API 應(yīng)用,也就是被稱(chēng)為 Serverless Functions,類(lèi)似于字節(jié)的“輕服務(wù)[15]

          九、部署

          官方推薦使用 Vercel[16] 來(lái)完成一鍵自動(dòng)化構(gòu)建部署

          首先執(zhí)行構(gòu)建,構(gòu)建時(shí)候會(huì)自動(dòng)做相關(guān)優(yōu)化

          yarn?build
          //?實(shí)際執(zhí)行
          next?build

          然后是啟動(dòng)服務(wù):

          yarn?start
          //?實(shí)際執(zhí)行
          next?start?-p?8080

          在生產(chǎn)環(huán)境,再用 PM2[17] 管理守護(hù)進(jìn)程

          然后使用 Nginx 作為網(wǎng)關(guān),配置域名,SSL,映射到本地 8080 端口即可。

          拓展更多

          Next.js 還有更多細(xì)節(jié)和 API,需要深入了解的小伙伴可以參閱:Next.js API文檔[18]

          除了 Next.js,還有 Razzle.js[19] 也可以學(xué)習(xí)下。

          推薦閱讀:

          • 《徹底理解服務(wù)端渲染 - SSR原理》
          • 魅族官網(wǎng)基于 next.js 重構(gòu)實(shí)踐總結(jié)與分享[20]
          • SWR - 用于數(shù)據(jù)請(qǐng)求的 React Hooks 庫(kù)[21]
          • react 服務(wù)端(ssr) 框架next.js開(kāi)發(fā)個(gè)人網(wǎng)站分享[22]
          • Next.js 應(yīng)用開(kāi)發(fā)實(shí)踐[23]

          總結(jié)

          通過(guò)對(duì) Next.js 的初步上手使用,SSR 確實(shí)有助于提升用戶(hù)的體驗(yàn),比如一些文檔網(wǎng)站、官網(wǎng)、營(yíng)銷(xiāo)網(wǎng)頁(yè),個(gè)人非常推薦這種方式,但其缺點(diǎn)也很明顯,服務(wù)端的穩(wěn)定性會(huì)有所降低,穩(wěn)定性可以通過(guò)增加成本提高,相較于其優(yōu)點(diǎn),還是值得投入的!

          Next.js 把一些生產(chǎn)配置初始化就構(gòu)建完成,對(duì)于開(kāi)發(fā)者來(lái)說(shuō),開(kāi)箱即用的感覺(jué)真的太棒了!

          參考資料

          [1]

          什么是前端的同構(gòu)渲染?: https://www.zhihu.com/question/325952676

          [2]

          Next.js: https://nextjs.org/

          [3]

          next/router: https://nextjs.org/docs/api-reference/next/link

          [4]

          useRouter: https://nextjs.org/docs/api-reference/next/router#userouter

          [5]

          next/image: https://nextjs.org/docs/api-reference/next/image

          [6]

          next/head: https://nextjs.org/docs/api-reference/next/head

          [7]

          自定義文檔: https://nextjs.org/docs/advanced-features/custom-document

          [8]

          next/script: https://nextjs.org/docs/api-reference/next/script

          [9]

          styled-jsx: https://github.com/vercel/styled-jsx

          [10]

          CSS 模塊化: https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css

          [11]

          PostCSS: https://postcss.org/

          [12]

          自定義配置 PostCSS: https://nextjs.org/docs/advanced-features/customizing-postcss-config

          [13]

          unfetch: https://www.npmjs.com/package/unfetch

          [14]

          fallback props: https://nextjs.org/docs/basic-features/data-fetching#the-fallback-key-required

          [15]

          輕服務(wù): https://qingfuwu.cn/

          [16]

          Vercel: https://vercel.com/

          [17]

          PM2: https://pm2.keymetrics.io/

          [18]

          Next.js API文檔: https://nextjs.org/docs/api-reference/cli

          [19]

          Razzle.js: https://razzlejs.org/

          [20]

          魅族官網(wǎng)基于 next.js 重構(gòu)實(shí)踐總結(jié)與分享: https://zhuanlan.zhihu.com/p/113853235

          [21]

          SWR - 用于數(shù)據(jù)請(qǐng)求的 React Hooks 庫(kù): https://swr.vercel.app/zh-CN/docs/getting-started

          [22]

          react 服務(wù)端(ssr) 框架next.js開(kāi)發(fā)個(gè)人網(wǎng)站分享: http://www.liuweibo.cn/p/206

          [23]

          Next.js 應(yīng)用開(kāi)發(fā)實(shí)踐: https://nextjs-in-action-cn.taonan.lu/


          瀏覽 74
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  探花爱爱视频网站 | 欧美午夜影院 | 一本色道久久综合无码 | 午夜迪级 | 亚洲网站在线观看视频 |