Nuxtで作る — useAsyncData で取得
このガイドでは、Nuxt 3 で「お知らせ一覧」と「お知らせ詳細」の2ページを作ります。SDKは
server/ 側のサーバールートからのみ呼び出し、フロントは
useAsyncData でそのサーバールートを叩く構成です。APIキーはクライアントには一切渡りません。
1. サーバー専用の設定(runtimeConfig)
nuxt.config.ts の runtimeConfig(トップレベル=private)にAPIキーとサイトコードを置きます。public 配下に置くとクライアントバンドルに含まれてしまうため、絶対に置きません。.env では NUXT_CMS_API_KEY / NUXT_CMS_SITE_CODE という命名で自動的に読み込まれます。
export default defineNuxtConfig({
runtimeConfig: {
cmsApiKey: '', // env: NUXT_CMS_API_KEY
cmsSiteCode: '', // env: NUXT_CMS_SITE_CODE
// public には置かない=クライアントに一切出さない
},
}); 2. 一覧(server route + useAsyncData)
server/utils/cms.ts で useRuntimeConfig() からクライアントを組み立てるヘルパーを1つ作ります。
import { ShareDanCmsClient } from '@sharedan/cms-sdk';
export function useCmsClient() {
const config = useRuntimeConfig();
return new ShareDanCmsClient({
baseUrl: 'https://api.cms.sharedan.co.jp',
apiKey: config.cmsApiKey,
siteCode: config.cmsSiteCode,
});
} server/api/news.get.ts がそのヘルパーを使って一覧を返す薄いサーバールートです。
export default defineEventHandler(async () => {
const cms = useCmsClient();
return cms.posts.list('news', { perPage: 20 });
});
ページ側は useAsyncData でこのサーバールートを叩くだけです。
<script setup lang="ts">
const { data } = await useAsyncData('news', () => $fetch('/api/news'));
</script>
<template>
<ul>
<li v-for="p in data?.items" :key="p.slug">
<NuxtLink :to="`/news/${p.slug}`">{{ p.title }}</NuxtLink>
<small>{{ p.category.name }}</small>
</li>
</ul>
</template> cms.posts.list() / cms.posts.get() に localeを渡すと言語別の公開版を取得できます。未翻訳は原文へフォールバックします。詳しくは多言語サイトを作るを参照してください。
3. 詳細ページ([slug].vue)
server/api/news/[slug].get.ts が cms.posts.get() を取得し、本文は renderProseMirror() でHTML化してからレスポンスに含めます。未公開・未存在は
isNotFound を見て createError({ statusCode: 404 }) を投げます。
import { renderProseMirror } from '@sharedan/cms-sdk';
export default defineEventHandler(async (event) => {
const slug = getRouterParam(event, 'slug')!;
const cms = useCmsClient();
try {
const post = await cms.posts.get('news', slug);
return { ...post, html: renderProseMirror(post.body) };
} catch (e: any) {
if (e.isNotFound) {
throw createError({ statusCode: 404, statusMessage: 'Not Found' });
}
throw e;
}
});
ページ側はルートパラメータで useAsyncData し、本文は
v-html で差し込みます。
<script setup lang="ts">
const route = useRoute();
const { data: post } = await useAsyncData(`news-${route.params.slug}`, () =>
$fetch(`/api/news/${route.params.slug}`),
);
</script>
<template>
<article>
<h1>{{ post?.title }}</h1>
<div v-html="post?.html" />
</article>
</template> server/ 側に置き、ページのcomposableからは直接呼ばないでください。
4. routeRules でキャッシュ/プリレンダ
nuxt.config.ts の routeRules で一覧・詳細をプリレンダ(SSG)にするか、ISR相当のキャッシュにするか選べます。
export default defineNuxtConfig({
routeRules: {
'/news/**': { prerender: true }, // SSG:ビルド時に生成
// 更新頻度が高い場合は ISR 相当のSWRキャッシュも選べる:
// '/news/**': { swr: 3600 },
},
}); どちらの場合も、投稿の更新反映には再ビルドまたはキャッシュのパージが必要です。管理画面からのWebhook / GitHub Actions 連携についてはWebhook / GitHub Actions でビルドを起動を参照してください。
このページはお役に立ちましたか?
改善要望・不具合・ドキュメントの分かりにくい点など、お気軽にお寄せください。いただいた内容は今後の改善に役立てます。
お寄せいただきありがとうございます。今後の改善に役立てます。