构建Next.js应用时出现ReferenceError: self is not defined的解决方法
解决Next.js构建时"ReferenceError: self is not defined"错误(moru-web-sdk相关)
在Next.js应用中使用moru-web-sdk时,开发模式(npm run dev)正常,但执行构建时触发ReferenceError: self is not defined错误。已尝试通过dynamic导入组件并设置ssr: false,但问题依旧。
问题原因
虽然使用dynamic({ ssr: false })可以避免组件在服务端渲染,但组件模块的**顶级代码(包括SDK的import语句)**在构建阶段仍会被Node.js环境执行。而moru-web-sdk内部直接使用了浏览器专属的全局变量self,Node.js环境中不存在该变量,因此抛出错误。
解决方案
将SDK的导入和初始化延迟到客户端环境运行时执行,避免Node.js在构建阶段处理SDK代码。以下是两种可行方案:
方案1:使用useEffect在组件挂载时加载SDK
修改pages/components/moru-sdk.js:
import { useEffect, useState } from 'react'; function MoruService() { const [checkout, setCheckout] = useState(null); useEffect(() => { // 仅在浏览器环境中加载并初始化SDK const initMoruCheckout = async () => { const { MoruCheckout } = await import('moru-web-sdk'); const options = { access_key: "test_9425294388834bdface7d1b58fd538bf67627d9408fe4f2589820cf550a5003d", transaction_id: "1", additional_fields: { name: "Shubham Dhakal", email: "shubham@gmail.com", }, callback_handler: { onSuccess: (response) => { console.log(response); alert("success"); }, onError: (error) => { console.log(error); alert("failure"); }, onClose: (error) => { console.log(error); }, }, }; setCheckout(new MoruCheckout(options)); }; initMoruCheckout(); }, []); const handleMoruPayment = () => { checkout?.open({ amount: 100 }); }; return ( <> {/* 未初始化完成时禁用按钮 */} <button onClick={handleMoruPayment} disabled={!checkout}>Pay with Moru</button> </> ); } export default MoruService;
方案2:点击支付时动态加载SDK
如果不需要提前初始化SDK,也可以在用户点击支付按钮时再加载:
function MoruService() { const handleMoruPayment = async () => { // 点击时才加载SDK const { MoruCheckout } = await import('moru-web-sdk'); const options = { access_key: "test_9425294388834bdface7d1b58fd538bf67627d9408fe4f2589820cf550a5003d", transaction_id: "1", additional_fields: { name: "Shubham Dhakal", email: "shubham@gmail.com", }, callback_handler: { onSuccess: (response) => { console.log(response); alert("success"); }, onError: (error) => { console.log(error); alert("failure"); }, onClose: (error) => { console.log(error); }, }, }; const checkout = new MoruCheckout(options); checkout.open({ amount: 100 }); }; return ( <> <button onClick={handleMoruPayment}>Pay with Moru</button> </> ); } export default MoruService;
说明
两种方案都确保了SDK的代码只在浏览器环境中执行,避免了Node.js构建阶段对self变量的访问。同时保留原有的dynamic({ ssr: false })配置,确保组件本身不会在服务端渲染。
内容的提问来源于stack exchange,提问作者Sudip Bhattarai
相关产品推荐
相关产品推荐

