Next.js Pages Router中Commerce.js触发window未定义错误求助
解决Next.js Pages Router中
window is not defined错误 问题原因
@chec/commerce.js初始化时依赖浏览器环境的window对象,但Next.js服务端渲染(SSR)阶段不存在window。你的_app.js会在服务端和客户端同时执行,导致初始化CommerceSDK时触发错误。
解决方案
方案1:条件初始化Commerce客户端
修改lib/commerce.js,仅在客户端环境创建SDK实例:
import CommerceSDK from "@chec/commerce.js"; let client; // 仅在浏览器环境初始化 if (typeof window !== 'undefined') { client = new CommerceSDK(process.env.NEXT_PUBLIC_CHEC_PUBLIC_API_KEY); } export default client;
如果需要确保实例唯一且避免异步问题,可改用函数式获取:
import CommerceSDK from "@chec/commerce.js"; let client; export const getCommerceClient = () => { if (typeof window === 'undefined') { throw new Error("Commerce client can only be used in browser environment"); } if (!client) { client = new CommerceSDK(process.env.NEXT_PUBLIC_CHEC_PUBLIC_API_KEY); } return client; }; export default getCommerceClient;
在组件中使用时,需在客户端生命周期钩子内调用:
import { useEffect, useState } from 'react'; import getCommerceClient from '../lib/commerce'; function MyComponent() { const [commerce, setCommerce] = useState(null); useEffect(() => { setCommerce(getCommerceClient()); }, []); if (!commerce) return null; // 后续业务逻辑 }
方案2:将CartProvider转为客户端组件
如果CartProvider内部直接依赖Commerce客户端,可通过Next.js的dynamic导入禁用SSR,确保它仅在客户端渲染:
// 修改_app.js的CartProvider导入 import dynamic from 'next/dynamic'; import '../globals.css'; const CartProvider = dynamic(() => import('../context/cart'), { ssr: false, }); export default function MyApp({ Component, pageProps }) { return ( <CartProvider> <Component {...pageProps} /> </CartProvider> ); }
同时在context/cart.js中延迟初始化客户端:
import { createContext, useEffect, useState } from 'react'; import CommerceSDK from "@chec/commerce.js"; export const CartContext = createContext(); export function CartProvider({ children }) { const [commerce, setCommerce] = useState(null); useEffect(() => { const client = new CommerceSDK(process.env.NEXT_PUBLIC_CHEC_PUBLIC_API_KEY); setCommerce(client); }, []); if (!commerce) return <div>Loading...</div>; return ( <CartContext.Provider value={/* 你的上下文数据 */}> {children} </CartContext.Provider> ); }
方案3:适配服务端兼容模式
部分版本的@chec/commerce.js支持服务端使用,可传入服务端兼容的fetch实现:
import CommerceSDK from "@chec/commerce.js"; import fetch from 'node-fetch'; const client = new CommerceSDK(process.env.NEXT_PUBLIC_CHEC_PUBLIC_API_KEY, { // 服务端使用node-fetch,客户端用浏览器原生fetch fetch: typeof window === 'undefined' ? fetch : undefined, }); export default client;
需先安装依赖:
npm install node-fetch
额外提示
- 无需手动安装webpack相关依赖,Next.js已内置适配好的webpack配置,手动安装可能引发版本冲突。
- 所有依赖浏览器API的代码,必须确保仅在客户端执行,避免服务端渲染阶段报错。
内容的提问来源于stack exchange,提问作者André Suárez Schou
相关产品推荐
相关产品推荐

