LoginSignup
70
39

More than 1 year has passed since last update.

microCMS & Astro で永久0円のJamstack爆速ブログを作成する丁寧なハンズオン

Last updated at Posted at 2022-11-30

アイレット株式会社 22新卒 Advent Calendar 2022 1日目の投稿です!
社外へアウトプットする習慣を作ることを目的として、このアドベントカレンダーを企画しました:raised_hands:
同期25人で最後まで完走することを目標に頑張ります!

概要

このハンズオンでは、microCMS・Astro・Vercelを利用し、永久0円の個人ブログを作成します。

所要時間

1 時間

流れ & 学べること

  1. 前知識 : 必要な知識を確認します。
  2. microCMS : microCMS の会員登録 / サービスを作成します。
  3. Astro : Astroプロジェクトを作成し、microCMSと連携します。
  4. Vercel : Vercelにデプロイし、microCMSとのデプロイフック連携をします。

前知識

なぜ 0円 なのか

このハンズオンでは、記事の管理(CMS)に microCMS、ブログのデプロイに Vercel という SaaS (Software as a Service) を利用します。
いずれのサービスにも、一定の利用量までは無料の 無料枠 が設定されており、個人ブログの利用範囲では無料枠を超えないため、無料で利用することができます。

microCMS とは

microCMSは、国産のヘッドレスCMSです。
ヘッドレスCMSとは、Wordpressのような従来のCMSが有していた「コンテンツ管理」「HTML生成」の2つの責務を切り分け、「コンテンツ管理」の部分だけをAPIで提供するものです。
SaaSとして提供されるので、サーバを用意する必要はありません
多く存在するヘッドレスCMSの中でも microCMS のメリットは、コンソールが日本語対応しており、無料枠が広いことです。
image.png

Astro とは

Astro は、2022年8月に正式リリースされたばかりの静的サイトジェネレータです。
現時点で静的サイトを生成する方法としては Next.js などの SSG が採用されることが多いかと思いますが、Astro は Next.js などと比べて生成されるコードに含まれるJavaScriptが圧倒的に少なく、非常に高速であることをアピールしています。
また、コンポーネントごとに React / Vue / Svelte などを自由に組み合わせて使うことができます。(使いどころはわからないですが)
一番似ている競合は Gatsby だと思いますが、個人的には Gatsby よりかなり使いやすい印象を受けました。
image.png

Jamstack とは

Jamは、JavaScript/APIs/Markup の頭文字のようです。
ググって出てくる解説では定義に揺れが見えますが、一般的に、ヘッドレスCMSと静的サイトジェネレータの組み合わせでコンテンツを配信するアーキテクチャを指します。
配信されるのは静的なHTMLファイルなので、CDNにもキャッシュされ、高速に配信されます。
一方、更新のタイムラグが発生するので、ニュースサイトなどリアルタイムな更新が必要なケースには向かない場合があります。
image.png

Vercel とは

Vercelは、Webホスティングサービスです。
GitHubと連携することで簡単にWebアプリケーションをデプロイできます。
無料枠も趣味で利用するなら十分です。
デフォルトでCDNを介して配信されるので、とても高速です。
ちなみに、Next.js も Vercel が開発していて、Next.js の ISR にも対応しています。


ではさっそく、ハンズオンを始めましょう!:v:

microCMS

microCMSに登録する

microCMSの登録画面にアクセスして、メールアドレスとパスワードを入力します。

microCMS 登録画面

質問が表示されるので回答します。
microCMS 2

こんな感じの画面になるので、Startを押下します。
microCMS 3

サービスを作成する

作成するサービス名、サービスIDが求められるので、任意の名前を入力して Create Service を押下します。
私は、サービスIDを michinosuke-blog としてみました。
microCMS 4

入力したIDが登録できると、サービスが作成されます。
microCMS 5

Blog APIを作成する

作成する API のテンプレートを選択する画面になるので、今回は Blog を選択します。
microCMS 6

しばらくローディングを待つと、次のような画面になります。
すでにサンプルとして、 (Sample) First, open this article というタイトルの記事が登録されていることがわかります。
microCMS 7

日本語化する

左下のアイコンを押下し、「Language」 を選択して、プルダウンから日本語に変更してから Save changes を押下します。
スクリーンショット 2022-11-20 4.51.01.png

APIを叩く

1個のAPIキー というタブを選択すると、次の画面に遷移します。
APIキー名 default の APIキー を copy を押下して、キーをコピーします。
スクリーンショット 2022-11-20 5.12.03.png

jq コマンドをインストールしていない場合は、あらかじめ次のコマンドを実行してインストールしておきます。

$ brew install jq

ターミナルを開き、次のコマンドを実行します。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx の部分は、先ほどコピーしたAPIキーに置き換えてください。
michinosuke-blog の部分も、ご自身のサービスIDに置換してください。

$ curl "https://michinosuke-blog.microcms.io/api/v1/blogs" -H "X-MICROCMS-API-KEY:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | jq

すると、以下のような jsonレスポンスを得られます。

{
  "contents": [
    {
      "id": "ch25b_0q5q",
      "createdAt": "2022-11-19T19:35:59.979Z",
      "updatedAt": "2022-11-19T19:35:59.979Z",
      "publishedAt": "2022-11-19T19:35:59.979Z",
      "revisedAt": "2022-11-19T19:35:59.979Z",
      "title": "(Sample) First, open this article",
      "content": "<h2 id=\"h2cec5766ea\">Created from a blog template🎉</h2><p>Created API from blog template. <br>Excellent job🎉<br></p><h2 id=\"h72c53f91f1\">Try Preview API🚀</h2><p>Let's try Preview API first. <br> The content you submit is retrieved via API and connected to the View. <br>The Preview API allows you to see the actual API response and accelerate your development. <br><br>👇Click here first. <br><img src=\"https://images.microcms-assets.io/assets/59d6f83d54a54444818f0f93961eab8f/6ea8d5840938412b988aeea8e9b5f247/blog-template-description1.png\" alt=\"\"><br><br>When the Preview API screen opens, click<strong> Get </strong>button to try out the request.<br><img src=\"https://images.microcms-assets.io/assets/59d6f83d54a54444818f0f93961eab8f/20545be1aa97451f878f65da35332792/blog-template-description2.png\" alt=\"\"><br><br>You can see that the contents of this article can be retrieved via the API.<br><img src=\"https://images.microcms-assets.io/assets/59d6f83d54a54444818f0f93961eab8f/cfc8d8829f824d56b726c4030bdef38c/blog-template-description3.png\" alt=\"\"></p><h2 id=\"h35257771a7\"><br>What to do next? 🏃</h2><p>Build your own website using the responses you see in the Preview API.<br>microCMS retrieves content via API, so you can build screens in your favorite language and framework. <br></p><ul><li><a href=\"https://document.microcms.io/tutorial/javascript/javascript-top\" target=\"_blank\" rel=\"noopener noreferrer\">JavaScript SDK</a></li><li><a href=\"https://document.microcms.io/tutorial/nuxt/nuxt-top\" target=\"_blank\" rel=\"noopener noreferrer\">Nuxt SDK</a></li><li><a href=\"https://document.microcms.io/tutorial/gatsby/gatsby-top\" target=\"_blank\" rel=\"noopener noreferrer\">Gatsby SDK</a></li></ul><p><br>Additionally, <a href=\"https://microcms.io/features/sdk\" target=\"_blank\" rel=\"noopener noreferrer\">server-side SDKs (PHP / Go / Ruby) and mobile SDKs (iOS / Android)</a> are also available.<br><br>Please feel free to reach out to us if you have any problems or questions. <br><br>Support: <a href=\"mailto:support@microcms.io\" target=\"_blank\" rel=\"noopener noreferrer\">support@microcms.io</a><br>Frequently Asked Questions: <a href=\"https://help.microcms.io/ja/knowledge\" target=\"_blank\" rel=\"noopener noreferrer\">https://help.microcms.io/ja/knowledge</a></p>",
      "eyecatch": {
        "url": "https://images.microcms-assets.io/assets/59d6f83d54a54444818f0f93961eab8f/4d80c8ec72754b38aef5b0eceeca0035/blog-template-en.png",
        "height": 630,
        "width": 1200
      },
      "category": {
        "id": "120hydnnx7m",
        "createdAt": "2022-11-19T19:35:57.241Z",
        "updatedAt": "2022-11-19T19:35:57.241Z",
        "publishedAt": "2022-11-19T19:35:57.241Z",
        "revisedAt": "2022-11-19T19:35:57.241Z",
        "name": "Update Information"
      }
    }
  ],
  "totalCount": 1,
  "offset": 0,
  "limit": 10
}

なお、APIのテスト実行は、コンソール画面右上の APIプレビュー からも行うことができます。
スクリーンショット 2022-11-20 6.32.14.png

Astro

Astroプロジェクトを作成する

npm の create コマンドでAstroプロジェクトの雛形を作成します。
今回は pnpm 使ってみます。

$ pnpm create astro@latest

? Where would you like to create your new project? › astro-blog-example
✔ How would you like to setup your new project? › a personal website starter kit
✔ Would you like to install pnpm dependencies? (recommended) … yes
✔ Would you like to initialize a new git repository? (optional) … no
✔ How would you like to setup TypeScript? › Strict

╭─────╮  Houston:
│ ◠ ◡ ◠  Good luck out there, astronaut!
╰─────╯

Houston は メジャーリーグのヒューストン・アストロズのパロディでしょうか?

GitHubリポジトリを作成する

Astro のインストールが終わったら、VSCode で開きます。

$ code astro-blog-example

ソース管理タブを開いて、GitHubに公開 を押下し、GitHubにパブリックリポジトリを作成します。

スクリーンショット 2022-11-21 0.20.34.png

Astroを実行してみる

Astroを実行してみます。

$ pnpm run dev

  🚀  astro  v1.6.10 started in 250ms
  
  ┃ Local    http://127.0.0.1:3000/
  ┃ Network  use --host to expose

それから、http://localhost:3000 にアクセスしてみます。
こんなページが表示されたら成功です。

スクリーンショット 2022-11-21 0.27.24.png

http://localhost:3000/blog にアクセスすると、サンプルの記事一覧が表示されます。
ここの記事を、microCMS で管理された記事に置き換えるのが目標です。
スクリーンショット 2022-11-21 0.30.29.png

これは、src/pages/blog.astro の以下の部分で、マークダウンファイルを読み込んでいるので、これを microCMS からフェッチするように変更することで実現できます。

src/pages/blog.astro
// Use Astro.glob() to fetch all posts, and then sort them by date.
const posts = (await Astro.glob('./blog/*.{md,mdx}')).sort(
	(a, b) => new Date(b.frontmatter.pubDate).valueOf() - new Date(a.frontmatter.pubDate).valueOf()
);

microCMSと連携する

プロジェクトの package.json と同じ階層に、.env ファイルを作成して、以下の内容を書き込みます。
michinosuke-blog はあなたが作成した microCMS のサービスIDに、xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx の部分は、あなたが作成したAPIのキーに置き換えてください。

MICROCMS_SERVICE_DOMAIN=michinosuke-blog
MICROCMS_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

microCMS は JavaScript用SDK を公開してくれているので、インストールします。

$ pnpm install microcms-js-sdk

src/library/microcms.ts ファイルを作成し、以下を書き込みます。

src/library/microcms.ts
import { createClient, MicroCMSQueries } from "microcms-js-sdk";
const client = createClient({
  serviceDomain: import.meta.env.MICROCMS_SERVICE_DOMAIN,
  apiKey: import.meta.env.MICROCMS_API_KEY,
});

export type Blog = {
  id: string;
  createdAt: string;
  updatedAt: string;
  publishedAt: string;
  revisedAt: string;
  title: string;
  content: string;
  eyecatch: {
    url: string;
    height: number;
    width: number;
  };
};
export type BlogResponse = {
  totalCount: number;
  offset: number;
  limit: number;
  contents: Blog[];
};

export const getBlogs = async (queries?: MicroCMSQueries) => {
  return await client.get<BlogResponse>({ endpoint: "blogs", queries });
};
export const getBlogDetail = async (
  contentId: string,
  queries?: MicroCMSQueries
) => {
  return await client.getListDetail<Blog>({
    endpoint: "blogs",
    contentId,
    queries,
  });
};

それから、src/pages/blog.astro の上部を以下のように編集します。

src/pages/blog.astro
---
import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import { SITE_TITLE, SITE_DESCRIPTION } from '../config';

//microCMS呼び出し
import { getBlogs } from "../library/microcms";
const { contents: posts } = await getBlogs({ fields: ["id", "title", "publishedAt"] });
---

また、posts.map しているところも、下のように置き換えます。

src/pages/blog.astro
<ul>
	{
		posts.map((post) => (
			<li>
				<time datetime={post.publishedAt}>
					{new Date(post.publishedAt).toLocaleDateString('ja-JP')}
				</time>
				<a href={`/blog/${post.id}`}>{post.title}</a>
			</li>
		))
	}
</ul>

改めて、Astroを起動して、http://localhost:3000/blog にアクセスします。

$ pnpm run dev

そして、以下のように microCMS のサンプル記事 (Sample) First, open this article が表示されていれば成功です!:tada:

スクリーンショット 2022-11-21 2.20.28.png

ただ、現状だと、記事タイトルをクリックしても、404: Not found になってしまいます。

スクリーンショット 2022-11-21 3.09.05.png

プロジェクトにテンプレートで生成されているように、記事の詳細ページは src/pages/blog/ 配下にファイルを配置することで、静的に生成することができます。

しかし、今回は microCMS に存在する投稿によって、動的にページを生成する必要があるため、変更が必要です。

src/pages/blog/[blogId].astro ファイルを作成し、以下の内容を書き込みます。

src/pages/blog/[blogId].astro
---
import Layout from "../../layouts/BlogPost.astro";
import { getBlogs, getBlogDetail } from "../../library/microcms";

// 生成する記事のIDを全て取得
export async function getStaticPaths() {
  const response = await getBlogs({ fields: ["id"] });
  return response.contents.map((content: any) => ({
    params: {
      blogId: content.id,
    },
  }));
}

//記事の詳細情報を取得
const { blogId } = Astro.params;
const blog = await getBlogDetail(blogId as string);
---

<Layout content={{
    title: blog.title,
    description: '',
    heroImage: blog.eyecatch?.url ?? '',
    pubDate: new Date(blog.publishedAt).toLocaleDateString('ja-JP'),
    updatedDate: new Date(blog.updatedAt).toLocaleDateString('ja-JP'),
}}>
  <main set:html={blog.content} />
</Layout>

再度、http://localhost:3000/blog にアクセスし、記事タイトルをクリックしてみます。
すると、このように記事ごとの詳細ページが生成されていることが確認できます!:tada:
スクリーンショット 2022-11-21 3.31.06.png

これでAstro実装は終了したので、microCMSとの連携 のようなメッセージでGitにコミットし、GitHubにプッシュしておきます。

Vercel

Vercel にデプロイ

Vercel にログインし、New Project を選択します。

Continue with GitHub を選択し、Astro をプッシュしたリポジトリを import します。
スクリーンショット 2022-11-21 3.40.11.png

任意のプロジェクト名を入力し、環境変数 MICROCMS_SERVICE_DOMAINMICROCMS_API_KEY を設定します。このキーと値は、.env ファイルに設定しているものと同じです。
Deploy を押下すると、ブログがデプロイされます。
スクリーンショット 2022-11-21 3.45.40.png

このような画面になれば、デプロイ成功です!:tada:
スクリーンショット 2022-11-21 3.48.26.png

スクリーンショットの部分を押下すると、ブログにアクセスできます。

デプロイフックを作成

Vercelのプロジェクト詳細のページから、Setting > Git に遷移します。
Deploy Hooks という項目があるので、任意の名前と、デプロイするブランチ名を指定して、Create Hook を押下します。
ここでは、microCMS という名前で master ブランチをデプロイするデプロイフックを作成しています。
スクリーンショット 2022-11-21 3.53.57.png

デプロイフックURLが生成されるので、Copy ボタンを押下してコピーします。
スクリーンショット 2022-11-21 3.54.17.png

microCMSにデプロイフックを設定

microCMSのコンソールにアクセスし、右上の API設定 を押下し、Webhook タブを選択します。
スクリーンショット 2022-11-21 3.59.00.png

+追加 ボタンを押下すると、「サービスの選択」 ポップアップが表示されるので、Vercel を選択します。
スクリーンショット 2022-11-21 3.59.18.png

任意の名前と、先ほどコピーした Vercel のデプロイフックURLをペーストして、下部の 設定する ボタンを押下します。
スクリーンショット 2022-11-21 4.01.06.png

これで、microCMS で記事を作成すると、自動で Vercel にブログが再デプロイされるようになりました!:tada:

記事を作成してみる

microCMS コンソール右上の +追加 ボタンを押下します。

スクリーンショット 2022-11-21 4.06.49.png

適当なタイトル、コンテンツ、サムネイルを設定して、右上の 公開 ボタンを押下しましょう。
それから、再度 Vercel にデプロイしたブログのURLにアクセスしてみると、新しく追加した記事が一覧に表示されているはずです!
なお、microCMSコンソールで記事を作成してからブログに反映されるまで、数十秒のラグがあります。
スクリーンショット 2022-11-21 4.15.20.png

詳細ページも生成されています。
スクリーンショット 2022-11-21 4.18.01.png

さいごに

おつかれさまでした!:tada: :confetti_ball:

この記事の内容は、個人ブログの他にも、

  • 店舗ホームページのニュース投稿をクライアントにやってもらう
  • イベントのバナーをCMSで管理する
  • 利用規約を再ビルドなしで更新できるようにする

など、応用できると思います。

Lighthouseでパフォーマンス計測しましたが、さすがAstroは爆速でした!:clap:
スクリーンショット 2022-11-21 4.54.33.png

アイレット株式会社 22新卒 Advent Calendar 2022 明日の記事は、@suraiくんの『Hello AWS SAM World!!』です!
お楽しみに!!

70
39
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
70
39