Gatsby中如何在Helmet标签内正确加载脚本文件
在JSX语法中直接将内联JS代码写在<script>标签内部时,React(以及Gatsby依赖的react-helmet/react-helmet-async)不会自动将标签内的文本识别为可执行脚本,只会将其作为普通文本节点渲染,最终浏览器不会解析执行这段代码。
使用React提供的dangerouslySetInnerHTML属性注入内联脚本内容即可解决执行问题,修改后的SEO组件代码如下:
<Helmet> <title>{metaTitle}</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script id="CookieConsent" src="https://policy.app.cookieinformation.com/uc.js" data-culture="EN" type="text/javascript" /> {/* 注意:gtag初始化脚本必须放在外部gtag.js脚本之前,保证consent配置生效 */} <script type="text/javascript" dangerouslySetInnerHTML={{ __html: ` window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('consent', 'default', { ad_storage: 'denied', analytics_storage: 'denied', wait_for_update: 1500, }); gtag('set', 'ads_data_redaction', true); ` }} /> <script async src="https://www.googletagmanager.com/gtag/js?id=321012880" /> </Helmet>
注意:该写法同时兼容Gatsby v3+使用的react-helmet和v4+默认替换的react-helmet-async,无需额外依赖调整。
官方插件方案(推荐用于gtag类统计脚本)
对于Google gtag这类通用统计脚本,优先使用Gatsby官方维护的gatsby-plugin-google-gtag插件,无需手动处理脚本注入、顺序问题,插件会自动完成脚本插入、路由切换时的页面浏览上报,同时支持自定义gtag初始化配置。你只需要在gatsby-config.js中声明插件和跟踪ID即可,默认consent规则可以配合gatsby-browser.js的客户端入口钩子提前配置,稳定性比手动写脚本更高。
基础配置示例:// gatsby-config.js module.exports = { plugins: [ { resolve: `gatsby-plugin-google-gtag`, options: { trackingIds: ["321012880"], pluginConfig: { head: true, // 脚本插入到页面head中 respectDNT: true, // 自动尊重用户的请勿跟踪设置 }, } } ] }SSR/静态构建阶段注入方案
如果需要全局注入脚本、不依赖组件渲染逻辑,可以通过Gatsby的onRenderBody(SSR/构建阶段)钩子直接将脚本插入到静态HTML的指定位置,这种方式在构建时就会把脚本写入最终生成的HTML文件,完全规避客户端渲染导致的脚本不执行问题,适合需要首屏同步执行的核心脚本(比如你当前的cookie consent默认配置脚本)。
示例代码(写入gatsby-ssr.js):exports.onRenderBody = ({ setHeadComponents }) => { // 可通过环境变量判断只在生产环境注入统计类脚本 if (process.env.NODE_ENV !== 'production') return setHeadComponents([ <script key="cookie-consent" id="CookieConsent" src="https://policy.app.cookieinformation.com/uc.js" data-culture="EN" type="text/javascript" />, <script key="gtag-init" type="text/javascript" dangerouslySetInnerHTML={{ __html: ` window.dataLayer = window.dataLayer || []; function gtag() {dataLayer.push(arguments);} gtag('consent', 'default', { ad_storage: 'denied', analytics_storage: 'denied', wait_for_update: 1500, }); gtag('set', 'ads_data_redaction', true); ` }} />, <script key="gtag-src" async src="https://www.googletagmanager.com/gtag/js?id=321012880" /> ]) }客户端动态加载方案
对于不需要首屏立即执行的非核心脚本,可以在gatsby-browser.js的onClientEntry钩子中,等页面完成客户端Hydration之后再动态创建script标签插入DOM,这种方式不会阻塞首屏渲染,适合低优先级的第三方脚本。
示例代码:// gatsby-browser.js exports.onClientEntry = () => { // 初始化gtag window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} window.gtag = gtag; gtag('consent', 'default', { ad_storage: 'denied', analytics_storage: 'denied', wait_for_update: 1500, }); gtag('set', 'ads_data_redaction', true); // 动态加载外部gtag脚本 const gtagScript = document.createElement('script'); gtagScript.async = true; gtagScript.src = 'https://www.googletagmanager.com/gtag/js?id=321012880'; document.head.appendChild(gtagScript); }
通用注意事项:所有涉及gtag consent默认配置的初始化代码,必须保证在外部gtag.js脚本加载之前执行,否则默认拒绝存储的配置不会生效,会违反cookie合规要求。
内容的提问来源于stack exchange,提问作者Jaacoubi

