TypeError:path.resolve 不是函数

我在 Udemy 上完成了使用 solc@^0.4.17、React 和 Next.js 的以太坊智能合约课程。我认为尝试将所有内容升级到最新版本并尝试重构将是一个有趣的练习。我在一个名为 factory.js 的文件中有以下代码被导入到我的主索引文件中:

import web3 from './web3';
const path = require('path');
const fs = require('fs');

const abiPath = path.resolve('ethereum/build', 'CampaignFactory.abi');
console.log(abiPath);

const abi = fs.readFileSync(abiPath, 'utf8');
console.log(abi);

const factory = new web3.eth.Contract(
    JSON.parse(abi),
    '0x2d54559dCe0DA6C92378A916e9eE0422CEFFCD80'
);

export default factory;

在我的主索引文件中,我这样称呼它:

import factory from '../ethereum/factory';
...
class CampaignIndex extends Component {
    static async getInitialProps() {
        const campaigns = await factory.methods.getDeployedCampaigns().call();

        return { campaigns };
    }
...

这是console.log:

    wait  - compiling /...
    event - compiled successfully in 637 ms (1422 modules)
    /Users/sonnyparlin/Github/kickstart/ethereum/build/CampaignFactory.abi
    [
      {
        "inputs": [
          {
            "internalType": "uint256",
            "name": "minimum",
            "type": "uint256"
          }
        ],
        "name": "createCampaign",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
      },
      {
        "inputs": [
          {
            "internalType": "uint256",
            "name": "",
            "type": "uint256"
          }
        ],
        "name": "deployedCampaigns",
        "outputs": [
          {
            "internalType": "address",
            "name": "",
            "type": "address"
          }
        ],
        "stateMutability": "view",
        "type": "function"
      },
      {
        "inputs": [],
        "name": "getDeployedCampaigns",
        "outputs": [
          {
            "internalType": "address[]",
            "name": "",
            "type": "address[]"
          }
        ],
        "stateMutability": "view",
        "type": "function"
      }
    ]

控制台日志确认 path.resolve() 确实在工作,但是当我通过 Web 浏览器访问该页面时,我看到以下错误:

enter image description here

Call Stack
Module../ethereum/factory.js
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/pages/index.js (1148:1)
Module.options.factory
/_next/static/chunks/webpack.js (638:31)
__webpack_require__
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/webpack.js (37:33)
fn
/_next/static/chunks/webpack.js (307:21)
eval
webpack-internal:///./pages/index.js (9:75)
Module../pages/index.js
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/pages/index.js (1192:1)
Module.options.factory
/_next/static/chunks/webpack.js (638:31)
__webpack_require__
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/webpack.js (37:33)
fn
/_next/static/chunks/webpack.js (307:21)
eval
node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?page=%2F&absolutePagePath=%2FUsers%2Fsonnyparlin%2FGithub%2Fkickstart%2Fpages%2Findex.js! (5:15)
eval
node_modules/next/dist/client/route-loader.js (236:50)

我的猜测是,这确实是某种版本控制或依赖问题,所以我还包括我的 package.json 文件:

{
  "name": "kickstart",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha",
    "dev": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@truffle/hdwallet-provider": "^1.0.37",
    "fs-extra": "^10.0.0",
    "ganache-cli": "^6.1.8",
    "mocha": "^9.1.3",
    "next": "^12.0.3",
    "next-routes": "^1.4.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "semantic-ui-css": "^2.4.1",
    "semantic-ui-react": "^2.0.4",
    "solc": "^0.8.9",
    "web3": "^1.6.0"
  },
  "browser": {
    "fs": false,
    "path": false,
    "os": false
  }
}

以及我的项目文件列表:

enter image description here

stack overflow TypeError: path.resolve is not a function
原文答案
author avatar

接受的答案

当您导入 factory.js 时,接下来会运行整个文件,它会看到“路径”并抛出错误

path 用于获取合约文件的目录, fs 用于读取合约文件。然后使用 solc 编译器,编译这段代码,运行这个文件

  node fileName.js

根据您使用 solc 定义的指令,此编译将创建一个具有“abi”属性的 .json 文件。到目前为止,我们与 next.js 无关。

然后,将其重构为一个单独的文件:

import abi from "directory/file.json"

const factory = new web3.eth.Contract(
    // pass the abi
    JSON.parse(abi),
    '0x2d54559dCe0DA6C92378A916e9eE0422CEFFCD80'
);

现在你必须将它导入到你的 next.js 项目中。


答案: