Nuxt:如何在服务器端动态添加内容/脚本到头部

Phi*_* S. 5 head server-side-rendering nuxt.js

如何在服务器端的 Nuxt 中动态添加内容到头部?

我试图在这里重写这个模块,它只支持静态 ID: https: //github.com/nuxt-community/modules/blob/master/packages/google-tag-manager/index.js

(我的 ID 来自商店(商店正在从休息呼叫中获取 ID))

这是将内容添加到头部的函数:

export default function addheadcode(head, id) {
  const options = {
    id: id,
    layer: 'dataLayer',
    pageTracking: true,
    pageViewEventName: 'nuxtRoute',
    respectDoNotTrack: false,
    query: {},
    scriptURL: '//www.googletagmanager.com/gtm.js',
    noscriptURL: '//www.googletagmanager.com/ns.html',
    env: {} // env is supported for backward compability and is alias of query
  }

  const queryParams = Object.assign({}, options.env, options.query)

  queryParams.id = options.id

  if (options.layer) {
    queryParams.l = options.layer
  }

  const queryString = Object.keys(queryParams)
    .filter(key => queryParams[key] !== null && queryParams[key] !== undefined)
    .map(
      key =>
        `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`
    )
    .join('&')

  head = head || {}
  head.noscript = head.noscript || []
  head.script = head.script || []

  head.script.push({
    hid: 'gtm',
    src:
      (options.scriptURL || '//www.googletagmanager.com/gtm.js') +
      '?' +
      queryString,
    async: true
  })

  head.noscript.push({
    hid: 'gtm-noscript',
    innerHTML: `<iframe src="${options.noscriptURL}?${queryString}" height="0" width="0" style="display:none;visibility:hidden"></iframe>`,
    pbody: true
  })

  head.__dangerouslyDisableSanitizersByTagID =
    head.__dangerouslyDisableSanitizersByTagID || {}
  head.__dangerouslyDisableSanitizersByTagID['gtm-noscript'] = ['innerHTML']
}
Run Code Online (Sandbox Code Playgroud)

这是我的中间件,我仅在服务器端执行 /middleware/gtm.js

import gtmAddheadcode from '~/src/googletagmanager.js'

export default function({ store, app }) {
  if (process.server) {
    const gtmID = store.getters['websiteskeleton/googelTagManagerId']
    gtmAddheadcode(app.head, gtmID)
  }
}
Run Code Online (Sandbox Code Playgroud)

问题: 在第一次通话时,它似乎工作正常。这是我可以在客户端看到的输出:

<script data-n-head="true" src="//www.googletagmanager.com/gtm.js?id=GTM-P4FZ3XX&amp;l=dataLayer" async="true"></script><noscript data-n-head="true" data-hid="gtm-noscript" pbody="true"><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXX&l=dataLayer" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
Run Code Online (Sandbox Code Playgroud)

如果我刷新该页面。我看到相同的内容重复了。如果我再次刷新它,我会看到它的三倍。

1)为什么Nuxt要保存应用程序的这种状态?

2)我可以做什么来解决这个问题?

编辑:我用代码创建了一个 git 存储库。该问题仅在生产模式下出现!运行 dev 时你看不到它。 示例存储库

编辑2:这是一个错误,将被修复:https://github.com/nuxt/nuxt.js/issues/6786#event-2893743506

HMi*_*adt 1

回答您的问题:

1.

这听起来确实像是某个地方的错误。Nuxt 不应该在请求之间保存这样的状态。这对我来说似乎是一个大问题,只要省略hid. 我建议在 Nuxt github 页面上提出一个问题来解决这个问题。

vue-meta我有根据的猜测是,Nuxt 可能会保留用于处理标签的库的状态head,并假设用户将hid在需要时使用其元素来替换它们。

2.

我唯一的建议是添加hid到您的脚本对象中,将其命名为“gtag”等常见名称。

  head.script.push({
    hid: 'gtag',
    src:
      (options.scriptURL || '//www.googletagmanager.com/gtm.js') +
      '?' +
      queryString,
    async: true
  })
Run Code Online (Sandbox Code Playgroud)