如果要在 Vue 中更改頁面的標題或 HTML Meta Tag,你可能使用或聽過 vue-meta,它能幫助你方便的更改 HTML Head、Meta Tag 等,但 vue-meta 已表示不再積極維護,取而代之的是 VueUse 的 @vueuse/head 和 unjs/unhead 這兩個替代品,在 Nuxt 3 中,也很好的整合了 unjs/unhead 提供的函式,讓我們可以直接使用。
使用 Vue 建置出的單頁式應用 (SPA, Single Page Application),在沒有特別設定的情況之下,是共用著 ./public/index.html 作為網頁的呈現進入點,雖然執行與渲染上更加的快速,但是當路由切換時,可能會需要根據頁面內容調整一下網頁的標題、Meta 標籤甚至是載入外部的 CSS 與 JS。
這其中又以 Meta 標籤與網頁的標題能動態調整更為主流需求,因為在 SEO (Search Engine Optimization, 搜尋引擎最佳化) 的考量與配合上,這是不可獲缺的一部分,甚至在分享網頁連結上的縮圖,Facbook、Twitter 都有自己的 Meta 標籤屬性可以做設置,雖然在 SPA 動態的設定這些 SEO 相關標籤可能搜尋引擎爬蟲或連結解析服務不一定可以支援,但部分搜尋引擎爬蟲,已漸漸開始支援動態執行 JavaScript 來解析這些標籤,更重要的是動態調整網頁標題、根據頁面需求載入外部的資源,來增強使用者的體驗也是網頁開發重要的一環。
Nuxt 3 提供了一個組合式函式 useHead
,允許你使用程式或響應式的方式來管理 HTML Head,這個組合式函式背後使用的正是 unjs/unhead。
可以設定的標籤屬性包含了 title、link、meta、style 和 script 等,例如我們變更目前頁面的網頁標題:
<script setup>
useHead({
title: 'Nuxt 3 學習網站',
})
</script>
屬性除了可以直接設定外,也可以透過 ref
、computed
或 reactive
響應式的狀態來綁定動態調整,以下例子使用響應資料動態變更網頁標題。
<script setup>
const count = ref(0)
setInterval(() => count.value += 1, 1000)
useHead({
title: count,
})
</script>
網頁標題更可以透過標題模板來動態的設定,下例子使用 %s
作為 title 參數傳入的位置 。
<script setup>
const count = ref(0)
setInterval(() => count.value += 1, 1000)
useHead({
title: count,
titleTemplate: '%s - Nuxt 3 學習網站',
})
</script>
或者你也可以使用函式來建立標題。
<script setup>
const count = ref(0)
setInterval(() => count.value += 1, 1000)
useHead({
title: count,
titleTemplate: (title) => {
return title ? `${title} - Nuxt 3 學習網站` : 'Nuxt 3 學習網站'
},
})
</script>
<script setup>
useHead({
link: [
{
rel: 'preconnect',
href: 'https://fonts.googleapis.com'
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap',
crossorigin: ''
},
],
})
</script>
HTML 的 Head 還能包含 JS、CSS、Style 等,甚至在 SFC 模板中直接使用相對應的元件,如 <Title>
、<Script>
、<Link>
、<Style>
等來設置屬性及標籤。
<template>
<div>
<Link rel="preconnect" href="https://fonts.googleapis.com" />
<Link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" crossorigin="" />
</div>
</template>
渲染出來的 HTML。
<html>
<head>
...
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" crossorigin="">
...
</head>
...
</html>
你也可以使用 tagPosition
屬性選項來決定標籤附加到 HTML 的位置,舉例來說,想要添加至 <body>
的結尾。
<script setup>
useHead({
script: [
{
src: 'https://third-party-script.com',
tagPosition: 'bodyClose', // 允許的值 head (預設), bodyClose, bodyOpen
},
],
})
</script>
渲染出來的 HTML。
<html>
...
<body>
<div id="__nuxt">...</div>
...
<script src="https://third-party-script.com"></script>
</body>
</html>
更多詳細資料可以參考官網的 useHead。
在網頁中動態的渲染資料其實需要非常的注意,只要是有可能渲染資料的地方,你都要注意是否有將特殊符號進行轉義,永遠不要將不可信任的內容作為模板內容使用,因為跨網站指令碼 (Cross-site scripting, XSS) 攻擊的媒介有很多,useHeadSafe
正是 useHead
組合式函式的包裝,它將我們可能書入的屬性值,僅允許特定白名單內的安全屬性。
這些安全值的白名單如下:
export default {
htmlAttrs: ['id', 'class', 'lang', 'dir'],
bodyAttrs: ['id', 'class'],
meta: ['id', 'name', 'property', 'charset', 'content'],
noscript: ['id', 'textContent'],
script: ['id', 'type', 'textContent'],
link: ['id', 'color', 'crossorigin', 'fetchpriority', 'href', 'hreflang', 'imagesrcset', 'imagesizes', 'integrity', 'media', 'referrerpolicy', 'rel', 'sizes', 'type'],
}
白名單的限制非常嚴格,如果你嘗試使用了不在白名單內的標籤或屬性,它將被忽略不被設定,如果你需要使用不在白名單的標籤或屬性,一定要確保輸入是乾淨且安全的,更多資訊可以參考 Unhead 的 useHeadSafe。
會採用 Nuxt 3 作為專案的框架,多數是為了實現 SSR 來做 SEO,而頁面中的 Meta Tag 也是 SEO 不可或缺的設定步驟,
透過 Nuxt 3 的 useHead
組合式函式,你可以設定頁面的 Meta Tag。
<script setup>
useHead({
meta: [
{ name: 'title', content: 'Nuxt 3 學習網站' },
{ name: 'description', content: '使用 Nuxt 3 來開發一個網站' },
{ name: 'keywords', content: 'Nuxt,Vue' },
{ property: 'og:title', content: 'Nuxt 3 學習網站' },
{ property: 'og:description', content: '使用 Nuxt 3 來開發一個網站' },
{ property: 'og:image', content: '/nuxt.png' }
],
})
</script>
你也可以使用 <Meta>
元件在頁面模板中來設置。
<template>
<div>
<Meta name="title" content="Nuxt 3 學習網站" />
<Meta name="description" content="使用 Nuxt 3 來開發一個網站" />
<Meta name="keywords" content="Nuxt,Vue" />
<Meta property="og:title" content="Nuxt 3 學習網站" />
<Meta property="og:description" content="使用 Nuxt 3 來開發一個網站" />
<Meta property="og:image" content="/nuxt.png" />
</div>
</template>
透過 Nuxt 3 提供的組合式函式,可以很方便的針對頁面中的資訊做一些 Meta 的標記或動態的調整頁面的 Head 資訊,這些設置也將幫助你最佳化網站,實務上,你也可以借助 Nuxt DevTools - Open Graph 來協助你觀察這些 SEO 相關的 Meta Tag 是否有正確設置及呈現的效果。
感謝大家的閱讀,歡迎大家給予建議與討論,也請各位大大鞭小力一些:)
如果對這個 Nuxt 3 系列感興趣,可以訂閱
接收通知,也歡迎分享給喜歡或正在學習 Nuxt 3 的夥伴。
參考資料