at backyard

Color my life with the chaos of trouble.

Headless CMS の Contentful からデータを取得して、Next.jsのページで表示させるメモ

完全なる備忘録です。

Next.js 9 with TypeScript セットアップ

最近 Next.js 9 を余暇を利用して触っているので、今回はそちらの環境のセットアップから行います。
ちなみに最初からTypeScriptで書けるように設定していきます。

以前Qiitaに書いたNext.jsでmeta情報をSSRするを参考にしています。

必要なライブラリをインストール

yarn add next@latest react@latest react-dom@latest

--dev つけて下記もインストールする必要があります。

yarn add --dev typescript @types/react @types/node

必要なディレクトリとファイルを作っていきます。

mkdir pages
vim pages/index.tsx

シンプルに Hello World と表示させてみます

export default () => <p>Hello World</p>;

開発用のサーバを立ち上げます。

yarn next dev

セットアップはここまで

Contentful セットアップ

次に 上でセットした Next.js アプリ上から Contentful のコンテンツを参照していきます

下記の公式ドキュメントを参照していきます。

https://contentful.github.io/contentful.js/contentful/7.10.0/

まずはcontentfulのnpmパッケージをインストール

yarn add contentful

次にcontentfulのSpace IDとaccess tokenを使って、実際にコンテンツを取得していきます
ここではContentfulでアカウントを作ったときに最初から用意されているThe example projectを使ってコンテンツを取得していきます。

なお、Space IDとAccess Tokenは下記から

f:id:shinshin86:20190919221500p:plain

Entry IDはエントリー画面の下記のボタンから確認できます。

f:id:shinshin86:20190919221515p:plain

取得サンプルは下記となります。 (ここではNode.jsのスクリプトとして一旦書いています)

const contentful = require("contentful");

(async () => {
  const space = "SPACE_ID";
  const accessToken = "ACCESS_TOKEN";
  
  const client = contentful.createClient({ space, accessToken });

  const entryId = "ENTRY_ID";
  const entry = await client.getEntry(entryId);
  console.log(entry); // 対象のEntry内容を取得できる
})();

Next.js上でContentfulのコンテンツを、SSRした状態で表示させる

ここまでくれば、あとはNext.jsで描画させた際にContentfulからコンテンツを取得して描画すればよいだけです。

pages/index.tsxを下記のように編集します。

const contentful = require("contentful");

const Index = ({ title, createdAt }) => (
  <div>
    タイトル: {title}<br />
    作成日: {createdAt}
  </div>
)

Index.getInitialProps = async () => {
  const space = "SPACE_ID";
  const accessToken = "ACCESS_TOKEN";
  
  const client = contentful.createClient({ space, accessToken });

  const entryId = "ENTRY_ID";
  const entry = await client.getEntry(entryId);
  return ({ title: entry.fields.title, createdAt: entry.sys.createdAt });
};

export default Index;

これでyarn next devしてlocalhost:3000にアクセスすると、タイトルと作成日にContentfulからの値が格納されています。
またgetInitialProps内で値を取得しているため、SSRもできています。
HTMLのソースコードを表示すると、ソース内に取得したContentful内のデータが取得できているのが確認できます。

おっと、そういえばTypeScriptを使えるように設定していて、ファイルもindex.tsxとしていたのに、普通にjsで書いていました。
後ほど、TypeScriptに書き直したものを追記します。

が、もう体力ゼロになってきたので、今日はこのへんで。。

TypeScriptで書き直しました

const contentful = require("contentful");

interface entryObj {
  title: string;
  createdAt: string;
}

const Index = ({ title, createdAt }: entryObj) => (
  <div>
    タイトル: {title}<br />
    作成日: {createdAt}
  </div>
)

Index.getInitialProps = async (): Promise<entryObj> => {
  const space = "SPACE_ID";
  const accessToken = "ACCESS_TOKEN";
  
  const client = contentful.createClient({ space, accessToken });

  const entryId = "ENTRY_ID";
  const entry = await client.getEntry(entryId);
  return ({ title: entry.fields.title, createdAt: entry.sys.createdAt });
};

export default Index;