Next.js使用@polkadot/extension-dapp报window未定义编译错误求解
错误根因
报错由Next.js的服务端渲染(SSR)机制导致:@polkadot/extension-dapp是纯浏览器端依赖,内部直接调用浏览器专属的window全局对象;而Next.js构建阶段/服务端预渲染页面时运行在Node.js环境,Node环境不存在window对象,因此直接抛出引用错误。
解决方案
任选一种方案即可解决问题:
方案1:客户端侧动态导入依赖(推荐,侵入性最小)
不要在文件顶部静态导入@polkadot/extension-dapp的相关方法,将导入逻辑移到仅在浏览器端执行的useEffect回调中,修改后的完整代码如下:
import { useEffect, useState } from "react"; import { InjectedAccountWithMeta } from "@polkadot/extension-inject/types"; const Home = () => { // 初始值为空数组,无需额外做非空判断 const [allAccount, setAllAccount] = useState<InjectedAccountWithMeta[]>([]); useEffect(() => { const getAccounts = async () => { // 仅在客户端运行时才加载依赖浏览器API的包 const { web3Enable, web3Accounts } = await import("@polkadot/extension-dapp"); const extensions = await web3Enable("my cool dapp"); if (extensions.length === 0) { return; } const allAccounts = await web3Accounts(); setAllAccount(allAccounts); }; getAccounts(); }, []); return ( <div> {allAccount.map((account) => ( <div key={account.address}> <div className="font-bold mb-2 text-white"> {account.address} </div> </div> ))} </div> ); }; export default Home;
方案2:关闭对应组件的服务端渲染
如果不想调整导入逻辑,可以将涉及Polkadot扩展调用的模块设置为仅客户端渲染,根据你用的Next.js路由模式选择对应配置:
- 若使用Next.js 13+ App Router:在页面文件最顶部加
'use client';指令,同时确保所有调用window/插件API的逻辑都放在useEffect或用户事件回调中执行,不要放在组件顶层作用域。 - 若使用Pages Router:把账号连接相关的逻辑抽成独立组件,再通过Next.js自带的
dynamic方法导入并关闭SSR,示例代码:
// 页面文件中 import dynamic from 'next/dynamic'; // 导入抽离的Polkadot账号组件,关闭服务端渲染 const PolkadotAccountList = dynamic(() => import('../components/PolkadotAccountList'), { ssr: false }); const Home = () => { return ( <div> <PolkadotAccountList /> </div> ); }; export default Home;
修改完成后重新执行构建命令,window is not defined的报错会直接消失,页面在浏览器加载后可正常唤起Polkadot插件读取账号列表。
内容的提问来源于stack exchange,提问作者s.Takahashi
相关产品推荐
相关产品推荐

