Astro と国産ヘッドレス CMS との接続方法をまとめてみました。

Astro を使って国産ヘッドレス CMS 3製品の接続方法を比較してみた

TL;DR

国産3種類のヘッドレスCMSを利用してブログサイトを想定したページを作成しました。
正直、Astro で構築する範囲では全てのサービスに同じ程度の実装量かなーというのが感想です。静的サイトでの運用を考えると、スラッグ・エイリアス機能のある Spearly / microCMS を利用したほうが覚えやすい URL を生成しやすそうでした。


 SpearlymicroCMSNewt
無料プラン
REST API
SDK JS
SDK JS
(TypeScript)
(※1)
スラッグ
(※2)

×
WebHook


※1 : 全て TypeScript に対応していますが、Spearly 以外は、コンテンツ取得後の型が `any` となり、型エラーの検出が難しかったです。
※2 : 静的サイトのファイル名にコンテンツを識別するためのIDをスラッグとして利用しています。Newt だけがスラッグの概念が無く、固有の識別子 `_id` を利用しています。そのためファイル名が `63a5520c2469ac525533db32.html` のように内容が推測できないものになっちゃいました。


Astro ?

Astro と Spearly を使ったボイラープレート の紹介を参照してください。

一言でいうと静的サイトジェネレーターです!

検証するCMS

今回は、REST API が使える&無料で使える日本製の CMS を対象とています。

microCMS と Newt のフリープランの比較は[【ヘッドレスCMS】microCMS と Newt を比較](https://zenn.dev/ryo555/articles/6fc9ad830c7679)に詳細が書かれています。Spearly の情報が無かったのでフリープランがどうなるか3製品で比較してみました。



Spearly CMS(Free)microCMS (Hobby)Newt (Free)
料金無料無料無料
APIリクエスト数無制限無制限2,000,000
データ転送量 (月毎)25GB20GB100GB
コンテンツ数無制限10,000件無制限
1メディアあたりの容量無制限40MB50MB
API数無制限3個無制限
APIキー数1個1個1個
メンバー数1人3人無制限


Spearly CMS (スピアリー)

https://cms.spearly.com/

国産の CMS ヘッドレスです。扱いやすいシンプルな機能です。埋め込みの簡単な JavaScript タグが用意されていたり、さくらインターネットの「ImageFlux」を使って WebP として画像を配信したりできます。


SDK JS:
https://www.npmjs.com/package/@spearly/sdk-js

microCMS

https://microcms.co.jp/

有名どころなので、紹介は不要だと思います。コンテンツの更新や削除などできるようですが、今回は簡単なコンテンツ取得だけを利用します。

SDK JS:
https://www.npmjs.com/package/microcms-js-sdk

Newt (ニュート)

https://www.newt.so/

国産で2021年に始まったスタートアップのヘッドレス CMS です。

SDK JS:
https://www.npmjs.com/package/newt-client-js

その他国産 CMS

色々ありますが、以下のものは今回は検証の対象外としました。


Astro との通信検証

今回は、Astro で記事リストを作る通信方法を検証してみます。
検証に関して、以下のページを参考にしています。

https://zenn.dev/oxid/articles/8f324a75af6ccf

https://docs.astro.build/ja/guides/cms/contentful/

Spearly CMS

Spearly はコンテンツを API クライアント経由で取得します。await spearlyApiClient.getList("blog") を実行することで、コンテンツのリストを取得できます。

あとは、表示コンテンツに合わせてフォーマットし直すことでリスト表示できるようになります。

js:index.astro 

---
import { spearlyApiClient } from "../lib/spearly"

const contents = await spearlyApiClient.getList("blog")
const posts = contents.data.map(c => {
    const title = c.attributes.fields.data.find(f => f.attributes.identifier === "title")
    const description = c.attributes.fields.data.find(f => f.attributes.identifier === "description")
    const date = c.attributes.fields.data.find(f => f.attributes.identifier === "date")
    const image = c.attributes.fields.data.find(f => f.attributes.identifier === "image")
    const alias = c.attributes.contentAlias
    return {
        title: title?.attributes.value,
        alias,
        description: description?.attributes.value,
        date: date?.attributes.value,
        image: image?.attributes.value
    }
})
---
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Blog</title>
</head>
<body>
    <h1>My Blog</h1>
    <ul>
      {posts.map((post) => (
        <li>
          <img src={`${post.image}`} alt={`${post.description}`} />
          <a href={`/posts/${post.alias}/`}>
            <h2>{post.title}</h2>
          </a>
          <time>{post.date}</time>
          <p>{post.description}</p>
        </li>
      ))}
    </ul>
</body>
</html>

ボイラープレートは以下のレポジトリにあるのでご自由にお使いください。
https://github.com/mantaroh/spearly-astro-boilerplate/

microCMS

Spearly と同じく、コンテンツを API クライアント経由で取得します。await microcmsApiClient.getList({endpoint: 'blogs'}) を実行することで、コンテンツのリストを取得できます。

あとは、表示コンテンツに合わせてフォーマットし直すことでリスト表示できるようになります。
js:index.astro 

---
import { microcmsApiClient } from "../lib/microcms"

const contents = await microcmsApiClient.getList({endpoint: 'blogs'})
const posts = contents.contents.map(c => {
    const title = c.title
    const description = c.description
    const date = c.date
    const image = c.image.url
    const alias = c.id
    return {
        title,
        alias,
        description,
        date,
        image,
    }
})
---
<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>My Blog</title>
  </head>
  <body>
    <head>
     
    </head>
    <h1>My Blog</h1>
    <section class="container">
      <ul>
        {posts.map((post) => (
          <li>
            <figure>
              <img src={`${post.image}`} alt={`${post.description}`} />
            </figure>
            <a href={`/posts/${post.alias}/`}>
              <h2>{post.title}</h2>
            </a>
            <time>{post.date}</time>
            <p>{post.description}</p>
          </li>
        ))}
      </ul>
    </section>
  </body>
</html>

Spearly 同様以下のレポジトリにボイラープレートを用意しているのでお使いください。

https://github.com/mantaroh/microcms-blog-template

Newt

Newet も他の CMS 同様ですが、WordPressのスラッグ、Spearly/microCMS のようなエイリアス・Id という別名の概念が無いため、デフォルトの識別子である `_id` を利用しています。

js:index.astro

---
import { newtApiClient } from "../lib/newt"

const contents = await newtApiClient.getContents({
  appUid: "blog",
  modelUid: "blog"
})
const posts = contents.items.map(c => {
  console.log(c)
    const title = c.title
    const description = c.description
    const date = c.date
    const image = c.image.url
    const alias = c._id
    return {
        title,
        alias,
        description,
        date,
        image,
    }
})
---
<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>My Blog</title>
  </head>
  <body>
    <head>
     
    </head>
    <h1>My Blog</h1>
    <section class="container">
      <ul>
        {posts.map((post) => (
          <li>
            <figure>
              <img src={`${post.image}`} alt={`${post.description}`} />
            </figure>
            <a href={`/posts/${post.alias}/`}>
              <h2>{post.title}</h2>
            </a>
            <time>{post.date}</time>
            <p>{post.description}</p>
          </li>
        ))}
      </ul>
    </section>
  </body>
</html>

こちらも他のCMS同様にボイラープレートを用意しています。
https://github.com/mantaroh/newt-blog-template

まとめ

実装してみて分かったこととしては以下のような事です。



Astro を使ってヘッドレス CMS のブログ運用を行うのであれば、構築にさほど時間はかからないのではないかというのが感想です。Newt だけがスラッグが無いので分かりやすいアドレスの運用が難しいかもしれません。


ぜひ、みなさんも Astro + Spearly などを使ったブログの運用を試してみてください!