skip to content
鰭狀漏斗

使用 Astro 時有元素在 html 標籤外面

/ 閱讀時間 3 分鐘

Astro script 文件的範例中,都把 <script> 放最外層,例如這個:

src/components/Hello.astro
<h1>Welcome, world!</h1>
<script>
console.log("Welcome, browser console!");
</script>

然而如果這個 .astro 檔案包含 <html> 的話,這麼做會讓 <script><html> 外面:

src/pages/WelcomePage.astro
<html>
<head>
<title>An Astro Page</title>
</head>
<body>
<h1>Welcome, world!</h1>
</body>
</html>
<script>
console.log("Welcome, browser console!");
</script>

程式碼通常不會那麼明顯,讓人一眼看出來 <script><html> 外面。<html> 一般會包在 layout 元件中:

src/layouts/Layout.astro
<html>
<head>
<title>An Astro Page</title>
</head>
<body>
<slot />
</body>
</html>

然後在使用這個 layout 元件時發生問題:

src/pages/WelcomePage.astro
---
import Layout from "../layouts/Layout.astro";
---
<Layout>
<h1>Welcome, world!</h1>
</Layout>
<script>
console.log("Welcome, browser console!");
</script>

如果把這樣產生出來的 HTML 丟到 HTML parser 或 validator,會出現這樣的錯誤:

Error: Stray start tag script.

雖然這樣的 HTML 是不正確的,但在 <html> 外面的腳本還是可以正常執行,所以其實就這樣放著不管也沒關係。

如果還是想讓 Astro 產生正確的 HTML 的話,我們就要避免在這種情況下把 <script> 放最上層。

我可以理解這樣寫法是為了讓 <script> 更好讀,如果直接把 <script> 移到 <Layout> 裡面,腳本的程式碼會跟 .astro 檔的其他部分混在一起,一旦程式碼很複雜,會讓 Astro 元件的結構更難看出來。

我覺得最好的解法是盡量把腳本放到更細的元件裡,不要放在 <html> 標籤或 layout 元件外面就可以避免這個問題。

其次比較好的解法是把腳本移到另外的檔案裡,再引入進來 .astro 檔,放到 <Layout> 元件裡面。

不過這麼做的缺點是原本可以放在同一個檔案,現在要分成多個檔案。另外有的腳本放在 Astro 元件裡,有的分開放,也會缺乏一致性。