将标签管理器添加到下一个 js,混淆文档
Adding tag manager to next js, confusing docs
我正在向我的 next.js 网站(下一个版本 12.0.4)添加标签管理器,这里的文档 https://nextjs.org/docs/basic-features/script 说我可以在 _document.js 文件。
当我按照说明操作时,我收到一个错误,将我指向此页面 https://nextjs.org/docs/messages/no-script-in-document-page 说我不能在 _document.js 页面中使用 next/script,此页面指向原始页面。
我很困惑,正确的实现是什么?
在四处挖掘之后,我发现了这个 post:
基本上说脚本不起作用,一旦我忽略了警告并尝试了我的解决方案,我发现也是这种情况。
在我的 _app.js 中使用 next/head 的解决方案似乎工作正常。
阅读@juliomalves 的上述评论,了解为什么要在 _app.js
中完成此操作的解释
import Script from "next/script";
const App = ({ Component, pageProps }) => (
<>
<Script
id="tagmanager-main"
strategy="afterInteractive"
async
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_MEASUREMENT_ID}`}
></Script>
<Script
id="tagmanager-setup"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_MEASUREMENT_ID}');
`,
}}
/>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<Component {...pageProps} />
</>
);
export default App;
这是我的_document.tsx,也许里面有什么东西阻止它工作,但我对上面的工作解决方案很满意。
import * as React from 'react';
// eslint-disable-next-line @next/next/no-document-import-in-page
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
// import theme from '../../styles/theme';
import createEmotionCache from '../lib/createEmotionCache';
// eslint-disable-next-line @next/next/no-script-in-document
import Script from 'next/script';
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
{/* <meta name="theme-color" content={theme.palette.primary.main} /> */}
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
<Script
id="tagman"
strategy="afterInteractive"
async
src="https://www.googletagmanager.com/gtag/js?id=G-xxxxx"
></Script>
<Script
id="tagman-datalayer"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-xxxxx');
`,
}}
/>
<script
src={`https://maps.googleapis.com/maps/api/js?key=${
process.env.NEXT_PUBLIC_MAPS_API_KEY || ''
}&libraries=&v=weekly`}
async
></script>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with static-site generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render
const originalRenderPage = ctx.renderPage;
// You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
// However, be aware that it can have global side effects.
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);
ctx.renderPage = () =>
originalRenderPage({
// eslint-disable-next-line react/display-name, @typescript-eslint/no-explicit-any
enhanceApp: (App: any) => (props) =>
<App emotionCache={cache} {...props} />,
});
const initialProps = await Document.getInitialProps(ctx);
// This is important. It prevents emotion to render invalid HTML.
// See https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153
const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => (
<style
data-emotion={`${style.key} ${style.ids.join(' ')}`}
key={style.key}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: style.css }}
/>
));
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [
...React.Children.toArray(initialProps.styles),
...emotionStyleTags,
],
};
};
我正在向我的 next.js 网站(下一个版本 12.0.4)添加标签管理器,这里的文档 https://nextjs.org/docs/basic-features/script 说我可以在 _document.js 文件。
当我按照说明操作时,我收到一个错误,将我指向此页面 https://nextjs.org/docs/messages/no-script-in-document-page 说我不能在 _document.js 页面中使用 next/script,此页面指向原始页面。
我很困惑,正确的实现是什么?
在四处挖掘之后,我发现了这个 post:
基本上说脚本不起作用,一旦我忽略了警告并尝试了我的解决方案,我发现也是这种情况。
在我的 _app.js 中使用 next/head 的解决方案似乎工作正常。
阅读@juliomalves 的上述评论,了解为什么要在 _app.js
中完成此操作的解释import Script from "next/script";
const App = ({ Component, pageProps }) => (
<>
<Script
id="tagmanager-main"
strategy="afterInteractive"
async
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_MEASUREMENT_ID}`}
></Script>
<Script
id="tagmanager-setup"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_MEASUREMENT_ID}');
`,
}}
/>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<Component {...pageProps} />
</>
);
export default App;
这是我的_document.tsx,也许里面有什么东西阻止它工作,但我对上面的工作解决方案很满意。
import * as React from 'react';
// eslint-disable-next-line @next/next/no-document-import-in-page
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
// import theme from '../../styles/theme';
import createEmotionCache from '../lib/createEmotionCache';
// eslint-disable-next-line @next/next/no-script-in-document
import Script from 'next/script';
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
{/* <meta name="theme-color" content={theme.palette.primary.main} /> */}
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
<Script
id="tagman"
strategy="afterInteractive"
async
src="https://www.googletagmanager.com/gtag/js?id=G-xxxxx"
></Script>
<Script
id="tagman-datalayer"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-xxxxx');
`,
}}
/>
<script
src={`https://maps.googleapis.com/maps/api/js?key=${
process.env.NEXT_PUBLIC_MAPS_API_KEY || ''
}&libraries=&v=weekly`}
async
></script>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with static-site generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render
const originalRenderPage = ctx.renderPage;
// You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
// However, be aware that it can have global side effects.
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);
ctx.renderPage = () =>
originalRenderPage({
// eslint-disable-next-line react/display-name, @typescript-eslint/no-explicit-any
enhanceApp: (App: any) => (props) =>
<App emotionCache={cache} {...props} />,
});
const initialProps = await Document.getInitialProps(ctx);
// This is important. It prevents emotion to render invalid HTML.
// See https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153
const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => (
<style
data-emotion={`${style.key} ${style.ids.join(' ')}`}
key={style.key}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: style.css }}
/>
));
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [
...React.Children.toArray(initialProps.styles),
...emotionStyleTags,
],
};
};