Nuxt.js contentful

Nuxt 系列 - #6 整合 CMS 服務 contentful

廖汶彬 2020/06/04 09:36:45
867

註冊/登入 contentful

contentful 網站 https://www.contentful.com/
contentful website

註冊頁 https://www.contentful.com/sign-up/
可使用 Github、Google 帳號登入或直接填表單進行註冊
contentful signup

建立 Space

建立方案的第一個步驟選擇類型,如未填寫付款資訊就不能選擇需付費的方案
這邊就直接選擇 Free 的方案,上面也會清楚標示可用上限之資訊
create space step1

步驟二就是給 Space 一個名字,並選擇建立一個空的 space
create space step2

步驟三確認後 Space 就建立完成
create space step3

在 Content model 建立 content type

點選畫面上方的 Content model 功能,新增 content type
相當於建立一個資料表的欄位名稱與型態
一個 content type 最多可定義50個欄位,資料型態也有11種
每種資料型態都會有一些限制,可能是長度、數字最大最小值、日期時間格式…等等
詳細規格可以直接參考 Content data model,裡面有非常詳細的說明

新增欄位時,介面提供以下幾種欄位型態
content model field
欄位全部設定完成後,按下畫面右側 Save 即可開始依照剛剛的欄位設定建立資料內容

目前 blog 文章的欄位規畫一共有6個欄位,如下圖所示
blog post model field
主要的文章內容儲存於 Article Content 欄位,內容格式使用 markdown 所以欄位型態選擇 Long Text 即可
文章分類標籤儲存於 Category List 欄位,由於可能有多個分類,所以在設定時要特別勾選是多筆。
使用此方式的好處是後續在使用 api 時,可以直接使用參數的方式過濾資料,因此可節省資料傳輸的大小。如果使用 Json object 方式儲存,則需要將所有資料撈回再過濾。
如下圖所示紅框部份要勾選
text field with list

新增 Content

點選畫面上方的 Content 功能,新增指定 content type 的資料內容
新增資料內容頁面會依據先前建立的 content type 呈現表單
編輯過程中會自動存檔
不同欄位型態會呈現不同輸入方式(日期選單、markdown 編輯器),也有基本檢核(例如長度、必填)
add content
完成編輯後可選擇排程或是立即 Publish

設定 API Key

點選畫面上方的 Settings 選擇 API keys 開啟設定畫面,按下 "Add API key"
add api key
編輯完成後按下 Save 即完成設定
畫面上有3個不可編輯的欄位,由系統自動產生的資訊,分別是

  • Space ID
  • Content Delivery API - access token
  • Content Preview API - access token

後續在專案中呼叫 contentful api 時,需要用到 Space ID 與 access token,其中 Content Delivery API - access token 是用來取得正式發佈的資料,而 Content Preview API - access toke 除了取得正式發佈的資料還有也會取得狀態為 "Draft"的資料。方便你在開發環境使用,可快速切換。

在 Nuxt.js 專案中使用 contentful 服務

執行下列指令安裝 contentful 套件

npm install contentful --save

在 plugins 資料夾新增一個檔案 contentful.js 用來建立呼叫 contentful api 的 client
建立時必需提供 space id 與 access token
如果有切換環境的需要,則可設定 environment 屬性,此設定預設值為 master

// plugins/contentful.js

const contentful = require('contentful')
// use default environment config for convenience
// these will be set via `env` property in nuxt.config.js
const config = {
  space: process.env.CTF_SPACE_ID,
  accessToken: process.env.CTF_CDA_ACCESS_TOKEN
}

// export `createClient` to use it in page components
module.exports = {
  createClient () {
    return contentful.createClient(config)
  }
}

在 nuxt.config.js 設定環境變數 CTFSPACEID、CTFCDAACCESSTOKEN 與 CTFBLOGPOSTTYPE_ID,供程式中取用

// ./nuxt.config.js
const config = require('./config')

module.exports = {
  // ...
  env: {
    CTF_SPACE_ID: config.CTF_SPACE_ID,
    CTF_CDA_ACCESS_TOKEN: config.CTF_CDA_ACCESS_TOKEN,
    CTF_BLOG_POST_TYPE_ID: config.CTF_BLOG_POST_TYPE_ID
  }
  // ...
}

利用 plugins/contentful.js 的 createClient 方法建立呼叫 api 的物件使用 getEntries 進行 api 呼叫
以下為簡易的呼叫 api 範例

import contentful from '~/plugins/contentful.js'
const client = contentful.createClient()

const getArticles = () => {
  return client.getEntries({
    // 設定要取得的 content type id
    content_type: config.CTF_BLOG_POST_TYPE_ID,
    // 指定呼叫 api 回傳的欄位有那些
    select: 'fields.id,fields.createDate,fields.title,fields.slug,fields.categoryList',
    // 指定回傳資料排序的欄位與排序方式(由大至小 or 由小至大)
    order: '-fields.createDate'
  })
    .then(res => map(res.items, item => item.fields))
    .catch(() => Promise.resolve([]))
}

完成以上步驟之後即可在 Nuxt.js 專案內呼叫 contentful 的 api
為了方便維護與管理我在專案中建立 services/api.js,並且於檔案內建立需使用的呼叫 api 方法提供程式使用

blog 專案使用 getEntries 查詢資料參數使用說明

在 Content 新增的資料稱為 Entry,而 getEntries 則是用來取得這些 Content 資料的方法,回傳為 Promise 物件
getEntries 方法提供了非常多的參數可供開發人員設定使用,以下針對目前專案有使用的參數進行說明
其他詳細的使用方式也可參考官方文件,點擊參數說明內的"Query entries"可看到該參數使用的程式碼(可選平台)並且模擬查詢(參數可自行調整)

首頁文章清單資料
  1. 顯示最新10筆資料
  2. 文章排列方式為由新到舊
  3. 不回傳"文章內容"欄位資料,節省傳輸量
import contentful from '~/plugins/contentful.js'
const client = contentful.createClient()
client.getEntries({
    content_type: 'post',
    select: 'fields.id,fields.createDate,fields.title,fields.slug,fields.categoryList',
    order: '-fields.createDate',
    limit: 10
})
依分類搜尋文章清單資料
  1. 取得所有文章分類包含"Nuxt.js"的文章資料
  2. 文章排列方式為由新到舊
  3. 不回傳"文章內容"欄位資料,節省傳輸量
import contentful from '~/plugins/contentful.js'
const client = contentful.createClient()
client.getEntries({
    content_type: 'post',
    select: 'fields.id,fields.createDate,fields.title,fields.slug,fields.categoryList',
    order: '-fields.createDate',
    'fields.categoryList': 'Nuxt.js'
})
使用 id 取得文章詳細內容頁的資料
  1. 取得 id 為"a-series-of-nuxtjs-01"的文章資料
  2. 回傳所有欄位
import contentful from '~/plugins/contentful.js'
const client = contentful.createClient()
client.getEntries({
    content_type: 'post',
    'fields.id': 'a-series-of-nuxtjs-01'
})

參考資料

contentful
contentful Guides
contentful Content data model
contentful API reference
contentful.js - Contentful JavaScript Delivery SDK
Integrate Contentful with Nuxt.js

廖汶彬