2023年06月30日
[J]avascriptで、[A]PIを使って、[M]arkupなページを作る
みたいな意味です、もともとは。
現在では、JavascriptとAPIは必須ではないみたいで、加えてJAMStackというスペリングからJamstackという綴りに変更されています。
ということで、ゆるっとした、分かるような分からないような、ふわっとした雰囲気の中進んでいきましょう。
最初はMarkdownファイルをサーバに置いて、それを読み込もうと思ったのですが、なんだか思い通りにいかなくって。
なんとか早めにこのサイトを開きたかったので、microCMSを使わせていただくことにしました。
しかも、カスタムではなく、ブログテンプレートを使わせていただいています。
このmicroCMSは、ヘッドレスCMSと呼ばれるCMSです。つまり、フロントエンド部分がないCMSです。
そのため、外部からAPIでデータを取得して取得した先でデータを表示するフロントエンドを実装する必要があります。
手間と思われるかもしれませんが、あらゆるデバイスに対応できる点や、フロントエンドはどんな言語でも実装できるのが特徴でありメリットです。
ということで、microCMSよりもこっちがメインなのですが、今回はフロントエンド部分はReact + Next.jsを使用しています。
というのも、今の時代Reactが普及している点と、尋常じゃない早さで表示ができるNext.js、という組み合わせを、一度体験しておきたかったから、です。
なぜ尋常じゃない早さで表示できるのかと言えば、SSG(またはSG)と言われる技術があるからです。
SSGは[Static Site Generation]、SGは[Static Generation]が正式名称です。元々はSSGだったのですが、なんかSGという言い方がメインになっています。
これは、サイト全体をビルドする際に、サーバ側でHTMLをあらかじめ作成しておき、クライアントかリクエストがあった際には、作成済みのHTMLだけを返すので、めちゃめちゃ表示が速いのです。
ただし、作成済みHTMLが存在する以上、ビルド済みのページの修正にはあまり向きません。その場合は別の方法が必要ですが、今回はブログなので問題ないと判断しています。
もちろん、Next.jsを使用することで、様々な技術を融合したサイト作りが可能です。が、今回はSSGだけを使用していきます・
と、ざっくり説明でした。
さて、いつもの通り、createしていきましょう。今回は公開までなるはやを目指しますのでTailwind CSSも使います。
あと、いろいろ便利なので、TypeScriptも使用していきます。つまり...
npx create-next-app sample-app
とします。最新のこのコマンドは、インタラクティブ(対話式)です。いくつか質問されますので、必要に応じて回答します。今回は...
Would you like to use TypeScript with this project? -> Yes
Would you like to use ESLint with this project? -> Yes
Would you like to use Tailwind CSS with this project? -> Yes
Would you like to use `src/` directory with this project? -> No
Use App Router (recommended)? -> Yes
Would you like to customize the default import alias? -> No
という、いわゆるデフォルト状態ですね。たぶん、これが一番ラクです。作成が終わったら、各種ファイルの中身の掃除と、versel.svgなどの使わないファイルのお掃除をします。
掃除が終わったら、とりあえずgitにpushしちゃいましょう。そうそう、gitも昔はmasterブランチが基本だったと思ったら、mainというブランチが基本になったんですね。
ちょっと離れている間にいろいろと変わりました...(離れたのいつだよ...)。
ということで、この段階でdevブランチを切って、そっちで開発をしていきます。
私の場合、サイト内にポートフォリオを設置する目的もあるため、app直下のディレクトリは以下のような構造になっています。
├── about
├── blog
│ └── [id]
├── components
└── styles
この前提で進めていきます。
こっちは先ほども書きましたが、ブログテンプレートを使っています。そのため、準備らしい準備はありません。
なので、Next.jsからAPIを叩けるように準備するのがメインです。
まずは、APIキーをコピーします。画面右のAPIプレビューから[X-MICROCMS-API-KEY]の項目にAPIキーが書かれています。
あと必要なのがservice domainなのですが、これは同じくAPIプレビューにあるURLの[hogehoge.microcms.io]の[hogehoge]の部分です。
この2つの情報をNext.jsに持たせます。
方法としては、.env.development.localに
API_KEY=xxx...xxx
SERVICE_DOMAIN=hogehoge
と書いておきます。これで、Next.jsからは、[rocess.env.API_KEY]や[rocess.env.SERVICE_DOMAIN]で呼び出せます。
ブログの各Postを取ってくる際に必要な型を定義します。
import type {
MicroCMSImage,
MicroCMSDate,
MicroCMSContentId,
} from "microcms-js-sdk";
export type BlogPostType = {
id: string;
title: string;
content: string;
eyecatch?: MicroCMSImage
} & MicroCMSContentId & MicroCMSDate;
としておくことで、ブログの各記事の型を定義しておきます。これを、app直下に掘ったtypesディレクトリに、[blogPost.ts]として保存します。ファイル名は任意です。
呼び出しは一つのファイルにまとめちゃいましょう。
ということで、app配下にlibsディレクトリを作成します。その中に、今回は[microcms.ts]というファイル名で新規ファイルを作成します。
その中に...
if (!process.env.API_KEY) {
throw new Error("need api key")
} else {
console.log("api key is ok");
}
if (!process.env.SERVICE_DOMAIN) {
throw new Error("need service domain")
} else {
console.log("service domain is ok");
}
export const client = createClient({
serviceDomain: process.env.SERVICE_DOMAIN,
apiKey: process.env.API_KEY,
});
みたいにAPI接続情報を設定して、clientを作成します。
APIキーとservice domainが読めなかった場合は、例外をスローします。読めた場合のconsole.logはデバッグ用です。
さておき、以降は、このclientを使用してAPIを叩きます。
export const getBlogs = async () => {
const blogList = await client.getList<BlogPostType>({
endpoint: "blogs"
})
console.log(blogList);
return {
contents: blogList.contents
};
};
まずは、console.logを仕込んでおいて、取れているかどうか確認します。結果的には取れていたため、returnでblogList.contentsを返しています。
あ、getListはawaitですので、全体をasyncで囲んでいます。何にしても、正常にデータが取れてきていることが確認できました。
ということで、初回はここまでです。