You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 23:17:22