この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは、CX事業本部MAD事業部の森茂です。
こちらの記事でRemixとmicroCMSを使った簡単なブログを構築してみました。ただ実際に運用する場合はブログに記事を投稿する際あらかじめプレビュー画面で確認したいことが多いと思います。microCMSには記事を書く際に下書き保存している記事を確認するためのプレビュー機能があるので、今回はその機能をRemixで実装してみました。
microCMSの設定
microCMSでは下書き状態のコンテンツにdraftKey
というユニークなキーが発行されます。コンテンツ取得時にこのdraftKey
を付与することでまだ公開されていない下書き状態のコンテンツを取得できます。microcms-js-sdk
を利用している場合は、queries
にdraftKey
を付与するだけ取得できるようになります。
const content = await client
.get({
endpoint: 'blog',
contentId: params.postId,
queries: { draftKey: '下書き状態の記事のdraftKey' } // draftKeyを渡す
});
まずmicroCMS側の設定を確認していきます。
API設定の画面プレビュー設定画面で遷移先URLを登録します。公開するサイトのURLにあわせて設定を記載します。今回はlocalhost
でのテストを行いたいので下記のように登録をしました。CONTENT_ID
、DRAFT_KEY
にはアクセス時に自動的に付与される値が入ります。
http://localhost:3000/posts/{CONTENT_ID}?draftKey={DRAFT_KEY}
microCMSの記事詳細画面から画面プレビューを押下するとここで登録したURLへ遷移するので、受け取り側では通常通りCONTENT_ID
の記事を取得するロジックを動かし、その際にDRAFT_KEY
を付与してあげることで本来取得できない下書き状態の記事が取得できるという仕組みです。
Remixでの実装
前回作成した記事ページをベースに、記事の詳細画面をプレビュー画面としても利用できるように実装します。クエリーパラメーターに付与されたdraftKey
がある場合はその値を追加してAPIからコンテンツを取得します。
今回の実装では`draftKey`が漏洩した場合誰でも対象の下書き情報が閲覧できる状態となります。機密性の高い情報を扱う場合は、認証が必要な別のページを用意するもしくは別のプレビュー用環境を用意するといった方法が必要です。またCDN下での意図しないキャッシュについても注意する必要があります。
RemixではLoaderFunction
で生成したデータをHeadersFunction
で受け取ることができます。今回はdraftKey
があり、プレビュー画面と判断した場合はヘッダーのCache-Control
の値を変更することでプレビュー画面をキャッシュさせないようにしています。
app/routes/posts/$postId.tsx
// ...
// stale-while-revalidateの設定
export const headers: HeadersFunction = ({ loaderHeaders }) => {
const cacheControl =
loaderHeaders.get('Cache-Control') ??
'max-age=0, s-maxage=60, stale-while-revalidate=60';
return {
'Cache-Control': cacheControl,
};
};
// ...
// microCMS APIから記事詳細を取得する
export const loader: LoaderFunction = async ({ params, request }) => {
// 下書きの場合
const url = new URL(request.url);
const draftKey = url.searchParams.get('draftKey');
const content = await client
.get<Content>({
endpoint: 'blog',
contentId: params.postId,
queries: { draftKey: draftKey ?? '' },
})
// 記事が404の場合は404ページへリダイレクト
.catch(() => {
throw new Response('Content Not Found.', {
status: 404,
});
});
// 下書きの場合キャッシュヘッダを変更
const headers = draftKey ? { 'Cache-Control': 'no-store, max-age=0' } : undefined;
return json(content, { headers });
};
// ...
draftKey
の有無を判断してヘッダー情報を変更するという仕組みを追加するのみで記事ページをプレビュー画面として利用できるようになりました。
一点、現時点でRemix(v1.1.3)のHeadersFunction
部分にはバグが有り上記のみではヘッダーの変更を行うことができません。下記root.tsx
にLoaderFunction
を追記することによって回避できます。(もちろんroot.tsx
のLoaderFunction
を別の用途で利用していれば問題はありません)
app/root.tsx
// ...
export const loader: LoaderFunction = async () => {
return null;
};
// ...
なお、こちらのバグについてはRemix開発チームも認識しており修正中とのことです。
動作の確認
ここで動作を確認していきます。Remixをローカルサーバーで起動しておきます。
$ npm run dev
microCMS上で下書き状態のコンテンツを作成して画面プレビュー
を押下してプレビュー画面へ遷移します。
URLにdraftKey
が付与された状態で下書き状態のコンテンツの確認ができました。ヘッダーのCache-Control
の値もno-store
となっています。
念の為draftKey
がない状態ではNot Found
となることも確認しておきます。
これでプレビュー機能の実装が完了です。
Vercelなど外部でデプロイする場合はmicroCMSの遷移先URL設定を変更しておくことをお忘れなく。
さいごに
RemixでmicroCMSのプレビュー機能を実装してみました。プレビュー機能というと何か複雑なものを想像してしまうところがありますが、実際試してみると比較的簡単に用意することができました。
Remixではヘッダーも動的に変更することができるためヘッダーを利用したキャッシュのコントロールも簡単です。LoaderFunction
やLoaderHeaders
などLoaderと呼ばれる機能が複数あり記載量も多くなりがちですがカスタマイズ性は非常に高いと思います。
次回はOG画像の自動生成を実装していきます:)