SvelteKit＋microCMSでブログサイトを作ってみる 


## 簡単に自己紹介
はじめまして。しゃもキットです。  
書いてみたいという気持ちは前からあったのですが、なかなか勇気が出ずこれが初めての投稿です。よろしくお願いします！

* Web制作会社勤務5年ほど
* ねこが好き
* 実務で触っているのはgulp,SCSS,WordPress,jQuery,Laravel
* 趣味程度にVue、Nuxt　ReactとTypeScriptはのんびり勉強中

うちのねこ
https://www.instagram.com/hokke_to_unagi/

## 本題
みなさん、個人ブログ、持ってますか？  
技術ブログサイトを作ってみたい 情報発信してみたいと思いつつ見る専になっているエンジニアも多いのではないでしょうか。

普段企業さんのサイトを作ることが多いのですが、その時使うCMSで圧倒的に多いのがWordPressです。  
慣れているWordPressで個人ブログを作るのもありですが、どうせならはやりの技術で作ってみたいのがエンジニアというもの。  

そこで今回はタイトルにある通り、

* microCMS(HeadlessCMS)
* SvelteKit(Svelte)

で個人ブログを作ってみることにします！


## 環境

* node v14.16.1
* npm 6.14.12

## microCMSのアカウント作成
### microCMSって？

https://microcms.io/

推しHeadlessCMSです。  
HeadlessCMSっていうのは簡単に言うと管理画面とデータ取得用のAPIが用意されていて、view側が用意されていないCMSです。

ブログを書きたい程度であればデータだけとってきて静的サイトジェネレータでページを生成してしまえばいいですし、HeadlessCMSを使うほうがスマートでしょう。

無料プランがあるのでとりあえず登録してみます。

### アカウントを作成する
アカウントを作成しましょう。  
アカウントの作成方法はすごくわかりやすく解説されているので僕が説明するまでもないでしょう！  
解説ページをご覧ください。

https://document.microcms.io/manual/signup

### コンテンツ(API)作成
WordPressでいうところの投稿タイプ作成みたいなものです。

APIは以下のように「ブログ」と「タグ」を作成しました。

![スクリーンショット 2021-09-20 152409.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1677134/1b5cd1ff-2923-5fbd-0157-dfe936469355.png)
![スクリーンショット 2021-09-20 152435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1677134/f5ae8193-163a-5d48-22cb-bc42545929bb.png)


とりあえずこれで準備はほぼ完了です。  
あとはX-API-KEYをヘッダーにつけてgetリクエストを送ればデータがjsonで返ってきます。  
**キーの確認は以下の「API-KEY」から確認できます。**
![スクリーンショット 2021-09-20 153027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1677134/5578e653-8016-cfa9-9401-fdf3b90ebb91.png)

WordPressだとインストールしてからプラグインを入れたりいろいろ設定しないといけないのでこの辺地味にめんどくさいのですが、最初から大体やりたいことができるように用意されているとすごく便利ですね。  
プラグインのバージョンやPHPのバージョンなどを気にする必要がないというだけで気持ちが楽になるのは私だけでしょうか。


## フロント実装
準備もできたのでSvelteKitでデータ取得してサイトを作りましょう！  

まずはyarnコマンド。

```
$ npm init svelte@next project
```

いくつか質問をされますが、すきなものを選択しましょう。  
以下のように選択しました。

```
√ Which Svelte app template? » Skeleton project
√ Use TypeScript? ... No
√ Add ESLint for code linting? ... Yes
√ Add Prettier for code formatting? ... Yes
```

データの取得にaxios、環境変数用にdotenvを使うので追加します。

```
$ cd project
$ yarn add axios dotenv -D
```

:::note warn
.gitignoreに.envを追記してください！  
:::

.envには以下のように記述しておきます。

```project/.env
VITE_API_KEY=ここにX-API-KEY
VITE_API_ENDPOINT=ここにサービスID
```
:::note info
.envで環境変数をセットしましたが、ViteではキーはVITE_で始める必要があります。  
SvelteKitにはViteが使われているのでそれに従いましょう。
:::

Svelteのコードのハイライトがほしいのでエディタに[Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode)も入れておきましょう。  
準備が整ったので開発用サーバーを立ち上げます。

```
$ yarn dev -o
```
http://localhost:3000/ で立ち上がってますね！

ちなみに-oは起動時ブラウザを開いてくれるオプションです。  
-Hをつけるとhttpsで起動してくれたりします。

### レイアウト作成

* ヘッダー
* フッター
* サイドバー（タグなどを表示）
* メインコンテンツエリア

があればとりあえず充分でしょう。  
project/src/components/layoutsに

* Footer.svelte
* Header.svelte
* Sidebar.svelte

を作成します。  
中身はご自由に。

今回は

* 記事一覧と詳細：サイドバーあり
* それ以外：サイドバーなし

で表示を分けたいので、サイドバーなし用のテンプレートとしてproject/src/routesに__layout.svelteファイルを作成します。

この__layout.svelteファイルはサイドバーなしのページに使うので

```js:project/src/routes/__layout.svelte
<script>
	import Header from '../components/layouts/Header.svelte';
	import Footer from '../components/layouts/Footer.svelte';
</script>

<Header />
<div class="l-content">
	<slot />
</div>
<Footer />

```

で作成します。  
slot部分にはroutesディレクトリに作成した各svelteファイルの中身が表示されます。

http://localhost:3000/  
にアクセスすると、__layout.svelteファイルが読み込まれていることが確認できますね。

さて、次はblog系のページで使用するテンプレートを作成します。

* /blog/　→　記事一覧
* /blog/記事のスラッグ/　→　記事詳細ページ

で作成します。  
/blog以下のページでサイドバーありテンプレートを読み込みます。

project/src/routes/blogに__layout.svelteファイルを作成しましょう。

```js:svelte:project/src/routes/blog/__layout.svelte
<script>
	import Sidebar from '../../components/layouts/Sidebar.svelte'
</script>
<Sidebar />
<main class="l-main">
    <slot></slot>
</main>
```

これでレイアウトを分岐できました。  
blogディレクト以下では今作ったテンプレートが読み込まれます。

ブログ一覧ページを作るために、project/src/routes/blogにindex.svelteファイルと、データ取得用のjsonファイルを作りましょう。

```js:project/src/routes/blog/index.svelte
<script context="module">
	import axios from 'axios';
	export const load = async () => {
		try {
			const res = await axios.get('/blog.json');
			return {
				props: {
					postsData: res.data
				}
			};
		} catch (e) {
			return {
				props: {
					errorMessage: e
				}
			};
		}
	};
</script>

<script>
	export let postsData;
	export let errorMessage;
	$: posts = postsData;
	$: error = errorMessage;
</script>

<svelte:head>
	<title>記事一覧</title>
</svelte:head>
<h1>記事一覧</h1>
{#if posts}
	<ul>
		{#each posts as post (post.id)}
			<li><a href="/blog/{post.id}/">{post.title}</a></li>
		{/each}
	</ul>
{:else if error}
	error:{error}
{/if}

```

記事を取得するjson.jsファイルを作成します。

```js:project/src/routes/blog/index.json.js
import axios from 'axios'
const ENV =
    import.meta.env
const API_KEY = ENV.VITE_API_KEY
const API_ENDPOINT = ENV.VITE_API_ENDPOINT
export const get = async() => {
    const URL = `https://${API_ENDPOINT}.microcms.io/api/v1/blog`
    const res = await axios
        .get(URL, {
            headers: {
                "X-API-KEY": API_KEY
            }
        })
    const posts = await res.data.contents
    if (res.status === 404) {
        return { body: [] }
    }
    const ret = {
        status: 200,
        body: posts,
    }
    return ret
}
```

ここまで以下のURLでブログ一覧ページを作成できました。  
確認してみましょう。
http://localhost:3000/blog/

### ブログ記事詳細
先ほどと同じように作っていきます。

```js:project/src/routes/blog/[slug].svelte
<script context="module">
	import axios from 'axios';
	export const load = async ({ page }) => {
		try {
			const res = await axios.get(`/blog/${page.params.slug}.json`);
			return {
				props: {
					postData: res.data
				}
			};
		} catch (e) {
			return {
				props: {
					errorMessage: e
				}
			};
		}
	};
</script>

<script>
	export let postData;
	export let errorMessage;
	$: post = postData;
	$: error = errorMessage;
</script>

<svelte:head>
	{#await post then data}
		{#if post}
			<title>{data.title}</title>
		{/if}
	{/await}
</svelte:head>
{#if post}
	<article>
		<h1>{post.title}</h1>
		{@html post.content}
	</article>
{:else if error}
	{error}
{/if}

```

```js:project/src/routes/blog/[slug].json.js
import axios from 'axios'
const ENV =
    import.meta.env
const API_KEY = ENV.VITE_API_KEY
const API_ENDPOINT = ENV.VITE_API_ENDPOINT
export const get = async({ params }) => {
    const { slug } = params;
    let URL = `https://${API_ENDPOINT}.microcms.io/api/v1/blog/`
    URL += slug
    const res = await axios
        .get(URL, {
            headers: {
                "X-API-KEY": API_KEY
            }
        })
    const post = await res.data
    if (res.status === 404) {
        return { body: [] }
    }
    const ret = {
        status: 200,
        body: post,
    }
    return ret
}
```

できましたね！

情報取得ができればあとは自分の好みに作っていくだけです。  
CSSを書くのがめんどくさい人はCSSフレームワークを使うなりして楽するといいでしょう。

ビルドとプレビューのコマンドは以下です。

```
$ yarn build
$ yarn preview
```

完成系はこちら
https://github.com/shamokit/test-sveltekit-microcms

SvelteもSvelteKitも情報は少ないですが、公式ドキュメントに必要な情報はほとんど乗っていました。ぜひ読んでみてください。

:::note warn
SvelteKitはまだベータ版です。  
最新の情報を確認ください。
:::

以上、しゃもキットでした。