この記事では Headless CMS として有名な Contentful の TypeScript 用型定義ファイルを自動的に生成する方法と Next.js で Contentful からのレスポンスを受け取る方法についても合わせて紹介します。
Contentful では様々なコンテンツを定義できるため自由度が高く、その反面手動で型定義をするのは大変なのでそれらを自動で生成できると便利です。
Contentful で自動的に型定義ファイルを生成するには contentful-typescript-codegen
というライブラリを使用します。
公式 JavaScript ライブラリの contentful
と contentful-management
も使用するため合わせてインストールしてください。
npm install contentful contentful-management contentful-typescript-codegen
もしくは
yarn add contentful contentful-management contentful-typescript-codegen
インストールが完了したら次は型定義ファイルを生成するための Contentful Management API Token を取得しましょう。
Contentful へログインし、「Settings」から「API keys」を押してトークン一覧画面を開きます。
次に「Content management tokens」のタブを選択し、「Generate Personal token」を押してトークンを作成します。
トークン名を設定して「Generate」を押すとトークンが表示されるのでメモしてください。
あとから確認することはできず一度忘れてしまうと再度作成する必要があるため注意です。
また、トークンは dotenv
を利用して管理すると便利です。
まだインストールしていない場合は以下のコマンドでインストールしておきましょう。
npm install dotenv
もしくは
yarn add dotenv
次に以下のように .env
ファイルを作成した上で取得したトークンを CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN
へコピペします。
CONTENTFUL_SPACE_ID = ****
CONTENTFUL_ENVIRONMENT = ****
CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN = ****
CONTENTFUL_DELIVERY_TOKEN = ****
CONTENTFUL_PREVIEW_TOKEN = ****
CONTENTFUL_SPACE_ID
は「Settings」の「General settings」から、CONTENTFUL_ENVIRONMENT
は同じく「Settings」の「Environments」確認することができます。
CONTENTFUL_DELIVERY_TOKEN
はコンテンツを取得するためのトークン、CONTENTFUL_PREVIEW_TOKEN
はプレビュー機能を利用する場合に使うトークンで、どちらも「Settings」から「API keys」のトークン一覧画面で「Content delivery / preview tokens」のタブから作成します。
「Add API Key」を押すとトークンが作成され、「Content Delivery API - access token」と「Content Preview API - access token」が表示されるためそれぞれ上記の .env
ファイルへコピペしてください。
プロジェクトのルートディレクトリに getContentfulEnvironment.js
というファイルを以下の内容で作成します。
require('dotenv').config()
const contentfulManagement = require("contentful-management")
module.exports = function() {
const contentfulClient = contentfulManagement.createClient({
accessToken: process.env.CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN,
})
return contentfulClient
.getSpace(process.env.CONTENTFUL_SPACE_ID)
.then(space => space.getEnvironment(process.env.CONTENTFUL_ENVIRONMENT))
}
次に package.json
の scripts
へ実行時に型定義ファイルを生成する以下のスクリプトを追加します。
{
// ...
"scripts": {
"contentful-typescript-codegen": "contentful-typescript-codegen --output @types/generated/contentful.d.ts"
}
}
最後に npm run contentful-typescript-codegen
もしくは yarn contentful-typescript-codegen
を実行して型定義ファイルを生成します。
これで contentful.d.ts
という名前の型定義ファイルが @types/generated
に作成されているはずです。
型定義ファイルを作成できたら、次は Next.js で Contentful からのレスポンスを取得する方法について見ていきましょう。
まずは utils
フォルダを作成し、 client.ts
というファイルを以下の内容で作成します。
import { createClient } from 'contentful'
const config = {
space: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN
}
export const client = createClient(config)
上記で用意した client.ts
を使用して特定のコンテンツ一覧を取得してみます。
また、ここでは一般的にブログを作る場合によく用いられる post
という Contentful のコンテンツタイプを作成していることを想定しています。
import { GetStaticProps } from 'next'
import { client } from '../utils/client'
import { Entry, EntryCollection } from 'contentful'
import { IPostFields } from '../@types/generated/contentful'
interface Props {
posts: EntryCollection<IPostFields>
}
export default function Home({ posts }){
return (
<>
{posts.map((post: Entry<IPostFields>) =>
<div>
<h1>{post.fields.title}</h1>
<p>{post.fields.body}</p>
</div>
)}
</>
)
}
export const getStaticProps: GetStaticProps<Props> = async () => {
const posts = await client.getEntries<IPostFields>({
content_type: "post",
order: "-sys.createdAt",
})
return {
props: {
posts: posts,
}
}
}
コンテンツ一覧取得に使われる getEntries()
は引数に content_type
を指定することで特定のコンテンツタイプのみを取得することが可能です。
また、order
でソートすることもでき、今回は createdAt
(作成日)の降順でソートをおこなっています。
Entry<IPostFields>
にはコンテンツの内容を保持している fields
の他にシステム的な情報を保持している sys
というプロパティで作成日や更新日などの項目も取得することが可能となっています。
今回は Contentful で型定義ファイルを自動的に生成する方法を紹介しました。
ライブラリを利用することで手動で型定義をする必要なく、快適に TypeScript の恩恵を受けることができます。
今回は簡単な例で紹介しましたが、複雑なモデルになっている場合でもエディターの予測変換に従っていけば目的の項目を見つけられるのはとても便利ですね。
TypeScriptの短絡評価の使い方「&&」「||」「??」の解説
TypeScriptのタイマー関数setTimeoutとsetIntervalの使い方
TypeScriptの多次元配列の使い方についてわかりやすく解説
TypeScriptでのタプルの使い方と実践テクニックを解説
TypeScriptのimport typeをわかりやすく解説
TypeScriptの配列やオブジェクトのソート完全ガイド
TypeScriptコメントアウトの使い方 完全ガイド
TypeScriptのオブジェクトとプロパティの存在チェック完全ガイド
TypeScriptで即時関数を使う方法を解説!基本から実践的な使い方まで