如何在Next.js中等待外部库加载后调用_bsa.init方法?
问题
我有一个基于Next.js和TypeScript的站点,正尝试接入广告。广告提供商给出的接入代码如下:
<script src="//m.servedby-buysellads.com/monetization.js" type="text/javascript"></script> <script> (function(){ if(typeof _bsa !== 'undefined' && _bsa) { _bsa.init('flexbar', 'MYTOKEN', 'placement:wwwmysitecom'); } })(); </script>
该库会加载包含var _bsa={init:function(format...的文件。我在主文件pages/_app.tsx中加入了如下脚本和代码片段:
if(typeof _bsa !== 'undefined' && _bsa) { _bsa.init('flexbar', 'MYTOKEN', 'placement:wwwmysitecom'); } else { console.log("bsa is undefined") } return ( <> <Script src="//m.servedby-buysellads.com/monetization.js" type="text/javascript"></Script>
但首次加载页面时,会打印“bsa is undefined”日志。请问如何在monetization.js库加载完成后再调用_bsa.init函数?
解决方案
问题出在代码执行顺序:调用_bsa.init时,monetization.js还未加载完成。以下是几种针对性的解决方法:
方法一:利用Next.js Script组件的onLoad属性
这是最贴合Next.js最佳实践的方案,通过onLoad指定脚本加载完成后的回调逻辑:
import Script from 'next/script'; export default function MyApp({ Component, pageProps }) { const initBSA = () => { if (typeof _bsa !== 'undefined' && _bsa) { _bsa.init('flexbar', 'MYTOKEN', 'placement:wwwmysitecom'); } }; return ( <> <Script src="//m.servedby-buysellads.com/monetization.js" type="text/javascript" onLoad={initBSA} /> <Component {...pageProps} /> </> ); }
方法二:声明_bsa全局变量类型(解决TypeScript报错)
TypeScript默认不识别全局的_bsa变量,需添加类型声明避免编译报错:
在项目根目录创建types/bsa.d.ts文件,内容如下:
declare global { var _bsa: { init: (format: string, token: string, placement: string) => void; }; } export {};
方法三:手动创建脚本并监听加载事件(传统方式)
若不想依赖Script组件的内置属性,可手动创建脚本元素并监听load事件:
import { useEffect } from 'react'; export default function MyApp({ Component, pageProps }) { useEffect(() => { const script = document.createElement('script'); script.src = '//m.servedby-buysellads.com/monetization.js'; script.type = 'text/javascript'; script.onload = () => { if (typeof _bsa !== 'undefined' && _bsa) { _bsa.init('flexbar', 'MYTOKEN', 'placement:wwwmysitecom'); } }; document.body.appendChild(script); return () => { document.body.removeChild(script); }; }, []); return <Component {...pageProps} />; }
内容的提问来源于stack exchange,提问作者Connor Leech
相关产品推荐
相关产品推荐

