ReactJS中使用ethers库获取钱包余额时出现编译错误求助
React项目使用ethers连接Metamask时出现编译错误
问题描述
在ReactJS项目中通过NPM安装ethers库后,尝试获取Metamask钱包余额时触发编译错误,访问本地服务时收到以下错误日志:
Compiled with problems:X ERROR in ./node_modules/node-gyp-build/node-gyp-build.js 1:9-22 Module not found: Error: Can't resolve 'fs' in '/Users/gustavopayano/Desktop/navbar/node_modules/node-gyp-build' ERROR in ./node_modules/node-gyp-build/node-gyp-build.js 2:11-26 Module not found: Error: Can't resolve 'path' in '/Users/gustavopayano/Desktop/navbar/node_modules/node-gyp-build' BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it. If you want to include a polyfill, you need to: - add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }' - install 'path-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "path": false } Module not found: Error: Can't resolve 'os' in '/Users/gustavopayano/Desktop/navbar/node_modules/node-gyp-build' BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it. If you want to include a polyfill, you need to: - add a fallback 'resolve.fallback: { "os": require.resolve("os-browserify/browser") }' - install 'os-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "os": false }
组件代码
import { React, useState } from "react"; import "./App"; import Navbar from "./Navbar"; import "./css/Metamask.css"; function Metamask() { const [errorMessage, setErrorMessage] = useState(null); const [defaultAccount, setDefaultAccount] = useState(null); const [userBalance, setUserBalance] = useState(null); const ethers = require("ethers"); const connectWallet = () => { if (window.ethereum) { window.ethereum .request({ method: "eth_requestAccounts" }) .then((result) => { accountChanged(result[0]); }); } else { setErrorMessage("Install MetaMask Please!"); } }; const accountChanged = (accountName) => { setDefaultAccount(accountName); getUserBalance(accountName); }; const getUserBalance = (accountAddress) => { window.ethereum .request({ method: "eth_getBalance", params: [String(accountAddress), "latest"], }) .then((balance) => { setUserBalance(ethers.utils.formatEther(balance)); }); }; return ( <div className="metamask"> <Navbar /> <h1>Metamask Wallet Connection</h1> <button class="btn btn-secondary btn-md" onClick={connectWallet}> {" "} Connect Metamask </button> <h3>Address: {defaultAccount}</h3> <h3>Balance: {userBalance}</h3> {errorMessage} </div> ); } export default Metamask;
解决方案
方案一:仅引入ethers浏览器兼容的核心工具(推荐)
你的代码只用到了ethers的formatEther工具函数,无需引入完整的ethers包(包含Node.js环境依赖)。修改导入方式即可解决问题:
- 替换原有的
const ethers = require("ethers");为:
import { utils } from "ethers";
- 在
getUserBalance函数中,将ethers.utils.formatEther(balance)改为utils.formatEther(balance)。
方案二:配置Webpack的Node核心模块Polyfill(若需完整ethers功能)
如果需要使用ethers的完整功能(如创建Provider等),需手动配置Webpack的fallback:
- 安装所需的polyfill包:
npm install path-browserify os-browserify --save-dev
针对Create React App项目
CRA默认不允许修改Webpack配置,需借助react-app-rewired:
- 安装react-app-rewired:
npm install react-app-rewired --save-dev
- 在项目根目录创建
config-overrides.js文件,添加以下配置:
module.exports = function override(config, env) { config.resolve.fallback = { ...config.resolve.fallback, "fs": false, // 浏览器环境无需fs模块,直接禁用 "path": require.resolve("path-browserify"), "os": require.resolve("os-browserify/browser") }; return config; };
- 修改
package.json中的scripts命令:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test" }
针对自定义Webpack配置的项目
直接在webpack.config.js中添加resolve.fallback配置:
module.exports = { // ...其他Webpack配置 resolve: { fallback: { "fs": false, "path": require.resolve("path-browserify"), "os": require.resolve("os-browserify/browser") } } };
额外优化点
- React中需使用
className替代class,将按钮的class="btn..."改为className="btn..."; - 错误信息可增加条件渲染和样式,例如:
{errorMessage && <p style={{color: 'red'}}>{errorMessage}</p>}。
内容的提问来源于stack exchange,提问作者Gustavo Payano
相关产品推荐
相关产品推荐

