【Astro】相対パスで静的ファイルを参照していたらビルドエラーが起きた
何が起きたか
本ブログでは、Astroコンポーネント.astroでOGP情報の取得やDeepL翻訳を一部で実行しています。ただしビルドの度にそれらを実行するのは時間もかかるしAPI制約の観点から避けたいので、実行結果をキャッシュしていました。
キャッシュは下記記事の方法を参考に、/cache/some_cache.json(/srcの外側)という形で持たせています。
アイテムのIDをキーとして、JSONファイルで保存する方法です。
このJSONファイルへのアクセスは、上記事の方法同様にimport.meta.urlを起点に相対パスを解決する方法を採っていました。
少なくとも私の環境では、この時点で開発・本番ともに問題なく動作していました。
// 呼び出しファイルから相対パスnew URL('../../cache/some_cache.json', import.meta.url);その後ディレクトリ構造を見直し、その分相対パスを変更したところ、開発(astro dev)では動くのに本番(astro build)では動かない(Not Foundになる)問題が生じました。
// 前よりも一段階深くなった相対パスnew URL('../../../cache/some_cache.json', import.meta.url);各種バージョン
原因
ビルドされて/distフォルダにまとめられる過程で実行されるスクリプトの位置は、開発時のパス構造とそっくりそのままとは限らないことに起因します。
'../../cache/some_cache.json'の指定で問題なく動作していたのは、恐らく偶然にも、参照元ファイルとcacheとの階層差が開発と本番環境で一致していたためです。
解決策
プロジェクトのルートディレクトリから絶対パスで指定する方法を取りました。
import path from 'path';// 第二引数は絶対パスで指定path.join(process.cwd(), '/cache/some_cache.json');process.cwd()は、Node.jsプロセスのワーキングディレクトリを返します。
一般的なAstroプロジェクトのようにプロジェクトルートでnpm run dev等のコマンドを実行した場合、
/cache/some_cache.jsonを参照できるという訳です。
ローカルやデプロイ先でのnpm run buildコマンドでも、プロジェクトルートがワーキングディレクトリとなっていれば、上記でパス解決を行えます。
Cloudflare Pagesでビルドしていますが、これで問題なく対応できました🎉
開発とビルド時の階層構造が異なる場合は、Astro云々関係なしにこの問題はありそうですね。
参考
関連記事