LoginSignup
0
0

Nuxt3のuseHeadを試してみた

Posted at

はじめに

Google Tag Managerのように <script> タグを埋め込むタイプの3rd PartyツールをNuxt3に適用するための手法を検討した。

実行環境

  • MacOS 13.4.1 (Apple M1)
  • Node 18.13.0
  • Nuxt 3.6.2

script setupの実行場所

とのこと。実際にやってみる。

pages/index.vue
<script setup>
  console.log(process.server)
  console.log(process.client)
</script>

http://localhost:3000/ 表示

サーバログ
true
false
クライアントログ
false
true

上記記事の通り、サーバとクライアント両方で実行されており、process.server, process.client で判定できることが確認できた。

useHead呼び出し

titleを上書き

pages/index.vue
<script setup>
const env = process.server ? 'Server' : 'Client'
useHead({
  title: `TOP titled | ${env}`
})
</script>
  • リロードすると一瞬は TOP titled | Server と表示される
  • すぐに TOP titled | Client に切り替わる

→サーバとクライアント両方で実行されている。

useServerHeadを使ってみる

useServerHead なる関数を発見したので試してみる。

pages/index.vue
<script setup>
const env = process.server ? 'Server' : 'Client'
useServerHead({
  title: `TOP titled | ${env}`
})
</script>
  • TOP titled | Server と表示されたままである

→サーバのみで実行されるよう関数内で分岐している模様。

<script> を挿入

<script> タグを埋め込む場合は useHead の引数の script が利用できる。

tagPriorityの基準は以下の通り(数字が小さいほど優先度高)

  • -2: <meta charset ...>
  • -1: <base>
  • 0: <meta http-equiv="content-security-policy" ...>
  • 10: 上記以外のタグのデフォルト値

pages/script-insertion.vue
<script setup>
  const config = useRuntimeConfig()
  const env = process.server ? 'Server' : 'Client'
  useHead({
    title: "useHeadデモ",
    script: [
      {
        type: "text/javascript",
        innerHTML: `console.log("${env} script loaded(5)")`,
        tagPriority: 5
      },
      {
        type: "text/javascript",
        innerHTML: `console.log("${env} script loaded(4)")`,
        tagPriority: 4
      }
    ]
  })
</script>

http://localhost:3000/script-insertion 表示

コンソールログ
script-insertion:5 Server script loaded(4)
script-insertion:6 Server script loaded(5)
chunk-VWWL2I6E.js:2710 <Suspense> is an experimental feature and its API will likely change.
VM1678:1 Client script loaded(4)
VM1679:1 Client script loaded(5)
生成されたHTML(DevToolsで確認)
<head>
  <meta charset="utf-8">
  <title>useHeadデモ</title>
  <script type="text/javascript">console.log("Server script loaded(4)")</script>
  <script type="text/javascript">console.log("Server script loaded(5)")</script>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link ...>
  <script>...</script>
  <style>...</style>
  <script type="text/javascript">console.log("Client script loaded(4)")</script>
  <script type="text/javascript">console.log("Client script loaded(5)")</script>
  <!-- 以下略 -->
</head>
  • Serverで追加した <script> は設定した優先度通り <title><meta> の間に挿入
  • Clientで追加した <script> は初期表示時の <style> より後に表示
    • Clientで追加したスクリプト同士の優先度は有効

NuxtConfigで挿入するscriptを定義

全ページ共通で挿入するscriptはNuxtConfigで定義することもできる。

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          type: "text/javascript",
          innerHTML: `console.log("Config script loaded")
window.onload = () => {console.log("page is fully loaded")}
window.addEventListener('DOMContentLoaded', () => {console.log('DOM fully loaded and parsed')})`,
          tagPriority: 9
        }
      ]
    }
  },
  runtimeConfig: {
    public: {
      priorityOfBeforeCommon: PRIORITY_OF_BEFORE_COMMON
    }
  }
})

http://localhost:3000/script-insertion 表示

コンソールログ
script-insertion:5 Server script loaded(4)
script-insertion:6 Server script loaded(5)
script-insertion:7 Config script loaded
script-insertion:9 DOM fully loaded and parsed
script-insertion:8 page is fully loaded
chunk-VWWL2I6E.js:2710 <Suspense> is an experimental feature and its API will likely change.
VM2198:1 Client script loaded(4)
VM2199:1 Client script loaded(5)
生成されたHTML(DevToolsで確認)
<head>
  <meta charset="utf-8">
  <title>useHeadデモ</title>
  <script type="text/javascript">console.log("Server script loaded(4)")</script>
  <script type="text/javascript">console.log("Server script loaded(5)")</script>
  <script type="text/javascript">
    console.log("Config script loaded")
    window.onload = () => {console.log("page is fully loaded")}
    window.addEventListener('DOMContentLoaded', () => {console.log('DOM fully loaded and parsed')})
  </script>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link ...>
  <script>...</script>
  <style>...</style>
  <script type="text/javascript">console.log("Client script loaded(4)")</script>
  <script type="text/javascript">console.log("Client script loaded(5)")</script>
  <!-- 以下略 -->
</head>
  • Configのscriptの優先度はServerのscriptと同じレベルで判断される
  • Config, ServerのscriptはDOM読み込み時にすでに存在する
    • DOMContentLoadedより前に読み込まれることから

まとめ

サーバサイドでuseHeadするのがよさそう

補足

GTMであれば @gtm-support/vue-gtm でもよさそう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0