待望の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をよろしくお願いいたします!