notion-blogの改造メモ (4)

Posted: March 03, 2021

https://manj.io/blog/notion-blog-custom-3 の続き

画像をCDNに載せる

オリジナルのnotion-blogは記事内の画像を表示するときに

  1. blockに含まれる画像URL (s3の北米リージョンにある) を抽出し、imgタグ内にapi/assetへquery paramとしてそのurlとblockidを付与したものを挿入
  2. api/assetの処理として、notion-blog内でその画像URLの閲覧権限を取得しquery paramに付加して307でそのURLに転送させる

というまわりくどい方式を使っている。

こうすると毎回リダイレクトが走る、つまり毎回北米リージョンのs3から画像を取得しなきゃいけない。さらに、Vercelが提供してるCDNにもキャッシュされないので、体験が悪い。

なんでVercelはこんな実装をしたんだろうか。自サービスのCDNになるべく載せたくないみたいなアレか? まあHobbyで無料使用してる上にnotion-blogというおもちゃまで提供してもらってる身なのでノーコメント。Vercelは最高です。


さて、解決策としてasset.ts内の処理を「内部でs3から画像を取得してそのデータを返す」ように変更した。

[slug].tsxでは以下のように変更。api/asset?~からapi/asset/[blockid]に変更しただけ。これはパスが特定されないとCDNに載らないんじゃないかと思ったからだけど、どうやらそうでもないように見えるので無駄かもしれない。<Img>next/imageを使ってる。lazy-loadできるらしい。

...waiting for Gist...

pages/api/asset/[blockid].tsを新しく作った。生成した認証情報つきurlへfetch()して、レスポンスのblobをbufferに変換している。ついでにキャッシュ用のヘッダもつけた。

max-ageが長すぎる説はあるけど、blockidの変更によってURLが変わるので、Notion内で画像を変更することでクライアント側のキャッシュを雑に無効化することができる。ということでとりあえず2時間。別に1年でもいいはずだけど、ブラウザ側にキャッシュを長時間置くことを強いるのもあんまり行儀がよろしくない気がしている。

🗒️
VercelのCDNでのキャッシュ保持期間はmax-ageと無関係に31日らしいので注意。これもblockidが変われば新規にキャッシュされる。

コードは以下。

...waiting for Gist...

こうすることで、画像が無事VercelのCDNに載るようになった。


これからやりたいことリスト: