yamaの気ままに
yamaの気ままに

【解決】NotionAPIを利用したブログ構築でアップロード画像が表示されない件

※ 画像・動画等のコンテンツが上手く生成されないことがあります。その際はお手数ですが、ページの更新を複数回お願いします。

目次
  1. 状況
  2. 前提
  3. ブログのコンテンツはSSGで取得している
  4. Vercelにデプロイしている
  5. 問題点
  6. 画像,動画ファイルが本番環境で表示されない。。。
  7. ただ、何回かリロードすれば表示はされる
  8. 対応
  9. 1時間毎にビルド(フェッチ)すれば良いのでは..?
  10. 調べてみるとこんなやり方も
  11. SSGやめてSSRにする
  12. 画像,動画は全て外部にホスティング
  13. Nextのpublicに設置する
  14. まとめ
  15. 参考

状況

前提

当ブログはヘッドレスCMSに、Notionのデータベースを利用している。 このデータベースをNext.jsでフェッチして、ブログのコンテンツ(タイトル,画像,動画,etc…)を表示している。

ブログのコンテンツはSSGで取得している

ビルド時にNotionデータベースをフェッチ

Vercelにデプロイしている

Githubのリポジトリと紐付けていて、masterにpush時に、Vercelに自動デプロイする仕組み。ついでにビルドも行ってくれる。

問題点

画像,動画ファイルが本番環境で表示されない。。。

実はNotionにアップロードした画像,動画ファイルはS3 にアップロードされる仕組みになってるっぽい。 実際、NotionAPIを使ってS3に保存された画像,動画のURL取得してみると、、

Expire Date が付いた状態で返却されてしまう。この画像 URL の有効期限60 分間で、当たり前なのだが、Expire Date を超えた画像に関しては 403 でエラーが返ってきてしまう。 要するに表示されない。

↑リンク切れURLにアクセス

ただ、何回かリロードすれば表示はされる

パワープレーではあるが、このブログの記事詳細はISRで取得していて、revalidate の指定によって、今回だと10s間経ったら次回アクセス時には再度 Notion API から fetch し直すようにし、結果的にExpire Date が更新された状態で再取得できて、表示できる仕組みだった。

ただ、ユーザーの体験は非常に悪い!何回もリロードせな。。。

対応

てことで、、この状況を打破するためにいくつか解決策があげられる。

1時間毎にビルド(フェッチ)すれば良いのでは..?

はい、てことでcronを使ってうまく定期ビルドしたいので、GithubActionsの出番。

とりあえず雑に、、

YAML

name: deploy to vercel hourly cron on: # 1時間ごとに実行 schedule: - cron: '0 * * * *' jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: ref: ${{ github.event.inputs.ref }} # 144 kB未満のデータフェッチであればvercel側でやっているビルドで満足 # - uses: actions/setup-node@v2 # with: # node-version: '18' # - name: Install Dependencies # run: yarn install # - name: Build Project # env: # NOTION_KEY: ${{ secrets.NOTION_KEY }} # NOTION_DATABASE_ID: ${{ secrets.NOTION_DATABASE_ID }} # NEXT_PUBLIC_EMAILJS_PUBLIC_KEY: ${{ secrets.NEXT_PUBLIC_EMAILJS_PUBLIC_KEY }} # NEXT_PUBLIC_EMAILJS_TEMPLATE_ID: ${{ secrets.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID }} # NEXT_PUBLIC_EMAILJS_SERVICE_ID: ${{ secrets.NEXT_PUBLIC_EMAILJS_SERVICE_ID }} # run: yarn build # Vercelにデプロイ - uses: amondnet/vercel-action@v20 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.ORG_ID}} vercel-args: '--prod' # カスタムドメインを設定している場合は、--prodをつける vercel-project-id: ${{ secrets.PROJECT_ID}} working-directory: ./

今回は、ただただシンプルにschedule決めて、Vercelにデプロイするだけです。

肝心なbuildに関しては、Vercelがデプロイ前にbuildしてくれるので、今回は不要。

Vercel側のデプロイログに、144 kBを超えるデータをフェッチする場合 build中でのフェッチがうまく行われない場合がるのでactionsでbuildしよう..

(追記:2023/11/20)

課金周りの話はどうなんだろう。Publicなリポジトリなら制限なかったはず。。確かw

調べてみるとこんなやり方も

Notion API使ってる人結構いると思うけど、画像扱う時皆どうしてんだろう。。

SSGやめてSSRにする

これは、あれか。ブラウザを更新するたびにブログコンテンツ取得してくるパターン。確かに画像のURLが1時間で切れても問題はない。

しかし、、今回のようなブログ記事に関しては別(だと思った)。

動的に扱いたいコンテンツは画像,動画ファイルのみで、その他の情報は全て静的なコンテンツだ。そのために表示速度的なパフォーマンス落とすのもなぁ

画像,動画は全て外部にホスティング

自身のS3とかにアップロードして、URLだけ拾ってくるみたいなパターン。

ただ、NotionをブログのCMSとしてやってる以上、Notion以外にブログ関連の素材を置くのもなんかなぁ。。

Nextのpublicに設置する

Vercel上に画像のバイナリーを直置き。これ意外とアリかもと思った。ただ、動画を管理するのはめんどくさそう。

まとめ

定期的にビルドしてデプロイしてあげるのが何だかんだ解決まで早いのかなと感じた。

懸念点は、ブログ記事が増えてビルドに10分くらいかかる時。

今は2分。長くても3分くらい。

様子見です。

参考