|
| 1 | +# IgnoreAssetsIntegration |
| 2 | + |
| 3 | +Astroのルート構築処理内で `src/pages/` 以下に配置された各種アセットを無視させ、非対応のファイル形式( `Unsupported file type` )の警告を抑制するインテグレーションです。 |
| 4 | +Astroの内部実装に大きく依存している関係上、利用する **Astroのバージョンを変更する際はパッチバージョンであっても慎重に動作確認** を行ってください。 |
| 5 | + |
| 6 | +## 経緯 |
| 7 | + |
| 8 | +Astroは `src/pages/` ディレクトリをrootとしたパスがWebサイトのパスとなるように[ルーティングを構築](https://docs.astro.build/ja/guides/routing/)しています。 |
| 9 | +ここに置かれるファイルはWebページとして機能するHTMLやMarkdownが想定されており、画像ファイル等は無視されます。 |
| 10 | + |
| 11 | +uteleconでは画像ファイルやリンクするPDFなどのアセットをMarkdown等のドキュメントと同じディレクトリに配置し、相対パスで指定することを基本的な方針としていますが、これはAstroの想定とは異なるため、アセットに対し非対応のファイル形式という警告が大量に表示され、重要な警告を見逃しやすくなっています。 |
| 12 | +このインテグレーションはこうした事態を回避するための策として作成されました。 |
| 13 | + |
| 14 | +## 動作確認方法 |
| 15 | + |
| 16 | +「[実装について](#実装について)」の記述を念頭に、Astro本体の関連ファイルに大きな処理の変更がないか確認してください。 |
| 17 | +以下の点を確認してください。 |
| 18 | +- `dev` および `build` のAstroコマンドが正常に実行・完了できる |
| 19 | +- ビルド成果物( `dist/` ディレクトリ以下)が同じ |
| 20 | + - `diff` コマンドに `--recursive | -r` オプションを渡すことで確認できます。 |
| 21 | +- アセットへの相対リンクが正しく機能する |
| 22 | + - 画像以外のアセットの多いページとしては `/online/shared/` などがあります。 |
| 23 | + - 特に `/articles/` や `/events/` は歴史的事情から複雑なリンク構造をしたページが多いため注意してください。 |
| 24 | + |
| 25 | +また、インテグレーションの呼び出し時にAstroのバージョン確認を行っているので、動作確認のとれたバージョン範囲を示す `TESTED_ASTRO_VERSION_RANGE` を修正してください。 |
| 26 | + |
| 27 | +## 実装について |
| 28 | + |
| 29 | +Astroのルート構築は基本的に [`core/routing/manifest/create.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/routing/manifest/create.ts) の中で行われます。 |
| 30 | +Astroはルート構築を詳細にカスタマイズする方法を提供していないため、このインテグレーションでは内部実装をハックする形で警告を抑制しています。 |
| 31 | + |
| 32 | +`create.ts` のエントリポイントである関数 `createRoutesList()` の中では、まずファイルベースルートが `createFileBasedRoutes()` 関数によって構築されます。 |
| 33 | +このとき `src/pages/` 以下にある非対応の形式のファイルに対し警告が表示されますが、「対応している形式」は [`astro:config:setup` フックに渡される引数の隠しメソッド `addPageExtension()` で追加することができ](https://github.com/withastro/astro/blob/main/packages/astro/src/integrations/hooks.ts)、これによって警告が抑制されます。 |
| 34 | + |
| 35 | +これだけだと「対応している形式」とされたファイルをAstroが処理しようとしてクラッシュするため、ファイルベースルートの構築後にリダイレクトルートが取り除かれることを利用し、アセットから適当なパスへのリダイレクトを `AstroConfig.redirects` に追加することでAstroの処理を回避しています。 |
| 36 | + |
| 37 | +これで目的はほぼ達成されますが、各アセットに対応して実際には参照されないリダイレクトのためのHTMLファイルが大量に生成されてしまいます。 |
| 38 | +そこで `AstroConfig.redirects` のリダイレクト先にはパスだけでなく *300番台の* リダイレクトのためのステータスコードが指定できることを利用し、 `410 Gone` をダブルアサーションで押し込むことで [`core/build/generate.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build/generate.ts) の `generatePath()` 関数によってHTMLファイルが生成されるのを回避します。 |
| 39 | +なお、リダイレクトのためのステータスコードはほぼ検査されることなく [`core/redirects/render.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/redirects/render.ts) にて最終的に `Response` クラスのコンストラクタにそのまま渡されるため、問題は生じていません。 |
| 40 | + |
| 41 | +さらにドキュメントファイルと拡張子のみが異なるファイルが存在する場合(例: `src/pages/google/drive/share.{mdx,png}` )、ルートの衝突が発生し、ドキュメントが参照できなくなることがあります。 |
| 42 | +(これに対してもAstroは警告を表示しますが、これは解消すべき問題です。) |
| 43 | +この場合はリダイレクトルートを挿入せず、 `astro:route:setup` フックでアセットファイルに対応するルートのタイプを `fallback` に書き換えることで `generatePath()` 関数にファイルベースルートを無視させています。 |
| 44 | + |
| 45 | +`astro:route:setup` フックは各ファイルベースルートに対し呼ばれますが、直前にファイル全体を走査する処理があり、大量のバイナリファイルを開くことがないよう最後の手段としています。 |
| 46 | +このルート情報は `RouteOptions` と型定義されているものの、内部データである `RouteData` のオブジェクトがそのまま渡されるため、前述のような上書き処理が可能になっていますが、意図された仕様かどうかは不明です。 |
0 commit comments