AstroでmicroCMSのデータを事前にJSONとして取得しておく
完成品から
import fs from 'fs';
import { createClient } from "microcms-js-sdk";
import dotenv from 'dotenv';
dotenv.config();
const client = createClient({
serviceDomain: process.env.MICROCMS_SERVICE_DOMAIN,
apiKey: process.env.MICROCMS_API_KEY,
});
const getAllContents = async (endpoint, queries = {}) => {
return await client.getAllContents({ endpoint, queries });
};
async function fetchData() {
const data = await getAllContents("projects");
fs.writeFileSync('src/assets/data/projects.json', JSON.stringify(data));
console.log("Created projects.json");
}
fetchData().catch(err => console.error('Data fetch failed:', err));
{
"scripts": {
"dev": "astro dev",
"build": "npm run fetch-data && astro build",
"fetch-data": "node scripts/fetchdata.js",
},
}
ディレクトリ構成
src
├── scripts
│ └── fetchdata.js
├── assets
│ └── data
│ └── projects.json
├── pages
│ └── index.astro
│ └── [id].astro
└── .env
なぜ先にCMSデータを取得しておくのか
開発環境においてAstroはCMSからのデータからページを作る場合、ページ遷移のたびにデータをCMSからFetchして遷移先を生成します。データが複雑になるとfetch()
に時間がかかり、ページ生成速度が遅くなるほか、CMSサービスのデータ転送量やコンテンツ取得回数もそれだけかさんでしまうことになります。
ローカルにCMSデータを事前にJSONとして落としておき、それを参照してページ生成等を行うようにすれば、データの取得は一度で済ませることができます。
結果として開発中のページ生成スピードの大幅な向上と、データ転送量がリミットを超えてしまう、といったハプニングを防ぐことになるのです。
技術仕様
- astro@4.8.2
- dotenv@16.4.5
- microcms-js-sdk@3.1.0
dotenvとmicrocms-js-sdkのインストール
パッケージマネージャーはyarnを使っています(お好みで)
プロジェクトルートでターミナルを開き以下を叩く。
yarn add dotenv microcms-js-sdk
.envのセットアップ
envファイルをプロジェクトルートに生成し、microCMSからデータを取得するための、serviceDomainとapiKeyをに記述しておきます。
microCMSの具体的な使い方は公式を参照してください
.env
MICROCMS_SERVICE_DOMAIN=<YOUR_SERVICE_DOMAIN> # .microcms.io は含まない値
MICROCMS_API_KEY=<YOUR_KEY_VALUE>
fetchdata.jsをつくる
ルートにscriptsフォルダを作成、その中にデータを取得するためのロジックをかいたfetchdata.js
を置きます。
import fs from 'fs';
import { createClient } from "microcms-js-sdk";
import dotenv from 'dotenv';
dotenv.config();
const client = createClient({
serviceDomain: process.env.MICROCMS_SERVICE_DOMAIN,
apiKey: process.env.MICROCMS_API_KEY,
});
const getAllContents = async (endpoint, queries = {}) => {
return await client.getAllContents({ endpoint, queries });
};
async function fetchData() {
const data = await getAllContents("projects"); //"projects"の部分は指定したいエンドポイントに書き換えてください
fs.writeFileSync('src/assets/data/projects.json', JSON.stringify(data));
console.log("Created projects.json");
}
fetchData().catch(err => console.error('Data fetch failed:', err));
dataフォルダを作る
srcにassetsフォルダをなければ作成、その中にdataフォルダを作成します。この中にfetchdata.js
にて取得し生成されたJSONファイルが格納されます。
package.jsonにロジックを追加
fetchdata.js
をパッケージマネージャーから走らせるためのロジックを追加します。これによってJSONデータを新たに生成したり、更新することができます。
{
"scripts": {
"dev": "astro dev",
+ "build": "npm run fetch-data && astro build",
- "build": "astro build",
+ "fetch-data": "node scripts/fetchdata.js",
},
}
これで以下のように叩くとprojects.json
がsrc/assets/data
に生成されているはずです。
yarn fetch-data
使い方
Astroのコードフェンスでimportし、あとは通常通り使うことができます。
---
import projectsData from "../assets/data/projects.json";
---
<ul>
{projectsData.map((project)=>{
<li>
<h1>{project.title}</h1>
<p>{project.info}</p>
</li>
})
}
</ul>
[id].astro
も同様です。
---
import projectsData from "../assets/data/projects.json";
//プロジェクトの個別ページ生成
export async function getStaticPaths() {
return projectsData.map((content, index) => ({
params: {
id: content.id,
},
props: {
project: projectsData.find(({ id }) => id === content.id),
}
}));
};
const { project } = Astro.props;
---
<h1>{project.title}</h1>
<p>{project.info}</p>
おわりに
Astroだけではなく、その他のJSフレームワークでも使用可能かと思います(実際SvelteKitでも同様の形でデータをローカルにキャッシュすることができました)。
Discussion