iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 2
3
Modern Web

Next.js + 各種套件組合系列 第 2

Next.js & Server

安裝設定介紹

Next.js 在 Node 環境下安裝 react react-dom 以及 next 就可已開始使用了


npm init -y
npm i react react-dom next 

接下來設定 package.json檔案

{
  "name": "base-setup",
  "version": "1.0.0",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "^16.0.0",
    "react-dom": "^16.0.0"
  },
  "license": "ISC"
}

以上重點是在scipts的部分 直接執行 npm run dev 就可以在 localhost:3000 啟動 Next.js 專案
npm run start 是給 Production 發佈用 執行前先跑 npm run build

一般在DEV開發階段的時候會有 Hot Module Replacement (HMR) 只要在程式碼有變更就會自動幫你動更新網頁但是在產品發佈的時候就不需要這個功能

製作一個起手式

Next.js 為約定目錄所以開發時起始位置是在 pages 的這個目錄

在pages目錄下新增一個 index.js檔案

export default () => (
  <div>我的第一個  Next 網頁</div>
)

寫好後就CLI下執行 npm run dev 網址打上 localhost:3000 看到第一個Next.js網頁了,在檢視網頁模式下也可以看到HMR模式

https://ithelp.ithome.com.tw/upload/images/20171205/20103438izNW1zXEWh.png

這時候可以在剛剛的index.js 檔案中改文字後再存檔,會發現到馬上同步更新,之前要做到這樣HMR就要設定滿多的,這個部分Next.js都幫你完成了

接下來做一個分頁來熟習一下 PAGES 感受一下目錄(File-Systme即Route),另外也在pages層下開一個about.js檔案

import Link from 'next/link'
export default () => (
  <div>關於 About Next 網頁</div>
  <div><Link href="/"> <a>回到首頁</a></Link></div>
)

並在 index.js 也加上 (注意新版的NEXT建議在link中再放一個 a tag標籤)

<Link href="/about"> <a>關於Next</a></Link>
import Link from 'next/link'
export default () => (
  <div>我的第一個  Next 網頁</div>
  <div><Link href="/about"> <a>關於Next</a></Link></div>

)

這樣就完成了頁面 Route 的切換了 ,另外值得一提的是這個Link元件有個不錯的功能 就是 prefetch 只要加上這個關鍵字,就會同時幫你把 about 的頁面也順便預先加載,到時候在切換頁面的時候會增加Ux使用者體驗

<Link prefetch href="/about">

另外有時候情境是在 Function 中去切換 Route 也想要有預先加載的功能的時候就使用
import Router from 'next/router' 配合 Router.prefetch 使用

以上是起手式 接下來進入 With Server 的部分

Next.js 可以搭配許多 不同的 Server 目前官方範例有 Koa Express Fastify Hapi Micro Nodemon 也可以客製化 Custom Server ,套用方法都大同小異,這裡使用EXPRESS來說明

修改一下 package.json 檔案

以上省略
"scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "next start"
  },
以下省略

在根目錄設定一隻server.js的檔案

const express = require('express')
const next = require('next')

const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare()
.then(() => {
  const server = express()
 
  server.get('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, (err) => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
  })
})

所有Server套用範例都差不多,例如上方範例 Express 都包在這個 NEXT 提供的APP裡面
const app = next({ dev })之中,其他 Route 設定 Middlewave 的設定方式都跟原先的使用方式一樣

如果沒有其他特定指定的 Router 要做的工作事項,前後端同步SSR基本會在 server.get('*', (req, res) 這個ROUTER完成
這邊也會透過getRequestHandler 這個方法把 req ,res 跟前端 static getinitialprops 做同步溝通

 server.get('*', (req, res) => {
    return handle(req, res)
  })

另外 Server 部分如果要把 Routers 分散管理 以下面範例為例可以使用next-routes

routes.js

const nextRoutes = require('next-routes')
const routes = module.exports = nextRoutes()

routes.add('index', '/')
routes.add('post', '/blog/:slug')

Routers 的部分要記得加上 routes.getRequestHandler(app) 並使用 use 加上Middleware

 
const routes = require('./routes')
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const handler = routes.getRequestHandler(app)

app.prepare()
.then(() => {
  const server = express()
  server.use(handler)
  server.get('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, (err) => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
  })
})

配合前端的 Router 元件使用:

route - 顯示目前的位置
pathname - 要前往連結的位置
query - 傳參數用,預設值{}
asPath - 瀏覽器實際顯示的路徑但非實際連結位置
push(url, as=url) - 執行呼叫

好了直接在CLI底下 npm run dev 開心的跑起一個喜歡的 Server 吧

總結

Next.js 大大降低了設定的入門門檻,但有些流程跟一般的React多了 getinitialprops 的部分要特別去理解

Server 部分 大同小異 模式都是一樣 都會用next({dev})包起來再透過 handle 傳送 其他寫作方式就跟用什麼框架的 Server 照原先的方法撰寫即可 特別注意的是 handle , server.get('*', (req, res) 要記得使用當預設

 server.get('*', (req, res) => {
    return handle(req, res)
  })

上一篇
Next.js 功能及介紹
下一篇
Next.js & Layout
系列文
Next.js + 各種套件組合30

尚未有邦友留言

立即登入留言