astro-notion-blog の導入 : Notion 解説 (76)

1. はじめに

ここに書いているように現在、ブログははてなブログを使っています。実は以前、はてなダイアリー難民 → Scrapbox ときて、職場の Web ページでブログを書いていた時期がありました。

この時は、Middleman という静的なサイト生成のシステムを利用していました。HAML で記述したものを HTML にコンバートするとともにタグや最近の更新などを自動作成するものでした。将来的には消してしまうので、リンクではなくスクリーンショットを掲載しておきます。

Middleman によるブログ

今回、同じ静的なサイト生成を行うことができる astro-notion-blog を知りました。Notion から blog を生成できる点はこれまであった easy-notion-blog と同様です。easy-notion-blog は動的な描画が可能なのでメリットは多いのですが、Notion からデータ取得を行うために、描画に少し時間がかかるのが気になっていました。

astro-notion-blog の方は、以前利用していた Middleman と同様に静的なページを事前に構築するものです。構築には少し時間がかかるものの、一度構築してしまえば単なる Web ページになるため描画は爆速になります。

Middleman は記事の執筆が面倒だったため、最終的には今のはてなブログに移行をしてしまいました。記事を Notion で執筆できるようになると、はてなブログよりも圧倒的に快適になるので、これを機に astro-notion-blog に移行することを検討しています。今回、その下準備を始めてみたので、ここで記事として公開することにしました。

2. astro-notion-blog のサブディレクトリ対応

基本的に astro-notion-blog は基本サーバを持たない人でも運用できるように Cloudflare で簡単にデプロイできるようにデフォルト設計されています。しかしながら、私の場合は職場の Web サーバで運用する予定です。ここで問題になるのがサブディレクトリです。現在、私の研究室のサーバの URL は以下のようになっています。

https://www2.metro-cit.ac.jp/~hkob/

astro-notion-blog は Cloudflare での利用を前提としているため、デフォルトで / に展開されるようになっているようでした。調査したところ、astro 自体はサブディレクトリには対応しているようでした。このことを踏まえて astro-notion-blog をサブディレクトリ対応したので、ここに記録しておきます。

2.1 astro.config.mjs の修正

まず、astro 自体のサブディレクトリは defineConfig の部分でできるようでした。astro.config.mjs の最後の部分を以下のように変更しました。この base を設定することで、yarn dev を実行時もサブディレクトリの下に展開される形になるようです。今回は、~hkob/astro/ の下に一時的にテスト展開し、移行が終わったら ~hkob/の下に展開するようにしたいと思います。

// https://astro.build/config
export default defineConfig({
  site: "https://www2.metro-cit.ac.jp/~hkob/astro/",
  base: "~hkob/astro/"
})

2.2 .env の修正

また、.env ファイルには SUB_DIR を追加しました。ここで、先頭に / をつけ忘れると相対アクセスになってしまうので注意が必要です(実はこれでかなり時間を潰しました)。

SUB_DIR=/~hkob/astro

2.3 server-constants.ts の修正

この環境変数は src/server-constants.ts にて取り込みます。

export const SUB_DIR = import.meta.env.SUB_DIR

2.4 Layout.astro の修正

src/layouts/Layout.astro ではいくつか / に決め打ちしている部分があるので、これを上記の環境変数で対応するようにします。まず、先ほど取り込んだ変数値を上部で取り込みます。

import {
  PUBLIC_SITE_TITLE,
  PUBLIC_SITE_DESCRIPTION,
  PUBLIC_GA_TRACKING_ID,
  SUB_DIR
} from '../server-constants.ts'

これで ${SUB_DIR} としてサブディレクトリが利用できます。変更した部分は以下のとおりです。

const { title = '', description = '', path = `${SUB_DIR}/` } = Astro.props

(中略)

const siteOGImage = new URL(`${SUB_DIR}/default-og-image.png`, Astro.site)

const navItems = [
  { label: 'Home', path: `${SUB_DIR}/` },
  { label: 'Blog', path: `${SUB_DIR}/blog` },
]

(中略)

       <a href={SUB_DIR}>{PUBLIC_SITE_TITLE}</a>

2.5 blog-helpers.ts の修正

src/lib/blog-helpers.ts にはページ間のリンクを生成する処理が書かれています。ここも絶対パスになってしまっているので、SUB_DIR を追加します。こちらも変更部分だけ記述します。

import { REQUEST_TIMEOUT_MS, SUB_DIR } from '../server-constants'

(中略)

export const getPostLink = (slug: string) => {
  return `${SUB_DIR}/blog/${slug}`
}

export const getTagLink = (tag: string) => {
  return `${SUB_DIR}/blog/tag/${encodeURIComponent(tag)}`
}

export const getPageLink = (page: number, tag: string) => {
  if (page === 1) {
    return tag ? getTagLink(tag) : `${SUB_DIR}/blog`
  }
  return tag ? `${SUB_DIR}/blog/tag/${encodeURIComponent(tag)}/page/${page.toString()}` : `${SUB_DIR}/blog/page/${page.toString()}`
}

3. Middleman ブログの移行

先ほどの Middleman で作成していたページを 1 ページだけ移行してみます。複製したテンプレートのページに登録してみました。プロパティは以下のようにしました。slug の部分は任意文字列を設定できるのですが、一意に決めるのは面倒なので、日付+通番にしようと思っています。rank については、今後どうやってつけるかを検討します。もしかしたら slug と同じ数字にしてしまうかもしれません。

ページプロパティ

肝心の本文ですが、元の Web page からそのまま Notion に貼り付けました。pre で書いていた部分は自動的に code block として認識されました。ただし、全て Plain Text になってしまっていたので、言語だけ変更しています。また、Middleman 運用時、画像は gyazo への外部リンクだったので、Notion でもそのまま外部リンクのまま画像が貼り付けられていました。

Notion に直接貼り付け

4. yarn dev でのプレビュー

まずはローカルで表示を確認してみます。以下のコマンドでローカルで Astro サーバが起動して描画を確認できます。base が設定されているので、URL がサブディレクトリ対応できていることがわかります。

yarn dev

yarn dev

URL をクリックするとブラウザで動作が確認できます。Blog にカーソルを合わせると ~hkob/astro/blog に正しくリンクが貼られています。

ブラウザでの動作確認

さらに移行したページも確認してみました。その後、数ページ移行してみたのですが、うまく移行できているようです。

astro-notion-blog での描画結果

5. yarn build での静的ページ作成

うまく動いているようなので、本来の目的である静的ページの作成をしてみます。コマンドは以下のようになります。

yarn build

結果は以下のようになりました。dist フォルダの下にそれぞれの html ファイルが生成されていました。blog/[slug].astro の作成結果を見ると、Notion API からのブロック取り出しがかなり時間がかかるようで 10秒から20秒程度の時間がかかるようです。ページが多くなると build に時間がかかってしまうようです。

yarn build

6. yarn build:cache でのキャッシュを使ったページ作成

ここから先は調査不足でまだ正しく動作しているのかが確認できていません。Cloudflare ではビルド時間に 20 分の制約があるそうです。ページ数が増えるとこの制約に引っかかってしまってビルドに失敗してしまう可能性があるとのことです。astro-notion-blog では Nx cloud へのキャッシュをすることで、その制限を回避するようにしているようです。詳しくはこちらの記事で紹介されています。

alpacat.com

Nx の設定をしなければとりあえず、ローカルにキャッシュだけ作ってくれないかなと淡い期待を持って、yarn build:cache を実行してみました。

hkob@hM1Pro ~/D/a/astro-notion-blog (main)> yarn build:cached
yarn run v1.22.19
$ npm run cache:fetch && astro build

> astro-notion-blog@0.2.0 cache:fetch
> node scripts/blog-contents-cache.cjs

@notionhq/client warn: request fail { code: 'unauthorized', message: 'API token is invalid.' }

上記の結果を見て分かるように Notion API の呼び出しで unauthorized になってしまっています。どうやら内部で呼ばれている node scripts/blog-contents-cache.cjs が .env から環境変数を読むように設計されていないようです。そういうことなら、.env の環境変数を事前に設定するようにすればよさそうです。

yarn build:cache

実際にページ作成の時間がかなり削減されています。また、以下のように block.json などの情報が tmp の下にキャッシュもされています。Nx の設定はしていないので、特に外には迷惑をかけていないと思うのですが、後でちゃんと確認しておく必要はあるかと思っています。

tmp の下の json ファイル群

7. Web サーバへのデプロイ

ここまで動いたらあとは Web サーバへの転送まで一気に実施する Makefile を書けばよさそうです。

exec:
    env `cat .env | xargs` yarn build:cached
    rsync -avr --delete dist/* www2.metro-cit.ac.jp:public_html/astro

これで make コマンドで build から転送までが一気に行えます。転送したページはこんな感じになりました。

www2.metro-cit.ac.jp

8. 終わりに

とりあえず astro-notion-blog でページが作成できることは確認できました。cache のところが少し怪しいですが、来週座談会で、おとよさんと話ができるので、この辺りの動作を教えてもらおうと思います。

とりあえずこのままでもいいのですが、slug は日付から Formula で作成したいですね。rank も同じようにそれを Formula で数値にすれば自動的に並びそうです。データベースを修正したときに、astro-notion-blog の方をどう修正するかは Next action にしたいと思います。


hkob.notion.site