Next.js與React服務(wù)端渲染

最近在一個資訊類的項目中用了 Next.js 服務(wù)端渲染,體驗了一把服務(wù)端渲染的速度,首屏直出奢浑,渲染速度666虏杰。

服務(wù)端渲染

在之前前后端沒分離的時候讥蟆,前端簡單寫一下 HTML 模版,后端通過諸如 Php纺阔、Java 等各種模版引擎把靜態(tài)頁面處理成動態(tài)模版渲染出來瘸彤,那個時候就是服務(wù)端渲染了。但這樣好麻煩笛钝,歷史車輪滾滾向前质况,單頁面應(yīng)用的時代,后端只提供接口玻靡,不再負責(zé)模板的處理结榄。再后來為了解決 SEO 的問題,順帶首屏渲染的問題囤捻,總不能再回到前后端不分離的年代吧臼朗,所以就是前端er自己選擇的路,跪著也要走下蝎土,Vue 的 Nuxt.js视哑,React 的 Next.js 等 SSR 框架應(yīng)運而生。

我們平常廣泛使用 Vue誊涯、React 在客戶端渲染挡毅,服務(wù)端返回了一個空的 HTML 模版,然后內(nèi)部加載JS暴构,生成并操作 Dom跪呈,最后由瀏覽器渲染出頁面段磨,這樣一系列的動作下來首屏加載會顯的慢了不少。另外由于是個空的頁面庆械,爬蟲無法識別薇溃,不利于 SEO,在瀏覽器中右鍵查看源碼缭乘,可以看到頁面是個空的 HTML沐序。

client.png

服務(wù)端渲染(SSR),服務(wù)端直接返回了 HTML堕绩,瀏覽器顯示即可策幼,無需等待 JavaScript 完成下載且執(zhí)行才顯示內(nèi)容,不僅渲染速度大大加快奴紧,更利于搜索引擎的爬取特姐,右鍵查看源碼可以看到密密麻麻的 HTML 標簽。

ssr.png

優(yōu)點

  • 更快的首屏加載速度
  • 更友好的 SEO

缺點

  • 增加了維護成本
  • 項目部署比單頁面應(yīng)用復(fù)雜

Next.js 基本使用

路由系統(tǒng)

pages 目錄路由

  • Next.js 的路由系統(tǒng)基于文件路徑自動映射黍氮,pages 目錄內(nèi)的文件會被自動處理成路由唐含,所以通常 pages 下我們只放置頁面路由的文件,其它組件不要放到 pages 目錄下面沫浆。比如在 pages 目錄下面創(chuàng)建了 login.js 和 register.js捷枯,那么路由就對應(yīng) /login 和 /register。

  • 同樣专执,多級路由也是類似的處理淮捆。例如在 pages 下創(chuàng)建了 user 目錄,user 下創(chuàng)建 login 和 register 文件本股。/user/login 對應(yīng) login 文件攀痊,/user/register 對應(yīng) register 文件。
    Next.js 的路由系統(tǒng)使我們不用再去關(guān)心路由拄显,合理在 pages 建立目錄苟径。

動態(tài)路由

  • Next.js 也支持支持動態(tài)路由,在文件前攜帶 [param]躬审,例如 pages/post/[pid].js涩笤,會匹配到海報詳情頁面 /post/pid。

  • 預(yù)定義的 API 路由優(yōu)先于動態(tài) API 路由

    • pages/post/create.js盒件, 將匹配 /post/create
    • pages/post/[pid].js`,將匹配 /post/1,但不匹配 /post/create

路由跳轉(zhuǎn)與傳參

next 提供了兩種方式舱禽,分別是導(dǎo)航式路由 next/link 和 編程式 next/router

  1. Link

    href 為必須屬性炒刁,可傳遞對象

    <Link href="/about?name=jackylin">
    
    <Link href={{ pathname: '/article', query: { type: active } }}>
    
  2. 編程式導(dǎo)航 next/router

    和 react hooks 中的 useHistory 用法一樣

    import { useRouter } from 'next/router'
    const router = useRouter()
    //: 1
    router.push(`/article/${c.queueId}`)
    //: 2
    router.push({
    pathname: '/publish',
        query: {
          contentId: c.contentId,
          status: active
        }
    })
    

路由參數(shù)獲取

Next.js 只能通過 query 來傳遞參數(shù),不能使用 params誊稚。
useRouter 或 getServerSideProps 方法內(nèi)都可以拿到 query 參數(shù)

import { useRouter } from 'next/router'
const { query } = useRouter()
query.cid //: 獲取 cid 參數(shù)

這種動態(tài)路由的參數(shù)通過 query 可以獲取到翔始,在 getServerSideProps 方法內(nèi)也可以通過 params 獲取
router.push(`/article/${c.queueId}`)

css

Next.js 支持 Css Module 和 Css-in-JS 這兩種方式罗心,二者自帶樣式隔離。

動態(tài)導(dǎo)入

Next.js 同樣支持和 React 客戶端一樣的 ES2020 import() 語法來實現(xiàn)導(dǎo)入城瞎,在 React 單頁面項目里面渤闷,Webpack 解析到該語法時會自動進行代碼分割。在 Next.js 里面脖镀, 還可以使用next/dynamic 來動態(tài)導(dǎo)入組件飒箭,它們將在客戶端懶加載。通過動態(tài)導(dǎo)入蜒灰,對于一些不需要在服務(wù)端渲染的組件可以使用 dynamic 來處理弦蹂。

const BreadCrumb = dynamic(() => import('@/components/ui/BreadCrumb'))

服務(wù)端請求 getServerSideProps

export async function getServerSideProps(context) {
  return {
    props: {}, // will be passed to the page component as props
  }
}
  • getServerSideProps,主要用于在服務(wù)端請求數(shù)據(jù)强窖,比如我們列表的的首屏數(shù)據(jù)凸椿,像列表下一頁的數(shù)據(jù)我們則可以放到客戶端去獲取。context 參數(shù)里面包含路由參數(shù)等對象翅溺。

  • 由于 getServerSideProps 是在服務(wù)端進行的請求脑漫,所以相關(guān)的 log 信息在終端才能看到,Network 面板里面是看不到請求情況包括 console 信息咙崎。

  • getServerSideProps 返回數(shù)據(jù)后优幸,Next.js 會把這些數(shù)據(jù)寫到 HTML源 碼里面,即 window.__NEXT_DATA__.props叙凡,這樣就實現(xiàn)了把數(shù)據(jù)傳送到客戶端劈伴,客戶端有了這些數(shù)據(jù),比如可以拿著 window.__NEXT_DATA__.props里面的數(shù)據(jù)初始化 React 組件的 props 等握爷。在 console 里輸入 __NEXT_DATA__,你就能看到 Next.js 在頁面中封裝了什么數(shù)據(jù)跛璧。

其它

  • 全面兼容最新 React 17版本
  • 鏈接跳轉(zhuǎn)使用 Link,避免使用編程式導(dǎo)航新啼,有利于 SEO追城。
  • Next.js 自帶 Image 組件,自動優(yōu)化圖像燥撞,極大改善用戶體驗座柱。
  • 可以自定義 document 頁面 404頁面、500頁面等物舒。當 Next.js 捕獲到錯誤時色洞,不論是接口錯誤還是代碼運行時的錯誤,Next.js 服務(wù)內(nèi)部會統(tǒng)一轉(zhuǎn)化并拋出500異常冠胯。
  • 官方文檔

服務(wù)端渲染常見問題

最后呢總結(jié)一下 Next.js 使用中遇到的問題火诸,歡迎各路俠客補充。

useEffect 的注意點

服務(wù)端渲染時拿不到屏幕荠察、元素寬高等尺寸信息置蜀,不要讓元素的顯示依賴于 useEffect 里面的設(shè)備寬高奈搜、 dom 位置計算。

useEffect(() => {
    //:錯誤示例
    //:服務(wù)端渲染的時候拿不到設(shè)備寬度deviceWidth 所以isDesktop的值不會改變
    deviceWidth > 960 && (isDesktop = true)
, [])

return (
    <>
      {isDesktop ? (
        <div>pc</div>
      ) : null}
    </>
)

一個響應(yīng)式的頁面盯荤,pc 端顯示 HeaderBar 組件馋吗,m 端不顯示,如何處理秋秤?

在客戶端渲染的情況下宏粤,判斷一下設(shè)備類型即可。但是在服務(wù)端渲染航缀,在哪里判斷設(shè)備類型呢商架?useEffect?不能在里面判斷芥玉。

方案有二:

  1. 采用客戶端渲染的處理方式蛇摸。使用 next/dynamic 動態(tài)導(dǎo)入 HeaderBar 組件,這樣 HeaderBar 組件將在客戶端進行渲染,其它元素依然還是在服務(wù)端進行渲染。
  2. 依然采用服務(wù)端渲染的處理方式挟憔。通過 css 的媒體查詢,在 m 端對 HeaderBar 進行 display:none饿肺,這也是一種處理辦法。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盾似,一起剝皮案震驚了整個濱河市敬辣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌零院,老刑警劉巖溉跃,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異告抄,居然都是意外死亡撰茎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門打洼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來龄糊,“玉大人,你說我怎么就攤上這事募疮§懦停” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵阿浓,是天一觀的道長他嚷。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么爸舒? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮稿蹲,結(jié)果婚禮上扭勉,老公的妹妹穿的比我還像新娘。我一直安慰自己苛聘,他們只是感情好涂炎,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著设哗,像睡著了一般唱捣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上网梢,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天震缭,我揣著相機與錄音,去河邊找鬼战虏。 笑死拣宰,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的烦感。 我是一名探鬼主播巡社,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼手趣!你這毒婦竟也來了晌该?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤绿渣,失蹤者是張志新(化名)和其女友劉穎朝群,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怯晕,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡潜圃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了舟茶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谭期。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吧凉,靈堂內(nèi)的尸體忽然破棺而出隧出,到底是詐尸還是另有隱情,我是刑警寧澤阀捅,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布胀瞪,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凄诞。R本人自食惡果不足惜圆雁,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望帆谍。 院中可真熱鬧伪朽,春花似錦、人聲如沸汛蝙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窖剑。三九已至坚洽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間西土,已是汗流浹背讶舰。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翠储,地道東北人绘雁。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像援所,于是被迫代替她去往敵國和親庐舟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

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