iT邦幫忙

2021 iThome 鐵人賽

DAY 6
1
Modern Web

製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~系列 第 6

#06 No-code 之旅 — 用 Next.js 解決前後端?API Routes 簡介

連假最後一天!分享了一些關於 Next.js 這個框架,雖然他是 React 的框架,可是你們知道嗎?Next.js 也可以同時實作後端喔!沒錯,前後端全包~ 怎麼做呢?今天來看看 Next.js 的 API Routes,看完應該會有想法怎麼實作,不過看這篇文章之前,可以先看看上一篇關於 Next.js 的 routing 喔!

Next.js API Routes

API Routes

Next.js 的 API routes 也採用 file-based routing,意思是每個檔案代表一個 route,而檔案名稱 (file name) 會變成 route 的 path name (路徑名稱)。Next.js 會把 pages/api 資料夾 / 目錄裡面的所有檔案看成 route (路徑) 的一部分:

  • pages/api/index.js 代表 / API route
  • pages/api/user.js 代表 /user API route

API routes 裡的所有程式碼是屬於後端的部分,所以只會跑在伺服器端。這代表我們寫的 API 不會讓我們前端的 bundle size 變大,不會影響網頁的下載時間!也是因為是跑在伺服器端,我們可以實作各種後端的功能,例如操作資料庫~

每個 pages/api 裡的檔案需要 export 一個 default function (函式) 作為 API 的 request handler (處理請求的函式),然後每個 handler 會有兩個 parameters:

Dynamic (動態) API routes

像 Next.js 的 routing 一樣,API routes 也支援 dynamic (動態) routing。如果我們對 pages/api/posts/[pid]/comments/[cid].js 路徑發個 /api/posts/world/comments/hello 的請求:

export default function handler(req, res) {
  const { pid, cid } = req.query
  res.end(`Comment #${cid} for post #${pid}`)
}

上面的 API 會回傳 Comment #hello for post #world

Index API routes

每個 index 檔案代表根目錄,所以

  • pages/api/posts.js 代表 /api/posts API route
  • pages/api/posts/index.js 也代表 /api/posts API route

注意:pages/api/posts/[pid].js 並不代表 /api/posts 只代表 /api/posts/1/api/posts/2

Catch all API routes

屬於 dynamic API routes 的一種,不過 catch all 的意思是不需要一個一個定義動態的部分,把所有動態的資訊抓起來,讓 route 比較彈性,寫法跟其餘參數(rest parameter)一樣。

  • pages/api/posts/[...slug].js 可以代表 /api/posts/a 也可以是 /api/posts/a/b/api/posts/a/b/c

slug 可以是 param 或是其他東西都可以,這些動態資訊也會出現在 query 物件裡面,例如 /api/posts/a/b/cquery 會是:

{ "slug": ["a", "b", "c"] }

Optional catch all routes

跟 pages 的 optional catch all routes 一樣,只要把 catch all 的 [...slug] 改成 [[...slug]] 就會變成 optional catch all。意思是 slug 這個 array (陣列) 可以是不存在的,

  • pages/posts/[[...slug]].js 可以代表 /posts/a 也可以是 /posts/a/b/posts/a/b/c 等,不過也可以代表 /posts

所以當我們發請求到 /api/postsquery 物件會是空物件

{ } // GET `/api/post` (空物件)
{ "slug": ["a"] } // `GET /api/post/a`
{ "slug": ["a", "b"] } // `GET /api/post/a/b`

API Middlewares

Next.js 有提供內建的 middlewares 塞進去 req 物件裡,除了內建的之外,我們還可以用其他 Connect / Express 相容的 middlewares。

Built-in (內建) middlewares

  • req.cookies:請求的 cookies,預設為 {}

  • req.query:請求的 query string,預設為 {}

  • req.body:已經被 parse 的請求 body,會根據 content-type 做 parse,當沒有 body 時會回傳 null。如果不想要 body 被 parse,可以在 API route 檔案裡加 config

    export const config = {
      api: {
        bodyParser: false,
      },
    }
    

除了 body parser 的 config 以外,還有更多 API 相關的 config 可以看這裡喔~

Connect / Express 相容的 middlewares

想要在我們的 API routes 增加其他 middlewares 也可以!直接在 handler function 裡執行該 middleware 再繼續跑 API 本身的 code,像:

import Cors from 'cors'

// initialize cors middleware
const cors = Cors({
  methods: ['GET', 'HEAD'],
})

// helper method 去執行 middleware,結束後才繼續跑下去
// 發生錯誤時跳 error
function runMiddleware(req, res, fn) {
  return new Promise((resolve, reject) => {
    // fn 為 middleware
    fn(req, res, (result) => {
      if (result instanceof Error) {
        return reject(result)
      }

      return resolve(result)
    })
  })
}

async function handler(req, res) {
  // 先跑 middleware
  await runMiddleware(req, res, cors)

  // API 本身的邏輯
  res.json({ message: 'Hello Everyone!' })
}

export default handler

官方 docs 在這裡

Response Helper

雖然 API routes 不是 Express.js,可是 Next.js 有提供一些類似的 helper functions 來幫助我們開發而提升 DX (開發者體驗):

  • res.status(code):設定 response 的 status code (要符合 HTTP status code)
  • res.json(body):回傳 JSON 為 response 給瀏覽器 (客戶端)
  • res.send(body):回傳 HTTP response,body 可以是 stringobject,或是 Buffer
  • res.redirect([status,] path):導頁,把瀏覽器導到別 path 或 URL,status 是 HTTP status code,是個非必須的 parameter,預設為 307 (Temporary redirect).

小結

我們看完 API routes 之後,可以開始做一些全端專案了(誤
大家會想用 API routes 做哪些事呢?有了這個真的讓前後端開發簡單一些~
祝大家明天上班上課愉快!

晚安 <3

看更多


上一篇
#05 No-code 之旅 — Next.js 的 Pages 與 Routing
下一篇
#07 簡介篇 — 使用 Next.js 的各種 Data Fetching 方式實作小專案 ft. Github API
系列文
製作你的無程式碼(No-code)個人網頁 ft. Next.js, SWR, 串 Youtube, IG, Github, Notion API ~30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言