astro-notion-blogリリース後初のアップデートとなるバージョン0.2ではビルドの高速化とタグの色付け、いくつかの不具合の修正を行いました。
この記事では始めにタグの色付けを紹介した後、astro-notion-blogにビルドの高速化が必要な理由と、どのように高速化を実現したのかについて詳しく説明します。
先日astro-notion-blogのTwitterコミュニティが誕生しました。
ユーザー同士で情報交換したい方、他のユーザーのastro-notion-blogを見てみたい方はぜひ参加してみてください。
記事タイトルの上に表示されているタグに、Notion上で設定した色が反映されるようになりました。
こちらはユーザーの方からいただいたPRで、アイデアもその方によるものです。
とてもNotionらしくて良いのでサイドバーに表示されるタグにも色が反映されるようにしました。
良いと思った方はぜひバージョン0.2にアップデートしてみてください。
アップデート方法はeasy-notion-blogのwikiを参考にしていただければと思います。
astro-notion-blogはその名の通り、Astroフレームワークをベースに作られています。
AstroではWebページを描画する方法としてSSR(Server-Side Rendering)とSSG(Static Site Generation)のどちらかを開発者が選ぶことができます。
SSRとはユーザーがWebページを訪れた際にHTMLを生成(レンダリング)する方式です。ユーザーごとにページの情報をダイナミックに出し分けられることから、動的なページ生成(動的生成)と言います。
一方、SSGはあらかじめHTMLを生成しておき、訪れたユーザーが誰であっても同じWebページを表示します。ユーザーによって表示が変わらないので、動的に対して静的なページ生成(静的生成)と言います。
すでに準備済みのものを渡す静的生成と、注文が来てから準備を始める動的生成ではどちらが速いかは明らかです。
リリース時の紹介記事でも書いた通り、astro-notion-blogではSSGを採用しています。
SSGはユーザー訪問時の速さと引き換えに、あらかじめページを生成しておかなければならないという制約があります。
astro-notion-blogはいつページを生成しているのでしょうか?
それは、みなさんがastro-notion-blogをCloudflare Pagesに初めて連携したとき、またはGitHubにブランチをpushしたときです。
このときCloudflare PagesはGitHubからastro-notion-blogのコードを取得しページ生成とリリースを開始します。
必要なライブラリのインストールやページ生成などアプリケーションが稼働するために必要な処理をビルド、ビルドからリリースまでを合わせた一連の処理をデプロイと言います。
デプロイの履歴はCloudflare Pagesで見ることができます。
ビルドはターミナルで yarn build
と入力するだけでローカルでも行うことができます。
実際に実行してみると、タグ別の一覧ページや記事ごとの個別ページが生成されている様子を見ることができます。
同時に「意外と時間がかかるなぁ」と思うかもしれません。その通りです。
例えば、記事数が約300あるこのアルパカログでビルドを実行すると20分以上かかってしまいます。
そしてこの20分という数字が重要で、なぜならCloudflare Pagesでは1回のデプロイは20分までという制約があるからです(2023年1月31日時点)。
記事数が多いユーザーはastro-notion-blogを使うことができない。
これこそがビルドの高速化を最優先で対応しなければならない理由でした。
時間がかかっているところは目星がついていて、それは下記でした。
- Notion APIとの通信
- ブックマークやEmbedしているサイト情報を取得するための通信
- 画像を取得するための通信
そう、どれも通信です。
ソフトウェアにおいて通信はかなり遅い部類の処理に入ります。
画像や動画といった重いデータや重いサイトの取得には時間がかかります。
また、Notion APIには1秒間に平均3回までという制限があります。
加えてNotionでは段落、見出し、コールアウトなどあらゆるものがブロックで表現され、一度に取得できるブロック数は100までという制限があります。
さらに、テーブル、カラムリスト、同期ブロックなどはブロックの入れ子で表現されます。
例えばテーブルだと、テーブルの中に行があり、行の中にセルがあるといった3段階の親・子・孫という構造になっています。
Notion APIでこうした入れ子構造になったブロックは一度に取得することはできません。
まず親から子を取得し、子から孫を取得するといったステップを踏む必要があります。
たった1ページを表示したいだけなのに1回の通信ではできないのですね。
ではここで少し計算をしてみましょう。
ページ内のすべてのブロックを取得するために必要な通信回数を平均5回とします。
300記事あるとすると全ページのブロックの取得に何秒かかるでしょうか?
答えは…
500秒です。
そのくらいなら余裕じゃないかと思われるかもしれません。
astro-notion-blogでは他に、画像やブックマークされたサイトの情報をビルド時に通信して取得しています。
画像はテキストに比べると非常に重いデータなので、10秒でも足りないケースが往々にしてあります。
また、サイトの方も厄介なことに30秒経っても返事してくれないものが世の中には存在します。
そしてもちろん、通信以外のビルドの処理やデプロイにも時間が必要です。
それら全てをあわせて20分以内にしなければならないのです。
まず、返事が来ないデータに対してはタイムアウトを追加して対応しました。
タイムアウトとは、ある程度待っても返事がなかったら時間切れとみなして次の処理に進む仕組みです。
これで無限に待ち続けてしまうことはなくなりました。
さらにこれらの情報はNotion APIと違って制限がないため、同時に取得することができます。
例えば、画像が3つあって1つの取得に10秒かかるとします。
1つずつ順番に取得すると30秒かかりますが、一斉に取得すると10秒で済みます。
こういった処理のことを並列処理と言います。
JavaScript/TypeScriptは比較的、並列処理が書きやすい言語です(難しいけど)。
今回、ページ内の画像やサイトURLはまとめて並列で取得するように処理を書き換えています。
ここまでで画像やブックマークURLの取得は高速化できました。
残すところはNotion APIです。
しかし、1秒あたりの通信制限があるものをどうやって高速化すれば良いのでしょうか?
制限を迂回することはできませんが、あらかじめ通信してデータを取得しておくことはできます。
すなわち、ビルドよりも前に別の場所で時間をかけてデータを取得し、ビルド時にそのデータを使うようにすれば、Notion APIとの通信ではないので制限を気にしなくて済みます。
そのために今回Nx Cloudというサービスを使うことにしました。
Nxはざっくり言うと、ビルド時に生成される中間生成物をキャッシュとして保存しておき再利用できる仕組みを提供するソフトウェアです。
Nx Cloudはそれらのキャッシュをクラウド上に保存できるサービスで、それによってローカルで生成したキャッシュをCloudflare Pagesなどのリモートでのビルド時に使用できるようになります。
つまり、あらかじめローカルでNotion APIと通信した結果をキャッシュとしてNx Cloudに保存しておき、本番のビルド時にはキャッシュを利用して高速にビルドしようという作戦です。
この作戦により、2秒かかっていた毎ページのブロック取得は100ミリ秒まで短縮することができました。
さらに詳しく知りたい方はコードを読んでみたり、私に直接聞いてみたりしてください。
さて、Notion APIの通信時間がボトルネックになってくるのは記事数の多いユーザーです。
astro-notion-blogでブログを始めたばかりのユーザーは、まだ記事が少ないので問題にはなりません。
加えて、Nx Cloudを使った高速化の設定は少し面倒なので、この機能はオプションで提供することにしました。
始めたばかりのユーザーは最初から難しい設定で頭を悩ませるよりも、記事を執筆したりデザインをカスタマイズしたりして楽しんで欲しいからです。
一方、記事数が多く設定したいけど詰まってしまったという方がいればサポートしますので気軽にお聞きください。
以上です。
この記事では始めにタグの色付けを紹介し、astro-notion-blogにビルドの高速化が必要な理由と、どのように高速化を実現したのかについて詳しく説明しました。
コメントを送る
コメントはブログオーナーのみ閲覧できます