Gatsby + Contentful + Netlifyのポートフォリオサイトを作って、QiitaとDev.toの記事を読み込んでみた


## 何のための記事？

- 備忘録
- Gatsbyでポートフォリオサイトを作るのが割とサクッとできたことを伝えたい

※細かい環境構築は説明しません。

## 自己紹介

プログラミング歴1年半の美容師。ウェブサイト、業務アプリ、ウェブサービスの開発経験あり。  
現在エンジニアになるべく転職活動中

## きっかけ

エンジニアへの転職を決意し、ウェブサービスやアプリの開発、記事投稿などを始めていた。それらを一つのウェブサイトにまとめると、自己アピールにとても便利なのではないかと考えた。

## 技術選定

Nextjs の経験はあったので、Nextjsとよく比較されるGatsbyに挑戦してみたかった。GraphQLも面白そう！  
なるべく早くポートフォリオサイトを作って転職活動をスムーズに進めたかったので、スターターキットが豊富で設定周りをうまくやってくれるというのもポイント。  
Contentful と Netlifyは他のCMSやホスティングサービスと比較しても無料枠が大きめでメジャーであることから個人サイトには合っていると考えた。

## 成果物

[ポートフォリオサイト](https://ko-engineer.net)

## Gatsby プロジェクト作成

[Gatsbyjs](https://www.gatsbyjs.com)

GatsbyjsはReactで作る静的サイトジェネレーター。ビルドしたら静的ファイルのみになり、ホスティングが楽。かつ、ワードプレスのようにスターターキットが豊富で素早く高パフォーマンスのウェブサイトが構築できるという理解。

今回はこちらのスターターキットを使用。

[gatsby-starter-mate](https://www.gatsbyjs.com/starters/EmaSuriano/gatsby-starter-mate/)

Contentful, Typescript対応。Netlify Deployment Friendlyとの記載もあったのでこちらを選択。レビューの★も多かったし。

コマンドラインで`gatsby new <プロジェクト名> <パス>`であっという間に雛形が完成。最初に`yarn`と`npm`どっち使うの？と聞かれたので使い慣れているnpmにした。

## Contentful アカウント登録

[Contentful](https://www.contentful.com)

非常にメジャーなCMS。用途に応じて様々なフィールドを追加、カスタマイズできる。サーバーサイドをこちらに任せることでフロント側Gatsbyでデータを読み込むだけでOK。サイトは日本語に対応してないが、CMS内では日本語に対応させられる。

まず、アカウント作成後に「スペース」を作る。

この「スペース」一つのサービスに紐づくものだということか。

## Gatsbyjs から Contentfulを読み込む

スターターキットのおかげで細かい設定は`npm run setup` のコマンドで以下3つ値をContentfulから以下を確認して入力するだけ。

- Space ID
- Content Delivery API - access token
- Personal Access Token

これで`gatsby develop` するとあっという間に連携完了が確認できた！！

※ 私の設定なのか、選んだスターターキットのアップデートが追いついてないのかわからないが、最初GraphQLのqueryがおかしい場所があってエラーが出た。修正したら正常に動作した。

## Netlifyの登録

[Netlify](https://www.netlify.com)

Netlifyは静的サイトのホスティングサービス。紐付けられたGithubにpushされると自動でデプロイされる。

アカウント登録後、GitHubのどのリポジトリを紐付けるか選択する。  
これだけで後はうまくやってくれる...？

ひかかったところが2つあった。

#### Netlifyの環境変数を設定

先ほどと同じです。

- Space ID
- Content Delivery API - access token

#### ビルドコマンド 

`Error: Cannot find module './about.json'`のえらーがでた

`gatsby build` から `npm run get-about && gatsby build` にした。

これらを設定後 masterにpushしたら。。。

![デプロイ完了](https://i.imgur.com/oj0468v.png)

慣れたらここまで1時間もかからなそう！

## Qiita APIを使ってGatsbyで記事を読み込む

Qiitaの記事をGatsbyでGraphQLを使わずに取得して表示させたい。~~GraphQLとintegrateするのは大変そうだったから...。~~

流石エンジニア向けのプラットフォーム読みやすいドキュメント、わかりやすいAPIを用意してくださっている。

[Qiita API v2](https://qiita.com/api/v2/docs)

>利用制限
認証している状態ではユーザごとに1時間に1000回まで、認証していない状態ではIPアドレスごとに1時間に60回までリクエストを受け付けます。

認証なしでも使えるが、一時間に60回ってちょっと微妙か？  
認証のためのトークンはQiitaの「設定」 → 「アプリケーション」から取得しておいた。

gatsby-node.jsファイルがなければ作って、以下のように設定すると該当ページのpageContextで取得できる。

```Javascript:gatsby-node.js

exports.createPages = async ({ actions: {createPage} }) => {
  const header = {
    headers: {
      Authorization: `Bearer ${process.env.QIITA_TOKEN}`, // トークンをヘッダーにセット
    },
  };
  const res = await fetch(
    'https://qiita.com/api/v2/authenticated_user/items', // authenticated_userで認証されたユーザーの記事を取得できる
    header,
  );

  const json = await res.json();
  
  const qiitaData = {
    // 取得したデータを加工
    title: json.title,
    // (略)
  }

  createPage({
      path: "/", // この場合トップページの pageContextで取得できる
      component: path.resolve("./src/templates/index.tsx'"),
      context: {
        qiitaData
      },
  })
}

```

※今回使用したgatsby-starter-mateではフォルダ構成が`./src/templates/index.tsx`ではなく`./src/pages/index.tsx`になっていて、これだと動かなかった。気づくまで時間がかかったなぁ...。

参考
[Why Gatsby Uses GraphQL](https://www.gatsbyjs.com/docs/why-gatsby-uses-graphql/)  
[How to use Restful API when createPages](https://github.com/gatsbyjs/gatsby/issues/23902)

## Dev API

Dev.toという英語版Qiitaのようなウェブサービスがあって、英語でプログラミング関連のことを検索するとヒットする。

[Dev.to](https://dev.to)

こちらでも記事を書いたことがあったので（~~この記事を執筆時点でQiitaの英訳記事1つだけ~~）こちらもポートフォリオサイトへ読み込んでみたいと思いAPIを調べてみた。

[DEV API (beta)](https://docs.dev.to/api/)

Qiitaに負けず劣らずシンプルで使いやすい。ドキュメントは英語でも非常に読みやすい。

こちらはTOKENなしで記事の読み込みが制限無しでできるかな？（記載を見つけられなかった）

gatsby-node.jsから、こちらも一緒にcontextに入れてあげる

```Javascript:gatsby-node.js

exports.createPages = async ({ actions: {createPage} }) => {
  
  // 省略

  const res2 = await fetch(
    'https://dev.to/api/articles?username=kazuhideoki',
  );
  const json2 = await res2.json();

  const devData = {
    // 取得したデータを加工
  }

  createPage({
      path: "/",
      component: path.resolve("./src/templates/index.tsx"),
      context: {
        qiitaData,
        devData // 一緒にcontextに入れる
      },
  })
}

```

これでサクッと両サイトから記事の読み込みをすることができた。

## パフォーマンス

なかなか良い！！以前ワードプレスでウェブサイトを立ち上げたことがあったが、こんな数字は見たことないなぁ。

![スクリーンショット 2020-12-04 7.51.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558894/5d4e0325-a2f9-b670-ee45-38084f2c21ad.png)


## 感想 まとめ

- Gatsbyを利用するとスターターキットのおかげで、少し設定すればすぐに使える形になって良い。デザインからCMSとの連携、デプロイ周りまでスターターキットが面倒を見てくれるのはありがたい。
- ContentfulもNetlifyもたくさん使われているだけ合って、使い勝手もカスタマイズ性も洗練されている印象。
- GatsbyにはGraphQLを使わなくてもRESTでデータを読み込んで、それをもとに静的サイトを生成してくれる機能もある。

さて、最低限のサイトができたので、ぼちぼち細かいところを修正していきます。

Gatsby楽しい！！