Nuxt.js + microCMSで、JAMStackなサークルのHPを作った話

この記事は [Tokyo City University Advent Calender 2022](https://adventar.org/calendars/8133) 4日目の記事です。

## はじめに

はじめまして！

東京都市大学メディア情報学部2年（2022年現在）の木本と申します。
普段はデジタルコンテンツ研究会というサークルで会計をしています。

今年も都市大アドカレが開催されるということで、サークルのHPをNuxt.jsとmicroCMS、Cloudflare Pagesで作ったよ！！という話を書こうかな〜と思います。
「詳しい技術的な話よりは、ふんわり理解してもらおう！」のスタンスで書いたので、技術的なことわかんないよ〜という方も、流し読みでも良いので最後まで見ていただけたら嬉しいです。

## 技術構成

- Nuxt.js
- microCMS
- Cloudflare Pages

## 実際にできたもの

リンク：[https://tcu-dc.net/](https://tcu-dc.net/)
Githubリポジトリ：[https://github.com/TCU-DC/tcu-dc.net/](https://github.com/TCU-DC/tcu-dc.net/)
![FMvem2BVkAEmsl9.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/277ecba4-c87b-0598-0221-e6b2de6cf3e4.jpeg)

## **Jamstack**って何？

- Jamは元々JavaScript/APIs/Markupの略
- 事前に静的なHTMLを生成しておく
    - サイトの表示が高速

事前に静的なHTMLを生成しておく、といきなり言われてもピンとこないと思いますが、Jamstackはこれまで一般的だったサイトの作り方とは異なります。例えば、有名なWordPressでは基本的にアクセスがある度、サーバーサイドでウェブページを作っています。（クライアントサイドレンダリングというのもありますが割愛します）

### サーバーサイドレンダリング（WordPressなど）

- WordPressなどではユーザーがページを要求する度、サーバーでは下記の動作が行われています
    - DBへアクセス
    - DBから取得したコンテンツをもとにページ（HTML）を生成
![77ofh5oGR8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/5ec2735e-92f6-80b7-44d8-0f75eb21217f.png)

### Jamstackで作られたサイト

- ホスティングサービスから、静的なページが返却されている
- ページの表示が速い
    - あらかじめ生成しておいたページを返却するだけ
![35uRZKntGt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/2d9496be-e020-fe1a-4591-9c01d22c079a.png)

## Jamstackのメリット

- 静的なHTMLを返却するので高速
- ウェブサーバーがいらない
- VercelやCloudflare Pagesといった無料のホスティングサービスがある
    - **お金を掛けずにサークルのHPを公開できる！**

## どうやって事前にページを生成するの？

以下の図を見てみましょう。
なんだか難しそうですが、大まかに書くと以下のことを行なっています。

1. microCMSにコンテンツを投稿
2. ページをビルド（microCMSからAPIで取得したものをHTMLに埋め込む）
3. ホスティングサービスにビルドしたファイルを配置
![SLfK9fKgfM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/8e59686b-03a3-da5f-2e6d-c67cd3ebd491.png)

## 1. microCMSにコンテンツを投稿

### 実際のmicroCMSの管理画面

実際にデジコンのサイトの情報を管理しているmicroCMSの画面です。
ここに、HPに載せたいお知らせなどを投稿していきます。GUIになっているので分かりやすいですね。
![J9Sat2DUDx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/275c3bde-d1af-1ae9-d3c1-522967b9fb1d.png)

## 2. microCMSからAPIで取得したコンテンツを、HTMLに埋め込む

### APIからコンテンツを取得

APIを叩いて先ほどの管理画面から投稿した、microCMSのコンテンツを取得します。
実際のコードを下に載せました。この場合だと`return`の中の`top`と`blog`に取得した値が入ることになります。

```jsx
  async asyncData ({ params }) {
    const res = await Promise.all([
      axios.get(process.env.API_BASE_URL + 'top', {
        headers: { 'X-MICROCMS-API-KEY': process.env.MICROCMS_API_KEY }
      }),
      axios.get(process.env.API_BASE_URL + 'blog/', {
        headers: { 'X-MICROCMS-API-KEY': process.env.MICROCMS_API_KEY }
      })
    ])
    return {
      top: res[0].data,
      blog: res[1].data
    }
  },
```

### 実際に取得したmicroCMSのコンテンツ

microCMSから返却されるAPIの実際の値です。
`publishedAt`が公開日、`body`がブログ本文というように、JSONの形式でコンテンツの内容が返却されます。
![GdkWC8kCQx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/51be28e3-535a-e6c0-1aab-702b96f98d9a.png)

### APIから取得したコンテンツを埋め込もう！

コンテンツの公開日やタイトル、本文などをHTMLの中に埋め込んでいきます。
Nuxt.jsの場合は簡単です。`blog.title`（記事タイトル）のような、埋め込みたい名前を`{{  }}`というテンプレート構文で囲みます。

```jsx
<div>
  {{ new Date(blog.publishedAt).toLocaleDateString() }} // 公開日
  <h1>{{ blog.title }}</h1> // 記事タイトル
</div>
```

## 3. ビルド・デプロイ

さて、このように準備したNuxt.jsのプロジェクトをGithubに上げたら準備は完了です。
手順は簡単です。GithubとCloudflare Pagesの連携後、ホストしたいGithubリポジトリを選択して、使っているフレームワーク（ここではNuxt.js）や、環境変数などを設定するだけです。

その後、Cloudflare Pagesがビルド・デプロイを行ない、サイトが公開されます。

### Webhook

実は、このままではコンテンツを更新しても、自動でビルド・デプロイが行われない（＝コンテンツが公開されない）ため、microCMSからCloudflare Pagesにビルド・デプロイを行うようにWebhookで通知する必要があります。が、今回は細かい話になるので省きます…。

## 最後に

簡単な説明でしたが、デジコン（サークル名）のHPの仕組みを、少しでも知っていただけたなら嬉しいです。

さて、明日は都市大アドカレ5日目、都市大クソbot3rdさんによる「都市大クソbot3rd自己紹介　ほか」です。3rdってことは襲名制なんですかね…？ わたし、気になります！
自己紹介ということで、そのあたりの疑問も解消されるのでしょうか？
楽しみですね！

## おまけ：デザイン

### Figmaでデザイン

今回はFigmaでデザインを行いました。
![tFAUv7Xvv5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/bb8e3d86-b259-838e-b1fa-aed7093ffc8d.png)

### コーディング

デザインを実際のCSSに起こす作業を行います。
基本的にFigmaでデザインしたものは自動でCSSに変換できないので、人力でゴリゴリCSSを書いていきます。

下記にスマホのナビゲーションバーのCSSの一部のコードを載せています。
（ロゴと「入会はこちら！」のボタンの部分がある部分ですね）

```css
@media screen and (max-width: 850px) {
  nav {
    z-index: 10;
    text-align: right;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    position: fixed;
    height: 65px;
    top: 0;
    left: 0;
    right: 0;
    background: #fff;
    box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
    border-radius: 0 0 15px 15px;
  }

  nav .button {
    font-size: 14px;
    text-align: center;
    color: #fff;
    text-decoration: none;
    margin-right: 2vw;
    padding: 10px 20px;
    background: #111;
    border-radius: 10px;
    box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
  }
```

### 実際にできたもの

まあまあ再現できたんじゃないでしょうか。
微妙にレイアウト崩れているところがあるので、いつか作り直したいですね…。
より良いデザイン作ってくれる方募集してます。
![Z2AvLbGu2t.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203924/779da688-42d8-0be1-4530-09bf00866da1.png)