どういうことかというと、
- 特定の
pages/[slug].astro
の中で getStaticPaths()
から複数のページを返しつつ- とある
slug
の場合のみ、<script>
を使ったコンポーネントを利用してる - はずなのに、すべての
slug
のHTMLで<script>
が出力されてしまう
というケース。
問題のコード
簡略化するとこういう感じ。
---
import V1OnlyScript from "../components/v1-only-script.astro";
export const getStaticPaths = () => ([
{ params: { slug: "v1-1", } }
// ...
{ params: { slug: "v2-1", } }
{ params: { slug: "v2-2", } }
// ...
]);
const { params: { slug } } = Astro;
---
{slug.startsWith("v1") && <V1OnlyScript />}
{slug.startsWith("v2") && <p>0JS</p>}
3つのHTMLが出力されるけど、slug: v1-*
のページでだけ、<script>
が出力されてほしい。
が、実際には、slug: v2-*
のページでも、<script>
が出力されてしまう。
バグではなく仕様
直感的じゃないし、バグでは?って最初は思ったけど、どうやら仕様らしい。
https://docs.astro.build/en/guides/troubleshooting/#an-unexpected-script-or-style-is-included https://docs.astro.build/en/guides/client-side-scripts/#script-bundling
.astro
ファイルにおける<script>
は、処理されるルールが決まってて、そのせいでこうなる。
ワークアラウンド
いくつか考えてみたが、どれもすっきりしない。
is:inline
にする案
その名の通り、インライン化してしまう。
そうすれば、それぞれのページで必要なところだけで出力される。
が、もちろん、そのアセットはサイト単位で見た場合に重複することになる。
public
ディレクトリなんかに逃がしてsrc
で参照するようにすれば、この問題は解決できるけど、コロケーションできない不都合は残る。
異なる.astro
ファイルに分ける案
[slug].astro
を、[slugV1].astro
と[slugV2].astro
に分けるってこと。
---
import V1OnlyScript from "../components/v1-only-script.astro";
export const getStaticPaths = () => ([
{ params: { slugV1: "v1-1", } }
]);
const { params: { slugV1 } } = Astro;
---
<V1OnlyScript />
と
---
export const getStaticPaths = () => ([
{ params: { slugV2: "v2-1", } }
{ params: { slugV2: "v2-2", } }
]);
const { params: { slugV2 } } = Astro;
---
<p>0JS</p>
に分けてしまうと、想定通りの出力にはなる。
が、共通部のコードをコンポーネントに切り出すなどの手間は必要。
今回はこの方法を採用したけど、もっといいやり方はないもんだろうか。