ブログをAstroに移行した

Posts

表題の通り、ブログをAstroに移行した。
Astroはできる限り静的にHTMLを生成してくれるツールで、Astroで作ったWebサイトは非常に高速な表示ができる。
2023年現在、注目されているツールでもある。

私は静的サイトジェネレーターが好きで、気になるフレームワークが出るたびにブログを作り直す悪癖があるので、Astroで書き直すことにした。

このブログの技術スタック

  • Astro
  • Markdoc
  • Tailwind
  • DocSearch

元々このブログはNext.jsとMarkdocで作っていて、使い勝手の良いMarkdocを引き続き使いたいと考えていた。
AstroでMarkdocを使うには、astro-markdoc-rendererを利用することで実現できる。
このライブラリを使ってMarkdocに対応させる方法については、以前記事に書いた。

AstroでMarkdocが使えるようになるastro-markdoc-rendererを試した。
ひよこまめ
Note

現在、astroのインテグレーションとして@astrojs/markdocが実験的に提供されている。
@astrojs/markdoc
使い勝手など、近いうちに試してみたい。

移行してよかったこと

表示が早くなった

そんな気がする。

クライアントサイドでのREST APIの実行が ビルド時のみで良くなった

このブログでは、以下のようなカード型の埋め込みリンクができるタグをMarkdocで実装している。

興味を持ったことを調べて書き散らしているブログです。
ひよこまめ

埋め込みリンクの情報にはリンク先のOGP情報を使っているが、OGP情報の取得は毎回クライアントサイドで行なっていた。
これは当時、サーバーサイド側でREST APIを実行しようとすると、Markdocの独自タグで呼ばれるコールバック関数が、非同期処理の完了を待ってくれないためだった。
Astroにしてからはビルド時にOGP情報を取得できるようになったため、OGP情報を取得するためのAPIの実行回数が抑えられるようになった。

大変だったところ

コンポーネントの書き換え

動的に生成したい箇所はほぼないため、TSX形式で書いていたコンポーネントをすべてAstroに書き直した。
これは単純に数が多かったため大変だった。
カスタマイズは程々にしたい。

@docsearch/reactを使うとビルドエラーが発生する

このブログでは、サイト内検索にAlgoliaを利用している。
これまではNext.jsを使っていたため、@docsearch/reactというライブラリを使って検索機能を実装していた。

React package for DocSearch, the best search experience for docs.. Latest version: 3.6.0, last published: 17 days ago. Start using @docsearch/react in your project by running `npm i @docsearch/react`. There are 55 other projects in the npm registry using @docsearch/react.
npm

検索ボックスや検索機能の実現にはクライアント側でのレンダリングが必要で、コンポーネントにclient:*を指定する必要があった。

<Search client:load />

このとき、astro devでは問題なかったが、astro buildを実行すると以下のエラーが出た。

$ npx astro build

// 省略
import { DocSearch } from "@docsearch/react";
         ^^^^^^^^^
SyntaxError: Named export 'DocSearch' not found. The requested module '@docsearch/react' is a CommonJS module, which may not support all module.exports as named exports.

CommonJSとES Moduleの狭間に落ちてしまったようだ。
調べてみると同様のエラーに悩まされているIssueがあり、解決方法が示されていたため参考にした。
🐛 BUG: Pseudo ES6 third-party module imports fail when building #3174
まさにAstroのドキュメントでも @docsearch/reactを利用したため、同じエラーに遭遇したらしい。

Astroの実装を真似して次のように書くと、astro devでもastro buildでも @docsearch/reactが提供する機能を利用できた。

src/components/Search.tsx
import * as docsearch from "@docsearch/react";
const { DocSearch } =
  (docsearch as unknown as { default: typeof docsearch }).default || docsearch;

import "@docsearch/css";

export function Search() {
  return (
    <DocSearch
      appId={import.meta.env.PUBIC_ALGOLIA_APP_ID}
      indexName={import.meta.env.PUBLIC_ALGOLIA_INDEX_NAME}
      apiKey={import.meta.env.PUBLIC_ALGOLIA_SEARCH_API_KEY}
      placeholder="Search"
      placeholder="Search"
    />
  );
}

まだ対応していないところ

  • 記事タイトルに合わせてOGP画像を自動生成する
    以前はページ生成の高速化のため、事前にコンテンツの情報をファイルに書き出し、その情報を使ってOGP画像を生成していた。
    Astroに移行したとき、ファイルに書き出す処理がなくなったため、それなりの書き直しが必要になっている。
    個別ページのルーティングを行なっているgetStaticPaths()で、画像を生成すれば良さそう。
  • 記事一覧のページネーション