Isomorphic SSR 的第一哩路: Next.js

威威不想說話發表於2018-09-21

什麼是 SSR?為什麼要 SSR?

SSR 是 Sever-side Render 的縮寫,意思是指「在 Server 端就產生(Render)出畫面」。目前大概有幾種產生畫面的時機點:

  1. Server Side Render: 在後端接收到 Request 即產生 HTML 畫面,需要新的資料則需要重新傳送 Request ,也會產生一個新的畫面。後端的 Framework 通常都會有一個 HTML Template 的機制就是在產生畫面的動作。
  2. Client Side Render: 在前端進行 Render,後端作為資料供應的 API 層。當需要新的資料時,前端傳送 Request 後只需要部份更新畫面就好。
  3. Isomorphic: 網站能夠同時考慮 SSR 與 CSR 兩種方式,之前有整理過關於 Isomorphic 的介紹。

Isomorphic SSR 的第一哩路: Next.js

最早期的網站都是 SSR 的方式進行,但每次的重新 Render 會造成後端的負擔提升也讓使用者的體驗變差。而後來的 React/Vue 之類的 Framework 則是基於 CSR 的方式讓使用者體驗,並達到了前後端分離的優點。但 CSR 還是伴隨著幾個問題:

  1. 有些 CSR 的網站會造成爬蟲取得的頁面不是那麼完整,造成 SEO 的問題
  2. 第一次載入畫面是等到前端載入後,會有一段時間的空白

因此,如果能夠兼具 CSR 與 SSR 的 Isomorphic ,成了一條新的解法。以下我們講的 SSR 都是 Isomorphic 同時兼具兩種方式的 SSR。

Next.js

「Next.js is a lightweight framework for static and server‑rendered applications.」

Next 是一個基於 React 的 SSR 解決方案,更多的細節可以參考官網

Isomorphic SSR 的第一哩路: Next.js

開始第一個 Next.js 專案吧!

方法 ①: 手動安裝

根據官方的教學,可以透過 NPM 的方式手動安裝:

$ npm install --save next react react-dom
複製程式碼

接著再把 package.json 中執行的方式改成 NEXT:

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}
複製程式碼

然後建立一個頁面在 /pages/index.js 檔案:

export default () => <div>Welcome to next.js!</div>
複製程式碼

最後,執行指令就會將專案跑在 3000 PORT:

npm run dev
複製程式碼

方法 ②: create-next-app

許多人開發 React 會搭配 create-react-app 的 scaffold 來跳過複雜的環境設定,Next.js 也有:

$ npm install -g create-next-app

$ create-next-app my-app
$ cd my-app/
$ yarn start
複製程式碼

來看一個簡單 Isomorphic 範例

增加一個新頁面

Next 是根據 /pages 目錄作為 Route 的分配,舉例來說 /pages 的 index 就會對應到 Root URL。我們先在 /pages 目錄下建立一個 hello.js 的檔案:

const Hello = (props) => (
    <div>
        <h1>Hello Next</h1>
    </div>
)

export default Hello
複製程式碼

此時就會多了一個 Route 在 /hello 。

兩個頁面彼此連結

在 Next 中提供了 Link 的 Component 讓我們可以進行頁面間的 Client Side 換頁:

import Link from 'next/link'

const Hello = (props) => (
    <div>
        <Link href={`/`}>
          <a>index</a>
        </Link>
        <Link href={`/hello`}>
          <a>hello</a>
        </Link>
    </div>
)

export default Hello
複製程式碼

CSR 與 SSR 判斷

我們現在有一個頁面,上面有連結。我們前面有說過 Next.js 是一個兼具 CSR 與 SSR 的框架,那他是怎麼處理的呢?先區分一下兩種來源:

  • 如果直接點 Link 連結,是在 Client Side 換頁 => CSR
  • 重新整理,或是第一次到這個畫面上,必須先發 Request 到後端 => SSR

Next 的做法是透過 getInitialProps 的方式,在 Render 之前就先透過 req 來判斷來源為何:

import Link from 'next/link'

const Hello = (props) => (
    <div>
        <h1>{props.text}</h1>
        <Link href={`/hello`}>
            <a>reload</a>
        </Link>
    </div>
)

Hello.getInitialProps = async function({req, query}) {
  if (req)
    return { text: 'hello server' }
  return { text: 'hello client' }
}

export default Hello
複製程式碼

這樣執行之後,我們可以發現:

  • 如果是 SSR 的話,會在 getInitialProps 取得 req
  • 如果是 CSR 的話,getInitialProps 中不會得到 req

小結論

Next 可以優雅地替我們解決 Isomorphic 的複雜機制,達到同時有 SSR 與 CSR 的解法。透過了簡單的實作來了解如何開始,如果之後新專案有需要是直得考慮匯入的!

Reference

  1. Next.js
  2. create-next-app

License

Isomorphic SSR 的第一哩路: Next.js

本著作由Chang Wei-Yaun (v123582)製作, 以創用CC 姓名標示-相同方式分享 3.0 Unported授權條款釋出。

相關文章