iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Vue.js

Nuxt 3 實戰筆記系列 第 15

[Day 15] Nuxt 3 使用 useHead 動態設定 HTML Head 與 Meta Tag

  • 分享至 

  • xImage
  •  

前言

如果要在 Vue 中更改頁面的標題或 HTML Meta Tag,你可能使用或聽過 vue-meta,它能幫助你方便的更改 HTML Head、Meta Tag 等,但 vue-meta 已表示不再積極維護,取而代之的是 VueUse 的 @vueuse/headunjs/unhead 這兩個替代品,在 Nuxt 3 中,也很好的整合了 unjs/unhead 提供的函式,讓我們可以直接使用。

為什麼需要動態設定 HTML Head 或 Meta Tag?

使用 Vue 建置出的單頁式應用 (SPA, Single Page Application),在沒有特別設定的情況之下,是共用著 ./public/index.html 作為網頁的呈現進入點,雖然執行與渲染上更加的快速,但是當路由切換時,可能會需要根據頁面內容調整一下網頁的標題、Meta 標籤甚至是載入外部的 CSS 與 JS。

這其中又以 Meta 標籤網頁的標題能動態調整更為主流需求,因為在 SEO (Search Engine Optimization, 搜尋引擎最佳化) 的考量與配合上,這是不可獲缺的一部分,甚至在分享網頁連結上的縮圖,Facbook、Twitter 都有自己的 Meta 標籤屬性可以做設置,雖然在 SPA 動態的設定這些 SEO 相關標籤可能搜尋引擎爬蟲或連結解析服務不一定可以支援,但部分搜尋引擎爬蟲,已漸漸開始支援動態執行 JavaScript 來解析這些標籤,更重要的是動態調整網頁標題、根據頁面需求載入外部的資源,來增強使用者的體驗也是網頁開發重要的一環。

頁面 Head 管理

Nuxt 3 提供了一個組合式函式 useHead ,允許你使用程式或響應式的方式來管理 HTML Head,這個組合式函式背後使用的正是 unjs/unhead

可以設定的標籤屬性包含了 titlelink、meta、stylescript 等,例如我們變更目前頁面的網頁標題:

<script setup>
useHead({
  title: 'Nuxt 3 學習網站',
})
</script>

屬性除了可以直接設定外,也可以透過 refcomputed 或 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>

使用外部 CSS

<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>

Body Tags

你也可以使用 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

使用 useHeadSafe

在網頁中動態的渲染資料其實需要非常的注意,只要是有可能渲染資料的地方,你都要注意是否有將特殊符號進行轉義,永遠不要將不可信任的內容作為模板內容使用,因為跨網站指令碼 (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

頁面 Meta 管理

會採用 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 的夥伴。

參考資料


上一篇
[Day 14] Nuxt 3 最佳化圖片 動態調整請求控制圖片大小 - Nuxt Image
下一篇
[Day 16] Nuxt 3 最佳管理 Meta Tag 的方式 - 使用 useSeoMeta 與 useServerSeoMeta
系列文
Nuxt 3 實戰筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言