无法将 web3 添加到 React 项目
Cannot add web3 to React project
我正在尝试将 Web3 添加到 React 项目中。
我用
初始化了一个新项目
gatsby new
然后,我安装了 web3
npm install --save web3
当我在 index.js
中包含 web3 时
import Web3 from 'web3'
如果我打电话
gatsby develop
我有一些奇怪的错误:
ERROR in ./node_modules/eth-lib/lib/bytes.js 9:193-227
Module not found: Error: Can't resolve 'crypto' in '/home/test/gatsby/test/test/node_modules/eth-lib/lib'
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: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }
@ ./node_modules/swarm-js/lib/api-browser.js 32:12-40
@ ./node_modules/web3-bzz/lib/index.js 24:12-31
@ ./node_modules/web3/lib/index.js 34:10-29
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/ethereumjs-util/dist/account.js 4:13-30
Module not found: Error: Can't resolve 'assert' in >'/home/test/gatsby/test/test/node_modules/ethereumjs-util/dist'
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: { "assert": require.resolve("assert/") }'
- install 'assert'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "assert": false }
@ ./node_modules/ethereumjs-util/dist/index.js 29:13-33
@ ./node_modules/ethereumjs-tx/dist/transaction.js 14:24-50
@ ./node_modules/ethereumjs-tx/dist/index.js 3:20-44
@ ./node_modules/web3-eth-accounts/lib/index.js 35:18-54
@ ./node_modules/web3-eth/lib/index.js 34:15-43
@ ./node_modules/web3/lib/index.js 30:10-29
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/ethereumjs-util/dist/object.js 4:13-30
Module not found: Error: Can't resolve 'assert' in >'/home/test/gatsby/test/test/node_modules/ethereumjs-util/dist'
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: { "assert": require.resolve("assert/") }'
- install 'assert'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "assert": false }
@ ./node_modules/ethereumjs-util/dist/index.js 45:13-32
@ ./node_modules/ethereumjs-tx/dist/transaction.js 14:24-50
@ ./node_modules/ethereumjs-tx/dist/index.js 3:20-44
@ ./node_modules/web3-eth-accounts/lib/index.js 35:18-54
@ ./node_modules/web3-eth/lib/index.js 34:15-43
@ ./node_modules/web3/lib/index.js 30:10-29
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-eth-accounts/lib/index.js 30:76-93
Module not found: Error: Can't resolve 'crypto' in '/home/test/gatsby/test/test/node_modules/web3->eth-accounts/lib'
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: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }
@ ./node_modules/web3-eth/lib/index.js 34:15-43
@ ./node_modules/web3/lib/index.js 30:10-29
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-eth-accounts/node_modules/eth-lib/lib/bytes.js 7:193-227
Module not found: Error: Can't resolve 'crypto' in '/home/test/gatsby/test/test/node_modules/web3-eth-accounts/node_modules/eth-lib/lib'
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: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }
@ ./node_modules/web3-eth-accounts/lib/index.js 29:12-40
@ ./node_modules/web3-eth/lib/index.js 34:15-43
@ ./node_modules/web3/lib/index.js 30:10-29
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-providers-http/lib/index.js 26:11-26
Module not found: Error: Can't resolve 'http' in '/home/test/gatsby/test/test/node_modules/web3-providers-http/lib'
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: { "http": require.resolve("stream-http") }'
- install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "http": false }
@ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48
@ ./node_modules/web3-core/lib/index.js 22:23-58
@ ./node_modules/web3/lib/index.js 29:11-31
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-providers-http/lib/index.js 27:12-28
Module not found: Error: Can't resolve 'https' in '/home/test/gatsby/test/test/node_modules/web3-providers-http/lib'
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: { "https": require.resolve("https-browserify") }'
- install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "https": false }
@ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48
@ ./node_modules/web3-core/lib/index.js 22:23-58
@ ./node_modules/web3/lib/index.js 29:11-31
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 21:11-26
Module not found: Error: Can't resolve 'http' in '/home/test/gatsby/test/test/node_modules/xhr2-cookies/dist'
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: { "http": require.resolve("stream-http") }'
- install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "http": false }
@ ./node_modules/xhr2-cookies/dist/index.js 6:9-38
@ ./node_modules/web3-providers-http/lib/index.js 25:11-49
@ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48
@ ./node_modules/web3-core/lib/index.js 22:23-58
@ ./node_modules/web3/lib/index.js 29:11-31
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 22:12-28
Module not found: Error: Can't resolve 'https' in '/home/test/gatsby/test/test/node_modules/xhr2-cookies/dist'
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: { "https": require.resolve("https-browserify") }'
- install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "https": false }
@ ./node_modules/xhr2-cookies/dist/index.js 6:9-38
@ ./node_modules/web3-providers-http/lib/index.js 25:11-49
@ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48
@ ./node_modules/web3-core/lib/index.js 22:23-58
@ ./node_modules/web3/lib/index.js 29:11-31
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 23:9-22
Module not found: Error: Can't resolve 'os' in '/home/test/gatsby/test/test/node_modules/xhr2-cookies/dist'
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 }
@ ./node_modules/xhr2-cookies/dist/index.js 6:9-38
@ ./node_modules/web3-providers-http/lib/index.js 25:11-49
@ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48
@ ./node_modules/web3-core/lib/index.js 22:23-58
@ ./node_modules/web3/lib/index.js 29:11-31
@ ./src/pages/index.js 9:0-24
@ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5
@ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
webpack compiled with 10 errors
我试过手动安装这些模块,将它们添加到 package.json 等。但没有任何效果。
你能帮帮我吗?
谢谢
不幸的是,大多数 Web3 堆栈严重依赖 window、浏览器和外部加密依赖项,这些依赖项在服务器端不可用。这不仅仅是 Gatsby 的问题,其他 SSR 和静态站点生成器(例如 Next.js)也是如此。
虽然有一些解决方法。参见 Using Client-Side Only Packages on Gatsby
使用不同的库或方法
通过CDN添加客户端包
使用可加载组件加载客户端依赖组件
仅在客户端使用 React.lazy 和 Suspense
根据您的要求,#1 可能不是一个选项。我使用 ethers 而不是 web3 取得了更大的成功。但是您可能 运行 在某些时候遇到与其他软件包类似的问题。
#2 和 3/4 的组合将是可行的方法。
首先,删除导致问题的包 (web3),然后从 gatsby-browser.js
或使用 page/component 上的 react-helmet
加载它们。
盖茨比-browser.js
const addScript = url => {
const script = document.createElement("script")
script.src = url
script.async = true
document.body.appendChild(script)
}
export const onClientEntry = () => {
window.onload = () => {
addScript("https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js")
}
}
反应头盔
<Helmet>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js" />
</Helmet>
您现在应该可以使用 web3 了。请务必使用 typeof window !== "undefined"
检查您是否在浏览器中 运行ning。完整代码示例:
import React from 'react'
import { Helmet } from "react-helmet"
export default function Web3() {
const [blockNr, setBlockNr] = React.useState()
const isBrowser = typeof window !== "undefined"
async function getBlockNumber() {
console.log('Init web3')
const web3 = new window.Web3('https://cloudflare-eth.com')
const currentBlockNumber = await web3.eth.getBlockNumber()
setBlockNr(currentBlockNumber)
}
return (
<div>
{/* Can use either react-helmet or include the script from gatsby-browser */}
<Helmet>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js" />
</Helmet>
{isBrowser &&
<div>
<p>Running in browser..</p>
<button onClick={getBlockNumber}>Get Block #</button>
</div>
}
{blockNr && <span>{blockNr}</span>}
</div>
)
}
您可能仍想延迟加载或使用可加载组件。例如
const LazyWeb3BlockNr = React.lazy(() =>
import("../components/Web3BlockNr")
)
并在您的页面中
<div>
{typeof window !== "undefined" &&
<React.Suspense fallback={<div />}>
<LazyWeb3BlockNr />
</React.Suspense>
}
</div>
这对我有用。将以下内容添加到您的 gatsby-node.js
配置中:
const webpack = require("webpack");
exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
plugins: [
new webpack.ProvidePlugin({
Buffer: [require.resolve("buffer/"), "Buffer"],
}),
],
resolve: {
fallback: {
"crypto": false,
"stream": require.resolve("stream-browserify"),
"assert": false,
"util": false,
"http": false,
"https": false,
"os": false
},
},
})
}
npm install --save-dev react-app-rewired crypto-browserify stream-browserify assert stream-http https-browserify os-browserify url buffer process
在您的根目录中创建一个 config-overrides.js
并添加:
const webpack = require('webpack');
module.exports = function override(config) {
const fallback = config.resolve.fallback || {};
Object.assign(fallback, {
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"assert": require.resolve("assert"),
"http": require.resolve("stream-http"),
"https": require.resolve("https-browserify"),
"os": require.resolve("os-browserify"),
"url": require.resolve("url")
})
config.resolve.fallback = fallback;
config.plugins = (config.plugins || []).concat([
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer']
})
])
return config;
}
现在将 package.json
中的 scripts:
更改为:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
瞧,在浪费了许多时间后为我工作!
我正在尝试将 Web3 添加到 React 项目中。 我用
初始化了一个新项目gatsby new
然后,我安装了 web3
npm install --save web3
当我在 index.js
中包含 web3 时import Web3 from 'web3'
如果我打电话
gatsby develop
我有一些奇怪的错误:
ERROR in ./node_modules/eth-lib/lib/bytes.js 9:193-227 Module not found: Error: Can't resolve 'crypto' in '/home/test/gatsby/test/test/node_modules/eth-lib/lib'
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: { "crypto": require.resolve("crypto-browserify") }' - install 'crypto-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "crypto": false } @ ./node_modules/swarm-js/lib/api-browser.js 32:12-40 @ ./node_modules/web3-bzz/lib/index.js 24:12-31 @ ./node_modules/web3/lib/index.js 34:10-29 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/ethereumjs-util/dist/account.js 4:13-30 Module not found: Error: Can't resolve 'assert' in >'/home/test/gatsby/test/test/node_modules/ethereumjs-util/dist'
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: { "assert": require.resolve("assert/") }' - install 'assert' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "assert": false } @ ./node_modules/ethereumjs-util/dist/index.js 29:13-33 @ ./node_modules/ethereumjs-tx/dist/transaction.js 14:24-50 @ ./node_modules/ethereumjs-tx/dist/index.js 3:20-44 @ ./node_modules/web3-eth-accounts/lib/index.js 35:18-54 @ ./node_modules/web3-eth/lib/index.js 34:15-43 @ ./node_modules/web3/lib/index.js 30:10-29 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/ethereumjs-util/dist/object.js 4:13-30 Module not found: Error: Can't resolve 'assert' in >'/home/test/gatsby/test/test/node_modules/ethereumjs-util/dist'
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: { "assert": require.resolve("assert/") }' - install 'assert' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "assert": false } @ ./node_modules/ethereumjs-util/dist/index.js 45:13-32 @ ./node_modules/ethereumjs-tx/dist/transaction.js 14:24-50 @ ./node_modules/ethereumjs-tx/dist/index.js 3:20-44 @ ./node_modules/web3-eth-accounts/lib/index.js 35:18-54 @ ./node_modules/web3-eth/lib/index.js 34:15-43 @ ./node_modules/web3/lib/index.js 30:10-29 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-eth-accounts/lib/index.js 30:76-93 Module not found: Error: Can't resolve 'crypto' in '/home/test/gatsby/test/test/node_modules/web3->eth-accounts/lib'
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: { "crypto": require.resolve("crypto-browserify") }' - install 'crypto-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "crypto": false } @ ./node_modules/web3-eth/lib/index.js 34:15-43 @ ./node_modules/web3/lib/index.js 30:10-29 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-eth-accounts/node_modules/eth-lib/lib/bytes.js 7:193-227 Module not found: Error: Can't resolve 'crypto' in '/home/test/gatsby/test/test/node_modules/web3-eth-accounts/node_modules/eth-lib/lib'
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: { "crypto": require.resolve("crypto-browserify") }' - install 'crypto-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "crypto": false } @ ./node_modules/web3-eth-accounts/lib/index.js 29:12-40 @ ./node_modules/web3-eth/lib/index.js 34:15-43 @ ./node_modules/web3/lib/index.js 30:10-29 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-providers-http/lib/index.js 26:11-26 Module not found: Error: Can't resolve 'http' in '/home/test/gatsby/test/test/node_modules/web3-providers-http/lib'
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: { "http": require.resolve("stream-http") }' - install 'stream-http' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "http": false } @ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48 @ ./node_modules/web3-core/lib/index.js 22:23-58 @ ./node_modules/web3/lib/index.js 29:11-31 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/web3-providers-http/lib/index.js 27:12-28 Module not found: Error: Can't resolve 'https' in '/home/test/gatsby/test/test/node_modules/web3-providers-http/lib'
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: { "https": require.resolve("https-browserify") }' - install 'https-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "https": false } @ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48 @ ./node_modules/web3-core/lib/index.js 22:23-58 @ ./node_modules/web3/lib/index.js 29:11-31 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 21:11-26 Module not found: Error: Can't resolve 'http' in '/home/test/gatsby/test/test/node_modules/xhr2-cookies/dist'
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: { "http": require.resolve("stream-http") }' - install 'stream-http' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "http": false } @ ./node_modules/xhr2-cookies/dist/index.js 6:9-38 @ ./node_modules/web3-providers-http/lib/index.js 25:11-49 @ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48 @ ./node_modules/web3-core/lib/index.js 22:23-58 @ ./node_modules/web3/lib/index.js 29:11-31 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 22:12-28 Module not found: Error: Can't resolve 'https' in '/home/test/gatsby/test/test/node_modules/xhr2-cookies/dist'
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: { "https": require.resolve("https-browserify") }' - install 'https-browserify' If you don't want to include a polyfill, you can use an empty module like this: resolve.fallback: { "https": false } @ ./node_modules/xhr2-cookies/dist/index.js 6:9-38 @ ./node_modules/web3-providers-http/lib/index.js 25:11-49 @ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48 @ ./node_modules/web3-core/lib/index.js 22:23-58 @ ./node_modules/web3/lib/index.js 29:11-31 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 23:9-22 Module not found: Error: Can't resolve 'os' in '/home/test/gatsby/test/test/node_modules/xhr2-cookies/dist'
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 } @ ./node_modules/xhr2-cookies/dist/index.js 6:9-38 @ ./node_modules/web3-providers-http/lib/index.js 25:11-49 @ ./node_modules/web3-core-requestmanager/lib/index.js 46:18-48 @ ./node_modules/web3-core/lib/index.js 22:23-58 @ ./node_modules/web3/lib/index.js 29:11-31 @ ./src/pages/index.js 9:0-24 @ ./.cache/this_is_virtual_fs_path/$virtual/async-requires.js 21:11-23:5 @ ./.cache/app.js 17:0-52 28:0-70 30:27-40 28:0-70
webpack compiled with 10 errors
我试过手动安装这些模块,将它们添加到 package.json 等。但没有任何效果。 你能帮帮我吗?
谢谢
不幸的是,大多数 Web3 堆栈严重依赖 window、浏览器和外部加密依赖项,这些依赖项在服务器端不可用。这不仅仅是 Gatsby 的问题,其他 SSR 和静态站点生成器(例如 Next.js)也是如此。
虽然有一些解决方法。参见 Using Client-Side Only Packages on Gatsby
使用不同的库或方法
通过CDN添加客户端包
使用可加载组件加载客户端依赖组件
仅在客户端使用 React.lazy 和 Suspense
根据您的要求,#1 可能不是一个选项。我使用 ethers 而不是 web3 取得了更大的成功。但是您可能 运行 在某些时候遇到与其他软件包类似的问题。
#2 和 3/4 的组合将是可行的方法。
首先,删除导致问题的包 (web3),然后从 gatsby-browser.js
或使用 page/component 上的 react-helmet
加载它们。
盖茨比-browser.js
const addScript = url => {
const script = document.createElement("script")
script.src = url
script.async = true
document.body.appendChild(script)
}
export const onClientEntry = () => {
window.onload = () => {
addScript("https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js")
}
}
反应头盔
<Helmet>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js" />
</Helmet>
您现在应该可以使用 web3 了。请务必使用 typeof window !== "undefined"
检查您是否在浏览器中 运行ning。完整代码示例:
import React from 'react'
import { Helmet } from "react-helmet"
export default function Web3() {
const [blockNr, setBlockNr] = React.useState()
const isBrowser = typeof window !== "undefined"
async function getBlockNumber() {
console.log('Init web3')
const web3 = new window.Web3('https://cloudflare-eth.com')
const currentBlockNumber = await web3.eth.getBlockNumber()
setBlockNr(currentBlockNumber)
}
return (
<div>
{/* Can use either react-helmet or include the script from gatsby-browser */}
<Helmet>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js" />
</Helmet>
{isBrowser &&
<div>
<p>Running in browser..</p>
<button onClick={getBlockNumber}>Get Block #</button>
</div>
}
{blockNr && <span>{blockNr}</span>}
</div>
)
}
您可能仍想延迟加载或使用可加载组件。例如
const LazyWeb3BlockNr = React.lazy(() =>
import("../components/Web3BlockNr")
)
并在您的页面中
<div>
{typeof window !== "undefined" &&
<React.Suspense fallback={<div />}>
<LazyWeb3BlockNr />
</React.Suspense>
}
</div>
这对我有用。将以下内容添加到您的 gatsby-node.js
配置中:
const webpack = require("webpack");
exports.onCreateWebpackConfig = ({ actions }) => {
actions.setWebpackConfig({
plugins: [
new webpack.ProvidePlugin({
Buffer: [require.resolve("buffer/"), "Buffer"],
}),
],
resolve: {
fallback: {
"crypto": false,
"stream": require.resolve("stream-browserify"),
"assert": false,
"util": false,
"http": false,
"https": false,
"os": false
},
},
})
}
npm install --save-dev react-app-rewired crypto-browserify stream-browserify assert stream-http https-browserify os-browserify url buffer process
在您的根目录中创建一个 config-overrides.js
并添加:
const webpack = require('webpack');
module.exports = function override(config) {
const fallback = config.resolve.fallback || {};
Object.assign(fallback, {
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"assert": require.resolve("assert"),
"http": require.resolve("stream-http"),
"https": require.resolve("https-browserify"),
"os": require.resolve("os-browserify"),
"url": require.resolve("url")
})
config.resolve.fallback = fallback;
config.plugins = (config.plugins || []).concat([
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer']
})
])
return config;
}
现在将 package.json
中的 scripts:
更改为:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
瞧,在浪费了许多时间后为我工作!