Getting Netlify build error when importing web3 in NextJS application - 'Error: Can't resolve 'electron' in...'

Getting Netlify build error when importing web3 in NextJS application - 'Error: Can't resolve 'electron' in...'

我正在构建一个使用 web3 与以太坊智能合约进行交互的网页。每当我将 web3 导入页面时,Netlify 构建中都会出现错误:

9:54:39 PM: ModuleNotFoundError: Module not found: Error: Can't resolve 'electron' in '/opt/build/repo/node_modules/swarm-js/node_modules/got'
9:54:39 PM: > Build error occurred
9:54:39 PM: Error: > Build failed because of webpack errors

我可以通过将 web3 导入添加到页面来重现这个错误与没有得到它:

import web3 from '../ethereum/web3'

以上代码只是从另一个文件中导出一个实例化的 web3 实例:

import Web3 from "web3";
 
let web3;
 
if (typeof window !== "undefined" && typeof window.ethereum !== "undefined") {
  // We are in the browser and metamask is running.
  window.ethereum.request({ method: "eth_requestAccounts" });
  web3 = new Web3(window.ethereum);
} else {
  // We are on the server *OR* the user is not running metamask
  const provider = new Web3.providers.HttpProvider(
    "https://mainnet.infura.io/v3/{INFURA_KEY}"
  );
  web3 = new Web3(provider);
}
 
export default web3;

我认为这可能与 web3 在浏览器中只能 运行 和 NextJS 做一些 SSR 有关,但我不能完全确定这个问题。这是我的整页代码:

import Head from 'next/head'
import Header from '../components/Header'
import Menu from '../components/Menu'
import Footer from '../components/Footer'
import web3 from '../ethereum/web3'
const compiledFaucet = require('../ethereum/contracts/Faucet.json')


export default function Faucet() {
  const getICHCHandler = () => {
    console.log('dripping ICHC from faucet')
  }

  return (
    <div className="container">
      <Head>
        <title>I Can Has Cheezburger Token</title>
        <link rel="icon" href="/favicon.ico" />
        <link rel="stylesheet" href="/fonts/fonts.css"></link>
        <link href="https://unpkg.com/nes.css@latest/css/nes.min.css" rel="stylesheet" />
        {/* Global site tag (gtag.js) - Google Analytics */}
        <script async src="https://www.googletagmanager.com/gtag/js?id=G-2EF9PKF797"></script>
        <script
          dangerouslySetInnerHTML={{
            __html: `
              window.dataLayer = window.dataLayer || []
              function gtag(){dataLayer.push(arguments)}
              gtag('js', new Date())

              gtag('config', 'G-2EF9PKF797')
            `,
          }}
        />
      </Head>

      <main>
        <Header />
        <div className="container">
          <h2 className="pink">ICHC Token Faucet</h2>
          <img src="/faucet_med.png" alt="ICHC Token Faucet" />
          <div className="faucet-container">
            <div className="nes-field">
              <label htmlFor="name_field" className="input-label">Enter wallet address:</label>
              <input type="text" id="name_field" className="nes-input faucet-txt-input" />
            </div>
            
            <button onClick={getICHCHandler} type="button" className="nes-btn is-primary faucet-btn">Get ICHC Token</button>
          </div>
          <Menu />
        </div>
      </main>

      <Footer />

      <style jsx>{`
        .container {
          padding: 1rem 0.5rem;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
        }

        .container h2 {
          font-size: 1em;
          font-family: "press_start_2pregular", Times,"Times New Roman", serif;
        }

        .container img {
          margin-top: 1em;
        }

        main {
          padding: 0 0;
          margin: 0 0 5rem 0;
          flex: 1;
          display: flex;
          flex-direction: column;
          justify-content: flex-start;
          align-items: center;
        }

        .faucet-container {
          display: flex;
          flex-direction: column;
          justify-content: flex-start;
          align-items: center;
          width: 700px;
          margin: 1em 0;
        }

        .input-label {
          font-size: .7em;
          font-family: "press_start_2pregular", Times,"Times New Roman", serif;
        }

        .faucet-txt-input {
          width: 700px;
          font-size: .9em;
          font-family: "press_start_2pregular", Times,"Times New Roman", serif;
        }

        .faucet-btn {
          margin-top: 2em;
          margin-bottom: 1em;
          font-size: .8em;
          font-family: "press_start_2pregular", Times,"Times New Roman", serif;
          color: black;
        }

        .faucet-btn span {
          margin-left: 40px;
        }
        
        .faucet-btn:hover {
          cursor: pointer;
          color: #ffffff;
        }

        a {
          color: inherit;
          text-decoration: none;
        }

        .title a {
          color: #0070f3;
          text-decoration: none;
        }

        .title a:hover,
        .title a:focus,
        .title a:active {
          text-decoration: underline;
        }

        .grid {
          display: flex;
          align-items: center;
          justify-content: center;
          flex-wrap: wrap;

          max-width: 1000px;
          margin-top: 1rem;
        }

        @media (max-width: 600px) {
          .grid {
            width: 100%;
            flex-direction: column;
          }
        }
      `}</style>

      <style jsx global>{`
        html,
        body {
          padding: 0;
          margin: 0;
          color: aqua;
          font-family: Times,"Times New Roman", serif;
          cursor: default !important;
        }

        .white {
          color: #FFFFFF;
        }

        .pink {
          color: #FF007A;
        }

        .default-font {
          font-family: Times,"Times New Roman", serif;
        }

        body {
          background: url("/stars_sparkle_bg.gif");
        }

        * {
          box-sizing: border-box;
        }
      `}</style>
    </div>
  )
}

export async function getServerSideProps(ctx) {
  const faucetContract = new web3.eth.Contract(
    compiledFaucet.abi,
    "0x4099E633A607F6ED211e2c82565003d6F755e75e"
  )
return { faucetContract }
}

感谢任何提示或建议。

对于面临此问题的任何其他人,以下是经过大量研究后最终对我有用的方法。

这似乎是一个 Webpack 问题,其中一个依赖项的 web3 依赖项中 'electron' 的条件/内联导入未被不正确地忽略。解决方案是显式忽略 next.config.js 文件中的电子,如下所示:

/**
 * @type {import('next').NextConfig}
 */

 const nextConfig = {
    webpack: (config, { webpack }) => {
        config.plugins.push(new webpack.IgnorePlugin({
            resourceRegExp: /^electron$/
        }),);
        return config
    }
  }
  
  module.exports = nextConfig