microCMS + Angular + ionic でJamstackなブログの雛形を作る
こんにちは。とあるフロントエンドエンジニアです。
ヘッドレスCMSを使ったJamstackなアーキテクチャがトレンドになってきているので、今回は純国産ヘッドレスCMSの代表格とも言えるmicroCMSを使って簡単なブログの雛形を作って遊んでみました。
この記事のスコープ
- microCMSを使ってのAPI作成
- AngularでAPIの取得
- 一覧ページと詳細ページの作成
今回はとりあえず動くものを作るという最低限の状態を目指します。
パフォーマンスやらなんやらは一切気にしません。
microCMSでAPIを構築する
アカウントの登録
まずは下記サイトでmicroCMSのアカウント登録をしましょう。
APIの作成
会員登録が終わったらまず下記画面でサービスの名前とサブドメインを決めます。
サブドメインは作成したAPIを後でAngular側で取得する際に使用します。
次にAPIの内容とエンドポイントを入力します。
エンドポイントはわかりやすいものにしましょう。
次はAPIの型を選択します。
今回はブログの記事を作成するので左側のリスト形式を選びます。
さてここからがAPI作成のメインとも言える工程です。
APIのスキーマを決めていきましょう。
まずどんなキーを持たせてどんな値を入れるかを設定します。今回は簡単に記事の「タイトル」「イメージ画像(サムネイル)」「本文」の3つで構成することにします。
作成日や更新日はデフォルトでAPIに入っているのであえて日付欄を設ける必要はありません。
スキーマの設定が終わったらデータを追加していきます。
今回は3つほど記事のデータを用意しました。
これでAPIの作成は終了です。とても簡単ですね〜。
APIやJSONの基礎的な知識があれば開発を主要な業務としていない人でも簡単に作成可能ですね🤔
Angular + ionic
そもそもionicとは
Ionic FrameworkはオープンソースのUIツールキットで、HTML、CSS、JavaScriptなどのウェブ技術を使って、 Angular, React, and Vue といった人気フレームワークと併用することで高性能で高品質なモバイルアプリやデスクトップアプリを作ることができます。
(公式ドキュメントより)
というわけで、Angularと組み合わせるととても簡単にネイティブアプリライクなUIを実装できるフレームワークです。今回はこれを使ってUIを整えます。
開発環境の構築
次にAngular + ionic環境を準備します。
以下コマンドを実行してionicのCLIをインストール
$ npm i ionic -g
ionicのCLIを使ってAngular環境を構築
$ ionic start --type=angular
templateの選択では今回はblankを選択。
? Starter template:
tabs | A starting project with a simple tabbed interface
sidemenu | A starting project with a side menu with navigation in the content area
❯ blank | A blank starter project
my-first-app | An example application that builds a camera with gallery
conference | A kitchen-sink application that shows off all Ionic has to offer
プロジェクトを作成したら次にmicroCMSのJavaScript用のSDKをインストールします。
公式でこういうのが用意されているのはすごく便利ですね〜。KotlinやSwiftなど、その他様々な言語に対応したSDKが用意されているので、開発の用途や使用技術に合わせられるんですね✍🏻$ npm i microcms-js-sdk
続けて詳細ページもこの段階で作っちゃいます。
今回はdetailという名前の詳細ページを作ります。
$ ionic g page detail
ページの作成が終わったら以下コマンドでアプリを起動してみましょう。
$ ionic serve
こんな感じの画面が出てきたら開発環境の構築はおわりです。
コード
環境ファイルの準備
src/environments内にenvironment.api.tsを作成し、以下のように先ほどインストールしたmicroCMSのSDKをインポート、サブドメインとAPIキーを入れます。
import { createClient } from 'microcms-js-sdk';
export const client = createClient({
serviceDomain: '', // XXXX.microcms.ioのXXX部分を入れる
apiKey: '', // 管理画面 > API設定 > APIリファレンス > ヘッダーに記載されているAPIキーを入れる
});
appのルーティングを修正
src/app/app-routing.module.tsにはデフォルトでhomeや先ほど作成したdetailページへのルーティングがされていたりするので、とりあえずいったん全て削除して以下のようにします。
(ただ自分がわかりやすくするため)
const routes: Routes = [
{
path: '',
loadChildren: () => import('./home/home.module').then(m => m.HomePageModule)
},
{
path: '',
redirectTo: '/',
pathMatch: 'full'
}
];
一覧ページの作成
microCMSから記事のデータを取得する
src/app/home/home.page.tsで先ほど作成したAPIを取得していきます。
まずは先ほどenvironment.api.tsに記載したものをインポートします。
import { client } from 'src/environments/environment.api';
次に、HomePageクラス内に必要なプロパティとAPIを取得するメソッドを書いていきます。
endpointの中には先ほど指定したAPIのエンドポイントを書き、postsにデータを格納します。
public posts;
public async getData(): Promise<void> {
const data = await client.get({
endpoint: 'article',
});
this.posts = data;
}
最後にionicのライフサイクルを使って、ビューの表示前にgetData()を呼び出します。
ionViewWillEnter() {
this.getData();
}
全体としてはこんな感じ
import { Component } from '@angular/core';
import { client } from 'src/environments/environments.api';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
public posts;
constructor() { }
ionViewWillEnter() {
this.getData();
}
public async getData(): Promise<void> {
const data = await client.get({
endpoint: 'article',
});
this.posts = data;
}
}
取得したデータを表示する
src/app/home/home.page.htmlを編集して、getData()で取得したデータを表示させるためのコードを書いていきます。
その前に、先ほど作成したAPIの中身を確認してみます。
管理画面 > API設定 > APIリファレンス > エンドポイント > GET /article > 試してみる > 取得 と辿っていくと、作成したAPIの中身を確認することができます。
今回作成したAPIを一部抜粋するとこんな感じです。
{
"contents": [
{
"id": "XXXXXXXX",
"createdAt": "2021-12-23TXX:XX:XX.XXXZ",
"updatedAt": "2021-12-23TXX:XX:XX.XXXZ",
"publishedAt": "2021-12-23TXX:XX:XX.XXXZ",
"revisedAt": "2021-12-23TXX:XX:XX.XXXZ",
"title": "XXXXXXXXXXXXXXXX",
"img": {
"url": "https://images.microcms-assets.io/assets/XXXXX.jpg",
"height": XXX,
"width": XXX
},
"description": "XXXXXXXXXXXXXXX"
}
],
"totalCount": 3,
"offset": 0,
"limit": 10
}
このAPIをベースにプロパティをバインディングしていきます。
今回はionicを使っているので、ionicのコンポーネントのion-cardを使ってサクッと整えます。
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>
Blank
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ng-container *ngIf="posts">
<div class="cards">
<ng-container *ngFor="let data of posts.contents">
<ion-card routerLink="/detail/{{data.id}}/">
<img src="{{data.img.url}}?fit=crop&w=300&h=300" alt="">
<ion-card-header>
<ion-card-title>{{data.title}}</ion-card-title>
</ion-card-header>
</ion-card>
</ng-container>
</div>
</ng-container>
</ion-content>
Angularでは、.card-containerについているrouterLinkを使って詳細ページへのルーティングをします。
そして詳細ページへは各記事に割り当てられているidを使い、「/detail/記事のid」というURLでルーティングします。
また、microCMSから呼び出す画像はクエリをつけてあげると縦横の幅を調整できます。今回はわかりやすく300px × 300pxの正方形で統一します。
ルーティングの調整
先ほどHTML側でルーティングのURLを書きましたが、これをtsで制御しなければなりません。
src/app/home/home-routing.module.tsのroutesの中を以下のように書きます。
const routes: Routes = [
{
path: '',
component: HomePage,
},
{
path: 'detail/:id',
loadChildren: () => import('../detail/detail.module').then(m => m.DetailPageModule)
}
];
スタイルの微調整
見栄えを若干調整して一覧っぽくしましょう。
.cards {
display: flex;
gap: 3%;
}
これでそれっぽい一覧ページが作れましたね。
詳細ページ
詳細データの取得
一覧ページができたので、詳細ページを作っていきます。
データの取得から表示はほとんど同じです。
まずはsrc/app/detail/detail.page.tsを修正して、一覧ページでクリックした記事のデータを取得していきます。
初めに必要なモジュールなどをインポートします。
import { ActivatedRoute } from '@angular/router';
import { client } from 'src/environments/environment.api';
先ほどのclientに加え、「/detail/記事のid」でURLに載せたidを取得するためのモジュールをインポートします。
続いて、先ほどのようにgetData()やionViewWillEnter()を書いていきます。
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { client } from 'src/environments/environments.api';
@Component({
selector: 'app-detail',
templateUrl: './detail.page.html',
styleUrls: ['./detail.page.scss'],
})
export class DetailPage {
public id: string;
public post;
constructor(
private activatedRoute: ActivatedRoute
) { }
ionViewWillEnter() {
this.id = this.activatedRoute.snapshot.paramMap.get('id');
this.getData();
}
public async getData(): Promise<void> {
const data = await client.get({
endpoint: 'article',
contentId: this.id,
});
this.post = await data;
}
}
ionViewWillEnter()内の
this.id = this.activatedRoute.snapshot.paramMap.get('id');
でURLのidを取得してidプロパティに格納します。
client.get()内、contentIdプロパティにコンテンツのidを入れます。これで指定したコンテンツのデータを取ってくることができます。
詳細データを表示する
先ほど同様、ionicのion-cardコンポーネントを使ってサクッとビューを整えつつ、データをバインディングしていきます。
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ng-container *ngIf="post">
<ion-title>{{post.title}}</ion-title>
</ng-container>
</ion-toolbar>
</ion-header>
<ion-content>
<ng-container *ngIf="post">
<ion-card>
<img src="{{post.img.url}}" alt="">
<ion-card-header>
<ion-card-title>{{post.title}}</ion-card-title>
</ion-card-header>
<ion-card-content>
{{post.description}}
</ion-card-content>
</ion-card>
</ng-container>
</ion-content>
ion-back-buttonコンポーネントを使用すると、前のページに戻るためのボタンを設置できます。
いったりきたりできるように設置しておきました。
何にもスタイルを整えていないので見栄えはあれですがこれで詳細ページができました。
こんな感じでmicroCMSを使って比較的簡単にブログのテンプレートを作ることができます。
おわりに
初めてヘッドレスCMSを使ってみましたが、こんな簡単にAPIって作れるんだ〜と思いました。
従来のWordPressとかだとテンプレートを作成するのにPHPを組み込んだりWordPress専用のメソッドを書いたり色々やらないといけないのと比較すると、フロント側ではデータの取得、表示に専念すればいいのでテンプレートの開発もしやすいなぁという肌感です。
microCMSとReact、Vueの記事は割とありますが、microCMS + Angular関連はほとんど無い、というか無いので、この記事で少しでも手助けになれば幸いです。
Discussion