Site cover image
🚀astro-notion-blog v0.3アップデート内容の紹介

astro-notion-blogバージョン0.3では記事ごとのOG画像、ファイルブロック、コードブロックのコピーボタン、クリックで画像拡大など、他にもいろいろな機能を追加しました。

この記事ではastro-notion-blogバージョン0.3で追加した機能を紹介した後、技術的にどのようにファイルブロックを実装したのかを詳しく説明します。

ℹ️
バージョン0.3.0のリリース後に不具合を修正した0.3.1をリリースしています。どちらも取り込んでご利用ください。

すでにお気づきの方もいると思いますが、ページに設定したアイコン(絵文字)がタイトル横に表示されるようになりました。

ページにアイコンを設定できるのはNotionらしさの1つだと思います。

他に、カバー画像のデータも Post.Cover に持つようにしたので、カスタマイズしたい人はぜひご利用ください。

ブログでは書いた記事はSNSで頻繁にシェアされます。

その際に表示されるOG画像は、見た人が記事を読みたいと思うかどうかを決める重要な要素です。

astro-notion-blogではこれまで一律のOG画像を設定することしかできませんでしたが、今回のバージョンアップで FeaturedImage に設定した画像がOG画像に設定されるようになりました。

例として、astro-notion-blogのブックマークブロックでは下記のように表示されます。

ぜひ魅力的なOG画像を設定してみてください。

コードブロックの右上にCopyボタンを追加しました。

テックブログをよく書く人にとっては、読者がよりコードを簡単に試せるようになります。

const button = document.querySelector('.copy-button')
コードブロックの右上にCopyボタンが付いた

ブログでは訪れたユーザーに1つでも多くの記事を読んでもらい、ブログに長く滞在してもらうことが重要です。

そのきっかけを増やすために個別記事のフッターに前後記事へのリンクをタグ付きで表示するようにしました。

また、タイトル下にだけ表示していたその記事のタグをフッターにも表示しました。

Image in a image block
個別記事ページのフッターに前後記事へのリンクが追加された

もちろん、見た目はご自身で自由にカスタマイズいただけます。

カスタマイズしたい方は src/components/PostRelativeLink.astro を編集してください。

写真のギャラリーサイトでよくあるように、画像をクリックした際にモーダルで画像を拡大表示できるようにしました。

Image in a image block
画像をモーダルで拡大表示する

実際に試してみたい方は下記サンプルページで画像をクリックしてみてください。

この機能は人によって好みが分かれる部分だと思いますのでデフォルトでは無効にしています。

利用する場合は環境変数 ENABLE_LIGHTBOX=true を設定して有効にする必要があります。

詳細はwikiをご覧ください。

astro-notion-blogを積極的にカスタマイズしている方に朗報です。

コードの書く際のスタイル、例えば if と括弧の間は1つスペースを入れるとか、改行をどこで入れるとか、インデントをどうするとか、そういったことは人間がわざわざ考える必要のないことです。

私たちはそういった些細なことよりも、もっとクリエイティブなことに時間やエネルギーを使うべきです。

そこで今回のアップデートでは、コードを自動整形してくれるツールPrettierを導入し、GitHubにコミットをpushした際に自動でコードを整形する仕組みを導入しました。

クリエイターの皆さんはコードのスタイルを気にすることなく、実現したいことだけに集中してプログラミングやデザインを楽しんでいただければと思います。

ちなみに、ローカルで自動整形を走らせたい場合は yarn format を実行してください。

💁‍♂️
Prettierのようにコードを整形してくれるツールのことをコードフォーマッターと言います。

astro-notion-blogは全て静的ファイルなのでホスト先としてクラウドサービスだけでなく、昔ながらのレンタルサーバーのようにただ公開ディレクトリがあるだけのサービスも選択肢に入れることができます。

しかしレンタルサーバーなどの場合、URLパスが /hoge/ のようにサブパスを含むケースがあるため、各種リンクをサブパスに対応する必要がありました。

サブパス対応のニーズを指摘してくださったNotionアンバサダーの @hkob さんは高専が所有する研究室ごとの公開ディレクトリを使ってブログをホストしているそうで、URLを見てみると確かにサブパスが付いていました。

ホスト先の選択肢が多いというのはastro-notion-blogのメリットなので、今回サブパス付きのURLでもホストできるようにしました。

サブパスを設定するには src/server-constants.ts 内の BASE_PATH を環境変数またはハードコードして指定してください。

おそらく CUSTOM_DOMAIN も合わせて設定するケースが多いでしょう。

export const CUSTOM_DOMAIN = process.env.CUSTOM_DOMAIN || '' // <- Set your costom domain if you have. e.g. alpacat.com
export const BASE_PATH = process.env.BASE_PATH || '' // <- Set sub directory path if you want. e.g. /docs/

astro-notion-blogバージョン0.3を対応している間にAstroのバージョンアップがあり、メジャーバージョン2がリリースされたのでastro-notion-blogでも早速取り込んでいます。

詳しい内容は下記の公式ブログを見ていただくとして、ここでは個人的に気になった2点のみを取り上げます。

まず1番大きい変更は、ページごとにSSRを選択できるようになった点です。

Astro 1系では全体を丸ごとSSRにするかどうかしか選べませんでしたが、2系からはページごとにSSRを選択できるようになりました。

これによってベースはSSGにしつつも、どうしても必要なページのみはSSRにするといった柔軟性が得られ、今後Astroのユーザーがぐんと増えるのではと予想しています。

実はこの機能を見たときにastro-notion-blogではどうすべきか結構悩んだのですが、前述した通り様々なホスト先を選べるのがastro-notion-blogのメリットだということ、SSRを利用する場合Cloudflareなどでは追加の設定が必要になりスタートのハードルが上がることを考慮し、SSRは取り入れない方針で行くことにしました。

もちろん、みなさんがご自身でSSRを導入いただくのは自由です。

導入したらぜひやり方の記事を書いてシェアしてください。

開発時のエラー画面は1系でも別に見にくかったということはないのですが、2系になってよりリッチに見やすくなりました。

私のようなエラーに慣れ親しんだ職業プログラマーはどちらかというとグラフィカルなエラー画面よりもコンソールに出力されるテキストだけのエラーログの方が情報密度が高くて好みだったりするのですが、それはさておき、エラーログがバッと出ることに恐怖を覚える初心者の方にとっては良さそうです。

あとこれは余談ですが、エラーログには問題がある箇所のヒントが書かれているので、怖がらずにじっくり読んでみることをおすすめします。

エラーログを読んで自分で問題解決できるようになればもう初心者は卒業です。

エラーログは友だち。

ここではAstroバージョン2の新機能のうち2つだけを取り上げましたが、もちろんパフォーマンスも向上しています。

その他の詳細はAstro公式を参照してください。

ファイルブロックはastro-notion-blogで対応していない数少ないNotionブロックの1つだったのですが、以前タグの色付け機能をPull RequestしてくださったさとうあまみさんがPull Requestを作ってくれました。

ファイルブロックの経緯だけでなくastro-notion-blogへの愛がこもった記事を書いてくれているので、まだ読んでない方はぜひ読んでみてください。必読です。

ファイルブロックに対応したことで、PDFファイルやTXTファイルなどをastro-notion-blogで配布することができるようになりました。

いろいろ応用できる可能性を秘めているのでぜひご利用ください。

さて、ファイルブロックに対応したといえば一言ですが、実装にあたっては一筋縄ではいきませんでした。

最後に、技術的に何が困難だったのかを書いてみたいと思います。

Notionにアップロードした画像やファイルは、Notion APIでは期限付きURLとして扱われます。

すなわち、画像やファイルのURLをNotion APIで取得しても一定時間が経過するとURLが無効になってしまうというわけです。

一定時間というのは具体的にどれくらいの時間なのでしょうか?

実はNotion APIのドキュメントに1時間と記載されています。

astro-notion-blogではデプロイの際にNotion APIからURLを取得しています。

ということは、デプロイから1時間経過するとファイルも画像もURLが無効になり、リンク切れしてしまうことになります。

この問題を解決するために、次のようなアイデアが思い浮かびました。

  1. 1時間でURLが無効になってしまうのであれば、1時間毎にデプロイする
  2. URLを含むブロックを取得するためのAPIエンドポイントを作り、URLが期限切れしている場合にブロックを取得し直す
  3. 画像でそうしていたようにデータURIスキームを用いてページに埋め込む
  4. ファイルをローカルの public ディレクトリ以下にダウンロードする

どのように検討したのか順を追って説明します。

まず最初に検討したのは、URLが無効になるなら再度URLを取り直すために1時間毎にデプロイすれば良いというシンプルなアイデアです。

デプロイの定期実行を自動化するのは簡単なので実現のためのコストも低いです。

しかし今回問題となったのは1時間という期限でした。

astro-notion-blogで推奨しているCloudflareだけでなく、多くのクラウドサービスではビルド回数や時間に制限があることが多いです。

Cloudflare Pagesでもビルドは月500回までという制限があります。

1時間毎にデプロイするとなると1日24回、30日で720回ビルドすることになり、この制限を超えてしまいます。

このことから他のアイデアを考える必要がありました。

URLが期限切れしている場合に、対象の画像ブロックやファイルブロックのみリフレッシュするというアイデアです。

このアイデアはSWRとして知られており、実際にastro-notion-blogの姉妹ソフトウェアであるeasy-notion-blogはこの方法で画像をリフレッシュしています。

非常にスマートな方法ですが、1つだけ難点がありました。それは専用のAPIエンドポイントを定義しなければならず、そのためにはSSRが必要になるということです。

前述したようにastro-notion-blogはSSRしないからこそ様々なホスティング先の選択肢があります。

SSRを導入してしまうとアプリケーションサーバーを持たないサーバーでホストしているユーザーは途方に暮れてしまうことになります。

また、仮にSSRする方針に踏み切ったとして、SSRを使用する場合はクラウドサービスごとに専用ライブラリのインストールといった追加の設定が必要になってきます。

Cloudflare PagesにはCloudflare Pagesの、NetlifyにはNetlify用のアダプタのインストールが必要になるといった具合にです。

そうなると、例えばVercelでホストしている人にとっては不要なライブラリが追加されることになってしまいます。これはVercelでホストしている人にとっては好ましくないでしょう。

これからastro-notion-blogを始めようとするユーザーにとっても、追加でライブラリのインストールといった作業が増えるのはハードルに感じてしまうでしょう。

これらのことから、良いアイデアですがastro-notion-blogにおいては見送ることにしました。

データURIスキームを用いれば画像だけに限らず、PDFファイルもHTMLに埋め込むことができます。

データURIスキームとはざっくり言うと、データの内容をBase64エンコードしたものにデータの種類を表すMIMEタイプを付加した表現方法です。

データURIスキームについての詳細は過去に説明した下記の記事をご覧ください。

データURIスキームを利用するにあたって重要となるMIMEタイプですが、これはNotion APIが返すS3 URLにリクエストした際のレスポンスの Content-Type ヘッダから得ることができます。

例えばPDFなら application/pdf として、テキストファイルなら text/plain として返ってきます。

Image in a image block
MIMEタイプはS3 URLのレスポンスヘッダのContent-Typeから得られる

ここまでデータURIスキームを使うアイデアは全く問題がないように見えます。

しかし、データURIスキーマにはキャッシュされないという大きな弱点があります。

通常、画像などの静的ファイルはCDNやブラウザにキャッシュされます。

特に、astro-notion-blogがホストされる可能性が高いCloudflareやVercelはCDNに強いベンダーです。CDNでのキャッシュを利用しない手はありません。

データURIスキームでも一度データをダウンロードする必要があるのなら、いっそのことローカルに保存してしまえというのがこのアイデアです。

動的アプリケーション用のアプリケーションサーバーと違い、静的ファイルをホストするだけのサービスではファイル容量に関する制約も緩やかであるケースが多いです。

例えばCloudflare Pagesでは、ファイル数は20,000まで、ファイル容量は1ファイルあたり25MiBまでとなっています(執筆時点)。

また、副次的な効果として、画像が期限なしでいつでもURLでアクセスできるようになったことから、記事ごとにOG画像を設定することができるようになりました。

データURIスキームでの埋め込みではURLが必要なOG画像には対応できません。

以上のことから、記事毎のFeaturedImageと記事内に含まれる画像を public/notion/ 以下にダウンロードするようにしています。

この挙動はローカルで実行した際にも確認することができます。

気になる方はローカルで yarn devyarn build を実行した後 public/notion/ 以下を見てみてください。

この記事ではastro-notion-blogバージョン0.3で追加した機能を紹介した後、技術的にどのようにファイルブロックを実装したのかを詳しく説明しました。

Astro 2系でページ毎のSSRが登場したこと、記事毎のOG画像が設定できるようになったことから、いよいよeasy-notion-blogとの境界がなくなってきました。

どんどんパワフルになっていくastro-notion-blogに対して、easy-notion-blogについてはいずれどのように棲み分けしていくのかを考える必要が出てきそうです。

引き続き今後のastro-notion-blogの進化にご期待ください。最後まで読んでくださりありがとうございました。

Thank you!
Thank you!
URLをコピーしました

コメントを送る

コメントはブログオーナーのみ閲覧できます