Next.js - 如何确保在触发历史更改事件时设置 <title>?

Next.js - How to make sure <title> is set by the time the history change event fires?

在我的 Next.js 应用中,我使用推荐的方法为各个页面设置 <title> 标签:

import Head from 'next/head'

export default () => <>
    <Head><title>My page title</title></Head>
</>

问题是:当触发历史记录更改事件时,document.title 的值并不总是与当前的 URL.

匹配

你可以自己测试一下:

Router.events.on("routeChangeComplete", () => {
    if ('browser' in process) {
        console.log('--------');
        console.log(window.location.href);
        console.log(document.title);
    }
});

在页面之间导航,您应该观察到 URL 和标题经常不匹配。 URL的值总是对的,而title的值却到处都是。它可以有:

这是使用分析时的一个问题,特别是 GTM - Google 标签管理器,它使用当前 URL 和页面标题来唯一标识访问过的页面。

我在使用 Next.js 7 时遇到过这个问题,升级到 8 后仍未解决。

你知道有什么方法可以解决这个问题吗?也许将历史更改事件延迟到 /pages/ 下的组件首次呈现?

谢谢!

这是一个小技巧。 setTimeout(()=>{console.log(document.title)}, 0)

我通过拦截发送到 window.dataLayer.push 的事件并添加一秒延迟以防事件是 gtm.historyChange.

找到了解决方法

这是我要添加到 _document.js 下的 <Head>GtagScript 组件:

export const GtagScript = () => {

    function intercept() {
        const scriptTag = document.querySelector('#gtm-js');
        if (scriptTag !== null)
            scriptTag.addEventListener('load', () => {
                window.dataLayer.pushOrig = window.dataLayer.push;

                window.dataLayer.push = (e) => {
                    if (e.event === 'gtm.historyChange') {
                        setTimeout(function () {
                            window.dataLayer.pushOrig(e);
                            console.log(`URL: ${window.location.href} Title: ${document.title}`);
                        }, 1000);
                    } else {
                        window.dataLayer.pushOrig(e);
                    }
                };
            });
    }


    return <>
        <script
            id="gtm-js"
            async
            src={`https://www.googletagmanager.com/gtm.js?id=${GA_TRACKING_ID}`}
        />
        <script
            dangerouslySetInnerHTML={{
                __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', '${GA_TRACKING_ID}');
            ${intercept.toString()}
            intercept();`
            }}
        />
    </>
};

我会稍等片刻,看看 ZEIT 团队是否会提供官方修复程序。我的解决方案实际上并没有回答这个问题。它不会设置 <title>,它只是推迟事件,这不是最佳选择。

您可以使用 setInterval

const firstPageViewEvent = setInterval(() => {
  if (document.title) {
    // send pageview event
    clearInterval(firstPageViewEvent);
  }
}, 200);