Hiratake Web ロゴ

Cloudflare Images を Nuxt Content で利用する

投稿した日
更新した日
書いたひと
icon
ひらたけ

Cloudflare ImagesNuxt Content で利用する方法について、備忘録的な感じで書いておこうと思います。

環境

今回確認した環境は、以下のとおりです。

Cloudflare Images についてですが、 Cloudflare には画像のサービスが 3 種類ある ようで、「Cloudflare Images」「Cloudflare Image Resizing」「Cloudflare Polish」のうち、この記事で利用するサービスは「Cloudflare Images」です。

結論

先に、最終的なコードを以下に示します。
以下の Vue コンポーネントを components/content/ProseImg.vue に保存します。

<script lang="ts" setup>
const props = defineProps<{
  src: string // 画像のパス
  alt: string // 画像の代替文字列
}>()
</script>

<template>
  <img
    :src="`/cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1536`"
    :srcset="`
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=320 320w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=640 640w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=768 768w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1024 1024w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1280 1280w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1536 1536w
    `"
    :alt="props.alt"
    sizes="(max-width: 768px) 100vw, 768px"
  />
</template>

Prose Component を上書きする

以下の公式ドキュメントによると、Nuxt Content では デフォルトのコンポーネントを同名のコンポーネントを作成することで上書き することができます。

参考:Prose Components · Nuxt Content

リストや表なども変更できるようですが、今回は画像のコンポーネントを変更したいので components/content/ProseImg.vue ファイルを作成し、画像を表示するときに使用されるデフォルトのコンポーネントを独自のものにします。

Markdown で ![画像の代替文字列](画像のパス) のように記述すると、このコンポーネントの Props に画像のパスや代替文字列がそれぞれ srcalt として入ってきます。

<script lang="ts" setup>
const props = defineProps<{
  src: string // 画像のパス
  alt: string // 画像の代替文字列
}>()
</script>

他の Props を指定する方法ですが、今のところは方法がなさそうです。以下の issue に、指定方法があるみたいなことが書いてあるのですが、動きませんでした。

Nuxt Image が正式リリースされたら的なことが書いてある気がするので(英語なんもわからん)、いずれできるようになるのかもしれません。

フレキシブルバリアントを有効にする

Cloudflare Images のダッシュボードから、「フレキシブルバリアント」の設定を変更します。

Cloudflare のダッシュボードへログインし、左側のメニューで 「イメージ」>「バリアント」 を選択します。その後、開いた画面で「フレキシブルバリアント」を有効にします。
これを有効にすることで、URL の後ろに w=300 など記述を付与して任意の大きさの画像を取得できるようになります。

Cloudflare のドキュメント にも記載がある通り、 誰でも未変換の画像やそのメタデータを取得できるようになります 。注意しましょう。

画像を表示する

ProseImg.vue コンポーネントで画像を表示する部分を作成します。

先ほどの「フレキシブルバリアント」の設定を行ったことで、任意の大きさの画像を表示できるようになりました。これを利用して、<img> タグの srcset 属性にさまざまな大きさの画像を指定します。

この記事では、srcsetsizes 属性の詳しい指定方法などは省略します。以下のページなどをご確認ください。

Cloudflare Images は、標準では以下のような URL で画像が配信されます。

https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/<VARIANT_NAME>

しかし、Cloudflare のアカウントに登録している任意のドメインで配信することも可能 で、その場合は以下の URL となります。

https://example.com/cdn-cgi/imagedelivery/<ACCOUNT_HASH>/<IMAGE_ID>/<VARIANT_NAME>

この URL を利用すると、次のようになります。
画像の幅については、このウェブサイトでは画像が 768px より大きく表示されることはありませんので、それに合わせて設定しています。

<template>
  <img
    :src="`/cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1536`"
    :srcset="`
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=320 320w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=640 640w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=768 768w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1024 1024w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1280 1280w,
      /cdn-cgi/imagedelivery/ACCOUNT_HASH/${props.src}/w=1536 1536w
    `"
    :alt="props.alt"
    sizes="(max-width: 768px) 100vw, 768px"
  />
</template>

Nuxt Image の Providers に Cloudflare があったので、対応しているのかなと思っていたのですが、実際の動作やらドキュメントやらを見ていくとどうも違うようでした。

ここで説明したコンポーネントは、このウェブサイトで使用しています(実際にはスタイルを当てるためにクラスを付与するとかしていますが)。GitHub にリポジトリ を置いていますので、参考にしていただければ。
また、より良い方法などご存知でしたら教えていただけると助かります。