AstroでS3の記事を引っ張ってくる

2025-01-19

はじめに

Obsidianで記事を管理してAstroで出すときに考えたこと の続きです。
今回は下記を行います。

  • R2 から記事を引っ張ってくる
  • Astro でよしなにする

また本記事では Cloudflare R2 を使用するので、AWS S3 を使ってる方は読み替えていただければと思います。

Astro で実装

気をつけること

ここの S3 API で示されてる URL が API のエンドポイントになる…と思ってたのですが、
実は後ろにあるバケット名は不要です。
バケット名を除いた、.r2.cloudflarestorage.com で終わる URL が正解です。
ここで 2 時間つまりました。

実装の理屈を考える

まず理屈を考えます。

  • Astro で何かしらのトリガーを引いてもらう
    • index に配置するとか
    • ビルド時に実行するとか
  • トリガーを引いたら、R2 から記事を引っ張ってくる
    • 画像はすでに R2 のリンクが貼られてるので OK

という流れを考えて、
「Astro で Markdown をよしなにしてくれる標準機能があるじゃん!」と気付き、

  • Astro のコンテンツフォルダに記事を格納する
    • ../src/content/tag/hoge.md みたいな感じが理想
  • 記事はなるべく Astro の Git に保存しないようにする
    • 編集が面倒なので…
  • Astro の標準機能でコレクション化
  • ブログとしての体裁を整える

という理屈をざっくり考えました、では動きます。

記事を取得する

記事を取得するタイミングですが、こんな感じ。

  • 開発中は src/page/index.astro で試験
  • 本番はビルド時にスクリプトを走らせる

必要パッケージ

下記パッケージが必要なのでインストールしてください。

  • @aws-sdk
  • @aws-sdk/s3-request-presigner
  • js-yaml

認証情報をセットする

R2 の認証情報をぶち込みます。

const s3ClientConfig: S3ClientConfig = {
  endpoint: R2_ENDPOINT,
  region: "auto",
  credentials: {
    accessKeyId: R2_ACCESS_KEY,
    secretAccessKey: R2_SECRET,
  },
};

const s3Client = new S3Client(s3ClientConfig);

Markdown の一覧を出力する

コードが長いので順番を踏みます。

export async function downloadMarkdownFiles(mdDirectory: string) {
  const listCommand = new ListObjectsV2Command({
    Bucket: R2_BUCKET,
    Prefix: mdDirectory,
  });
  const files = await s3Client.send(listCommand);
  // ...
  • バケットの中にディレクトリがあり、パスにすると バケット/ディレクトリ みたいな感じ。
  • これを BucketPrefix に分けて new ListObjectsV2Command にわたす。
  • それを send したらファイルの一覧の完成

https://dev.to/nuro/how-to-build-an-astro-collection-loader-3no1

おまけ

これで実装はだいたい大丈夫ですが、デバッグ時に記事を消したい時があるのでそれをバッチにしておきます。

今回、開発環境が WSL の Ubuntu なのでシェルスクリプトで組みます。

rm -rf src/content/*/*.md
touch "public/images/.gitkeep"

おわりに

色々大変だった Astro 実装もこれで一段落したので安心です。
レスポンシブ対応しなきゃなあと思いつつ。