microCMS

SvelteKit + microCMS のブログ作成チュートリアル

柴田 和祈

この記事は公開後、1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

待望のSvelteKit 1.0がリリースされましたね!
https://svelte.dev/blog/announcing-sveltekit-1.0

早速、microCMSとの連携を試してみたいと思います。

Svelteとは

ビューを生成するライブラリです。
ReactやVueと異なる点は、ライブラリのコードをほとんど含まないVanilla JSに近い形でコンパイルされるという点です。

そのためコンパイル後のJSファイルのサイズが小さく、高いパフォーマンスが期待できます。

「ライブラリのコードをほとんど含まない」ことを実現するために、SvelteではVirtual DOMを敢えて採用せず、代わりにコンポーネントを非常に効率的な命令型コードに変換して、DOMをピンポイントに更新します。

SvelteKitとは

Svelteと組み合わせて使うアプリケーションフレームワークです。
NextやNuxtのように柔軟なファイルシステムによるルーティングやSSR, SSGをサポートしています。

ビルドツールにはViteが採用されており、プロジェクト作成時には TypeScript / ESLint / Prettier / Playwright / Vitest を追加するかどうか選択することが可能です。

今回はこの SvelteKit と microCMS を組み合わせてブログを作ってみたいと思います。

0. 前提

下記のバージョンで開発を行っています。
バージョンの差異によって機能が異なる可能性があります。

  • Node.js v17.9.1
  • SvelteKit v1.0.0


※ 本記事では最終的にCloudflare Pagesにデプロイするため、そちらで設定可能なNodeバージョンに合わせています

1. プロジェクトを用意する

まずは公式が用意してくれているテンプレートを用いてプロジェクトを作成します。

$ npm create svelte@latest my-app

質問項目にはとりあえず全部載せで下記のように答えました。
最初の質問でテンプレートとして demo app を選択することもできますが、今回は最小構成で挑みたいため Skeleton project を選択しています。

その後、下記コマンドで開発環境を立ち上げましょう。

$ cd my-app
$ npm install
$ git init && git add -A && git commit -m "Initial commit"
$ npm run dev -- --open

このような画面が立ち上がれば成功です。

2. microCMSの用意をする

アカウント登録がまだの方はこちらのドキュメントを参考に、登録を行ってください。
https://document.microcms.io/manual/getting-started

2-1. ブログ用のサービスを作成する

サービス名、サービスIDはよしなに設定してください。

2-2. APIを作成する

ブログ用のテンプレートを選択すると、ブログAPIとカテゴリーAPIが自動的に生成されます。

2-3. コンテンツを作成する

最初からサンプル記事が1つ作成されていますので、さらにもうひと記事追加してもしなくてもどちらでも構いません。
コンテンツ一覧画面にて、画面右上のAPIプレビューをクリックします。
取得ボタンをクリックし、入力内容がAPI経由で取得できるか確認してください(レスポンスJSONが表示されます)。

3. APIキーを環境変数で保護

microCMSではリクエストにAPIキーを含める事で特定のデータを取得できます。
このAPIキーが、GitHubで公開されてしまうのはセキュリティ上よくありません。
そこで環境変数を用いてAPIキーを保護してあげましょう。

.envファイルを作成し、下記の情報を記述します。

MICROCMS_SERVICE_DOMAIN=xxxxxxxxxx
MICROCMS_API_KEY=xxxxxxxxxxxx


MICROCMS_SERVICE_DOMAINはmicroCMSの管理画面URLのサブドメイン部分の値です。
MICROCMS_API_KEYはmicroCMSの「サービス設定 > APIキー」にて確認できます。

.envに記載した変数はプロジェクト内で下記のように参照することができます。

import { MICROCMS_SERVICE_DOMAIN, MICROCMS_API_KEY } from '$env/static/private';


SvelteKitにおける環境変数の参照の仕方についてはこちらをご覧ください。
https://kit.svelte.dev/docs/modules#$env-static-private

4. ブログ一覧を表示する

SvelteKitではファイルベースのルーティングが採用されています。
各ルートディレクトリには、1つまたは複数のルートファイルが含まれ、それらは+の接頭辞で識別することができます。

SvelteKitで画面を作っていく上で、ひとまずこの3つのファイル形式を覚えておくと良いでしょう。

+page.svelte ー 画面の描画を行う
+page.server.ts+page.svelteに渡すデータ処理を行う(サーバーでのみ動く)
+page.ts+page.svelteに渡すデータ処理を行う(クライアント・サーバー双方で動く)

トップページはsrc/routes/+page.svelteです。
ここをブログ一覧画面に作り替えていきたいと思います。

画面を作っていく前に、microCMSからデータを取得する準備をします。
microcms-js-sdkをインストールします。

$ npm install microcms-js-sdk


そしてmicrocms-js-sdkを利用しやすくするためにsrc/lib/microcms.tsを追加しましょう。

import { createClient, type MicroCMSQueries, type MicroCMSImage } from "microcms-js-sdk";
import { MICROCMS_SERVICE_DOMAIN, MICROCMS_API_KEY } from '$env/static/private';
const client = createClient({
  serviceDomain: MICROCMS_SERVICE_DOMAIN,
  apiKey: MICROCMS_API_KEY,
});

//型定義
export type Blog = {
  id: string;
  createdAt: string;
  updatedAt: string;
  publishedAt: string;
  revisedAt: string;
  title: string;
  content: string;
  eyecatch?: MicroCMSImage;
};
export type BlogResponse = {
  totalCount: number;
  offset: number;
  limit: number;
  contents: Blog[];
};

//APIの呼び出し
export const getList = async (queries?: MicroCMSQueries) => {
  return await client.get<BlogResponse>({ endpoint: "blogs", queries });
};
export const getDetail = async (
  contentId: string,
  queries?: MicroCMSQueries
) => {
  return await client.getListDetail<Blog>({
    endpoint: "blogs",
    contentId,
    queries,
  });
};


以上でmicroCMSからデータを取得する準備ができました。

microCMSとの通信処理はAPIキー秘匿の関係上サーバーサイドでのみ行いたいので、今回は+page.server.tsの方を利用します。
よって今回はsrc/routes/+page.server.tsファイルを作成し、microCMSからデータを取得する処理を記述します。

import { getList } from "../lib/microcms";
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async () => {
  return await getList();
};

export const prerender = true;

上記のload関数で返した値は+page.svelte側でdataという変数に割り当てられます。

次に、src/routes/+page.svelteを以下のように書き換えます。

<script lang="ts">
  import type { PageData } from "./$types";
  export let data: PageData;
</script>

<svelte:head>
  <title>Home</title>
  <meta name="description" content="Svelte demo app" />
</svelte:head>

<section>
  <h1>ブログ</h1>
  <ul>
    {#each data.contents as content}
      <li><a href="{content.id}">{content.title}</a></li>
    {/each}
  </ul>
</section>

<style>
  section {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
</style>


以上で一覧ページが表示されるはずです。

型システムについて

SvelteKitでは、npm run dev時に.svelte-kit/typesディレクトリが生成され、src配下のファイル構成に応じて階層ごとに$types.d.tsが自動的に生成される仕組みがあります。
.tsファイル利用時はimport type ...という形で型を割り当ててあげて、.jsファイルにおいてはJSDoc記法で下記のように型を適用するのが良さそうです。

<script>
  /** @type {import('./$types').PageData} */
  export let data;
</script>

なお、.svelteファイルにおいては<script lang="ts">とすることでTypeScriptが動くようになります。

SvelteKitの型システムについてはこちらをご覧ください。
https://kit.svelte.dev/docs/types

5. ブログ詳細を表示する

一覧画面ではブログ記事タイトルをクリックすると/{content.id}に遷移するようにしました。
それに合わせてルーティングをしていきましょう。

新たにsrc/routes/[slug]というディレクトリを作成し、その中に+page.server.ts+page.svelteを用意します。

まずは先ほどと同様+page.server.tsから記述していきます。

import { getDetail } from "../../lib/microcms";
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async ({ params }) => {
  return await getDetail(
    params.slug
  );
};

export const prerender = true;


load関数の引数にはparamsが渡ってくるので、その中からslugを取り出してmicroCMSから該当のコンテンツを取得します。

次に+page.svelte側です。

<script lang="ts">
  import type { PageData } from "./$types";
  export let data: PageData;
</script>

<svelte:head>
  <title>ブログ</title>
  <meta name="description" content="Svelte demo app" />
</svelte:head>

<section>
  <h1>{data.title}</h1>
  <img src={data.eyecatch?.url} alt="" />
  <div>{@html data.content}</div>
</section>

<style>
  section {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
</style>

microCMSから取得してきた記事タイトル、アイキャッチ画像、本文を表示しています。
次のように表示できていれば成功です。


さて、+page.server.tsファイルに次の行があったのをお気付きでしょうか。

export const prerender = true;


これはプリレンダリングを行うかどうかのフラグで、静的ファイルとして配信したい場合はこちらをtrueにします。

コマンドラインにてnpm run buildをしてみると、.svelte-kit/output/prerendered配下にHTMLとSPAでのページ遷移時に用いられるJSONが生成されているのが分かります。

6. ホスティングする

ここまででブログの一覧画面と詳細画面を作ることができました。

あとは作りたいブログのデザインに合わせてスタイルを調整してみたり、microCMSのAPIスキーマをいじって項目を増やしてみたりしてみてください。

最後の仕上げとして作成したものをホスティングします。
今回はホスティングサービスとしてCloudflare Pagesを利用します。
https://pages.cloudflare.com/

まずはここまでの作業内容をGitHubに上げます。
GitHubのリポジトリを作成後、下記コマンドでプッシュしていきます。

$ git add .
$ git commit -m 'add blog'
$ git remote add origin your-repository  // 自分のリポジトリを入力
$ git push -u origin main


そしてCloudflare Pagesにログイン後、「プロジェクトを作成 > Gitに接続」を選択して先ほど作成したリポジトリと連携します。


ビルド設定ではフレームワークとしてSvelteKitを選択し、環境変数のセットを行います。(.envの内容)

現時点(2022/12)ではCloudflare Pagesのデフォルトで使用されるNodeバージョンが低いのでビルドが失敗してしまうため、環境変数にNODE_VERSION=v17.9.1をセットします。(現時点での最大バージョン)

※できればローカル環境のNodeバージョンも合わせた方が良いと思います

デプロイをスタートし、無事完了すればCloudflare Pagesのドメインでアクセスできるようになります。

Webhookの設定

現状ではGitHubにソースコードをPushするたびにビルド&デプロイがされますが、microCMSの記事を追加・更新してもビルドはされません。
そこで、microCMSのWebhook機能を使って、記事の追加・更新のたびにCloudflare Pagesでビルド&デプロイがされるように設定しましょう。

設定方法は下記の記事で紹介しているので参考にしてみてください。
https://blog.microcms.io/webhook-cloudflare-vercel/

設定後に新しく記事を公開してみて、Cloudflare Pagesのビルドが動き出したら成功です。

おわりに

microCMSとSvelteKitを用いてJamstack構成のブログを作成しました。
SvelteKitはSSRとSSGをprerender=true/falseによって簡単に切り替えられるため、サービス要件に合わせてSSRとSSGを柔軟に組み合わせることができそうだなと思いました。

また、TypeScriptの導入がスムーズにでき、型定義の自動生成の仕組みもあって便利だなと感じました。

気になった方はぜひ試してみてください!

-----

microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitterお問い合わせからお気軽にご連絡ください!
microCMSコミュニティへのご参加も大歓迎です。
引き続きmicroCMSをよろしくお願いいたします!

まずは、無料で試してみましょう。

APIベースの日本製ヘッドレスCMS「microCMS」を使えば、 ものの数分でAPIの作成ができます。

microCMSを無料で始める

microCMSについてお問い合わせ

初期費用無料・14日間の無料トライアル付き。ご不明な点はお気軽にお問い合わせください。

お問い合わせ

microCMS公式アカウント

microCMSは各公式アカウントで最新情報をお届けしています。
フォローよろしくお願いします。

  • X
  • Discord
  • github

ABOUT ME

柴田 和祈
microCMSのデザイン、フロントエンド担当 / ex Yahoo / 2児の父 / 著書「React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで 」 / Jamstack