AstroのImageタグでNewtから出力された画像を扱う時の注意点

komosyu
Astro

目次

  1. はじめに
  2. 発生した事象
    1. ビルド時に派生したエラー
    2. 解決方法
  3. 参考
  4. さいごに

はじめに

現在 Web フレームワークのAstroと国産 HeadlessCMS のNewtで Web サイトを実装してみているのですが、Astro の Image タグで Newt から出力されてきた画像の url を src に入れてみてビルドするとエラーが発生して困ってしまったので、解決方法をここで共有していきたいと思います。

発生した事象

発生した事象としては Newt から出力された例えばサムネイルとかの json データは以下のように出力されるのですが、その中にある src をAstro の Image タグに使って、そのままビルドしてしまうとエラーが出力されてしまいます。

コードは以下のような感じです。

---
import { Image } from '@astrojs/image/components'

thumbnail = {
  _id: 'xxxxxxxxx',
  altText: '',
  description: '',
  fileName: 'fileName.jpg',
  fileSize: 123456,
  fileType: 'image/jpeg',
  height: 1000,
  metadata: {},
  src: 'https://storage.googleapis.com/p_63af8f734c2a75ca5c5bbe08/5f6cd768-94b4-4684-b635-5fc859dfca29%2F_MG_1720-2.jpg',
  title: '',
  width: 1000
}
---
<Image
    src={thumbnail.src}
    alt={thumbnail.altText}
    width={thumbnail.width}
    height={thumbnail.height}
/>

ビルド時に派生したエラー

上記のようなコードを実装したままビルドしてみると、このようなエラーが発生しました。

ビルドして発生したエラー

エラーの内容を見てみると/node_modules/@astrojs/image/dist/build/ssg.js:125:22と書いてあったので、Astro の Image タグが原因なのかな?と思って、一度通常の img タグにしてみたところ、エラーが解消されたので間違いなさそうでした。

でも、Newt から出力される以外のところは何も言われていないので、Astro の Image タグだけが原因というわけでもなさそうです。

解決方法

Astro も Newt も比較的新しいものなので、調べてみても今回のエラーを解決できる方法は出てきませんでした。

あわせて、最近よくお世話になっている OpenAI のチャットボットである chatGPT にも聞いてみたのですが、こちらも期待する答えをもらうことはできませんでした。

では、どうやって解決したかというと、Twitter でエラーの内容を投げかけてみたところ@chabatake5さんも同じエラーが出ていたらしく、その時に解決した方法を教えていただきました(感謝)。

内容としては、ここで教えたもらったように「Newtから帰ってくる画像のsrcが一部エンコードされていた」のでデコードする必要があったようです。

たしかに、先ほどのエラーメッセージを見てもFile URL path must not include encoded / characters(ファイルのURLパスには、エンコードされたものを含んではいけません。)と言われており、urlにエンコードされたものを含むな!と怒られているのがわかります。

ふだん、エンコードとかデコードとかいう言葉を見ることも聞いたこともなかったので、謎すぎてすぐエラー事態を調べてしまいましたが、エラーが出た時はきちんとその単語の意味を理解してから動き出さないと、逆に遠回りする羽目になってしまうので良くないですね。

ちなみに、エンコードとデコードとはこういういう意味でした。

  • エンコード: データを他の形式に変換すること
  • デコード: エンコードされたデータを復元すること

ということで、Newt の方でエンコードされてデータの形式が変わってしまったのが原因だったようです。

そして、js ではエンコードとデコードのためのメソッドがそれぞれ用意されています。

エンコードする場合はencodeURIComponent()メソッドを使います。
こうすることで文字列中の記号やスペースを、URL に使用できる形式に変換することができます。

デコードする場合はdecodeURIComponent()メソッドを使います。
こうすることで URL に使用される形式に変換された文字列を元の文字列に戻すことができます。

つまり、Astro の Image タグのファイルの URL パスには、エンコードされたものを含んではいけないとのことだったので、decodeURIComponent()メソッドを用いて url をデコードしてから使うとよさそうです。

なので、解決方法としてはこんな感じになるかと思います。

<Image
  src={decodeURIComponent(thumbnail.src)}
  alt={thumbnail.altText}
  width={thumbnail.width}
  height={thumbnail.height}
/>

ちなみに吐き出された src をデコードしてみるとこんか感じになります。

  • エンコードされていたもの: https://storage.googleapis.com/p_63af8f734c2a75ca5c5bbe08/5f6cd768-94b4-4684-b635-5fc859dfca29%2F_MG_1720-2.jpg
  • デコードした結果: https://storage.googleapis.com/p_63af8f734c2a75ca5c5bbe08/5f6cd768-94b4-4684-b635-5fc859dfca29/_MG_1720-2.jpg

これでビルドしてみたところ、問題なくエラーは解消されました。

参考

さいごに

新しい技術を使っていると、情報が少なくて調べても解決策が出てこないことが多々ありますが、Twitter に投げてみると優しく教えてくれたりする方もいるので、積極的に情報共有してみようと思ったきっかけにもなりました。

また、情報が少ないからもうダメだとあきらめずに、まずはエラーが出た時はまずメッセージをよく読んで理解してから動き出すのが大事だな。と初心に戻って改めて感じることができていい経験になったのでよかったです。

Astro も Newt も触っていてとても楽しいので、今後も引っかかったところやおもしろかったことなど共有していきたいと思いました。