如何在Webpack 5中填充Node核心模块

398

webpack 5不再自动为node.js核心模块添加polyfill。

如何修复这个问题?

BREAKING CHANGE: webpack < 5过去会默认包含node.js核心模块的polyfills。现在不再是这样。请验证是否需要此模块并配置相应的polyfill。

错误信息


我尝试过在这里提到的解决方案,但没有成功:https://github.com/webpack/webpack/issues/11868 - Saber
尝试这个解决方案:https://alchemy.com/blog/how-to-polyfill-node-core-modules-in-webpack-5 - codemon
对于 Gatsby 用户,请参见 https://dev59.com/K8Hqa4cB1Zd3GeqP8tpT,修改 gatsby-node.js 而不是 config-overrides.js。 - Steve Scott
也许你在这里加了一个错误的导入:import { text } from "body-parser"; - undefined
37个回答

155

当我从webpack v4升级到v5时,也遇到了这些错误。 通过对webpack.config.js进行以下更改来解决:

添加resolve.fallback属性

移除node属性

{
resolve: {
  modules: [...],
  fallback: {
    "fs": false,
    "tls": false,
    "net": false,
    "path": false,
    "zlib": false,
    "http": false,
    "https": false,
    "stream": false,
    "crypto": false,
    "crypto-browserify": require.resolve('crypto-browserify'), //if you want to use this module also don't forget npm i crypto-browserify 
  } 
},
entry: [...],
output: {...},
module: {
  rules: [...]
},
plugins: [...],
optimization: {
  minimizer: [...],
},
// node: {
//   fs: 'empty',
//   net: 'empty',
//   tls: 'empty'
// },
}

从v4升级到v5 => https://webpack.js.org/migrate/5/#clean-up-configuration,需要清理配置。

5
node_modules里面存放的是什么?[...] - Justin Meskan
15
你在哪个文件中进行了这些编辑?即使你提供的Webpack迁移指南也似乎没有提到这一点。 - Ruik
3
@Ruik 通常我们会在应用程序的根目录下的 webpack.config.js 文件中设置 webpack 配置。https://webpack.js.org/configuration/ - Maqsood Ahmed
6
@MaqsoodAhmed 我的应用程序根目录中似乎没有这个文件(webpack.config.js)??? - johnDoe
7
@johnDoe 我认为你是使用 create-react-app 创建的项目。因此,你可以通过弹出项目或进入 react-scripts 的 node_modules 文件夹来获取配置文件。 https://dev59.com/nlYM5IYBdhLWcg3wxSR_ - Maqsood Ahmed
显示剩余5条评论

115

使用node-polyfill-webpack-plugin重新添加对Node.js核心模块的支持:

安装该软件包后,将以下内容添加到您的webpack.config.js文件中:

const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")

module.exports = {
    // Other rules...
    plugins: [
        new NodePolyfillPlugin()
    ]
}

18
这个解决方案解决了大部分错误,但并非全部。我仍需要使用@lukas-bach的方法修复“fs”和“path-browserify”。 - kenecaswell
3
@kenecaswell,我很乐意听取改进建议。在浏览器中应该如何填充fs?我们只需使用一个shim吗? - Richie Bendall
3
我收回之前的话,node-polyfill-webpack-plugin 对于我的客户端打包非常有效。我还在打包服务器端代码,需要'fs'和'path-browserify'。一旦只将您的插件应用于我的客户端构建,它就运行得很好。 - kenecaswell
4
大家都在提webpack.config.js文件,但我在我的应用程序根目录中找不到它。请问有人可以给予建议吗? - johnDoe
3
@johnDoe 如果你正在使用create-react-app,webpack.config.js文件可以在node_modules/react-scripts中找到(https://dev59.com/nlYM5IYBdhLWcg3wxSR_#48396154)。如果要编辑CRA项目的webpack配置,你可能需要考虑使用react-app-rewired包(https://www.npmjs.com/package/react-app-rewired)。 - Wasbeer
显示剩余3条评论

89
我认为这里大多数的答案都可以解决你的问题。然而,如果你不需要在node开发中使用Polyfills,那么我建议你在Webpack模块配置中使用target: 'node'。这帮助我解决了这个问题。
以下是一些关于此回答的文档:https://webpack.js.org/concepts/targets/ 输入图像描述

5
它能够很好地适用于 Node 16.. 版本。 - hastrb
5
不适用于 Node 14.0.0。 - user2128702
这对我没有起作用,它完全崩溃了我的应用程序,出现了一些关于打包的错误。 - codmitu
解决错误,但在浏览器控制台中出现了“require未定义”的错误。 - Dotista
2
适用于Node v18.12.1,运行良好。 - user3290525

75

根据Web3文档

如果您使用的是create-react-app版本>=5,可能会遇到构建问题。这是因为NodeJS polyfill未包含在最新版本的create-react-app中。

解决方案:

安装react-app-rewired和缺失的模块。

如果您使用的是yarn:

yarn add --dev react-app-rewired crypto-browserify stream-browserify assert stream-http https-browserify os-browserify url buffer process

如果您正在使用 npm:

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中,将start、build和test的scripts字段进行修改。将react-scripts替换为react-app-rewired。 之前:

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
},

之后:

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
},

现在应该包含了缺失的 Nodejs polyfills,并且您的应用程序应该能够与 web3 一起正常运行。

如果您想要隐藏控制台创建的警告:

在 config-overrides.js 中的 override 函数中添加:

config.ignoreWarnings = [/Failed to parse source map/];

3
这很有帮助,我将config-overrides文件添加到我的根目录中,然后在src文件夹中的js文件中调用了crypto。当我这样做时,我遇到了错误: 模块未找到:错误:您尝试导入/Users/username/abja/identity/node_modules/crypto-browserify/index.js,它位于项目src/目录之外。不支持src/之外的相对导入。 - Mabel Oza
它对我有效。 - user16102215
1
对我来说不起作用: 找不到模块:错误:无法解析“/Users/bartolini/workspace-osa/osa-web-ui/node_modules/axios/lib/defaults”中的“process/browser” 你是指“browser.js”吗? 重大变更:请求“process/browser”未能解析,仅因为它被视为完全指定的模块。 - bartektartanus
还有一个类似的问题,但是出现在另一个库(react-markdown 的依赖项)中:模块未找到:错误:无法解析“...\node_modules\uvu\node_modules\kleur”中的“process/browser”。 你是指 'browser.js' 吗? 重大变更:请求“process/browser”未能解析,仅因为它被完全指定解析。 - Paintoshi
在搜索了数小时(天?)后,唯一有效的方法。我认为应将其标记为已采纳答案。 - LeandroG
显示剩余2条评论

39

我在使用create-react-app遇到了这个问题,因为默认情况下它给了我...

"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.2"

我只需将 react-scripts 的版本更改为 4.0.3,就解决了问题。


3
这对我起了作用。这是一个临时解决方案,但目前很成功。 - Luke Dupin
1
唯一有效的方法,谢谢!很好的临时解决方案,直到它坏掉的时候,希望会有更现代化的解决方案。 - user1300214
2
这对我也起作用了,我们的应用程序中还没有webpack集成,所以这对我来说是最好的解决方案。 - Ronnie
降级到4.0.3对我也起作用了。 - Ashiq Dey
使用React 18,我在4.0.3版本中比5.0.1版本多20个漏洞。 - codmitu

32

看起来你使用了path包,但是它默认不包含在webpack构建中。对我来说,像这样扩展webpack配置有所帮助:

{
  // rest of the webpack config
  resolve: {
    // ... rest of the resolve config
    fallback: {
      "path": require.resolve("path-browserify")
    }
  },
}

如果您正在使用yarn,请通过yarn add path-browserify --dev 或者通过 npm install path-browserify --save-dev 安装 path-browserify


如果它将被发送到浏览器,它应该是一个开发依赖吗? - MkMan
4
如果你将你的应用程序构建为一个 webpack 项目,并只出售已构建的产物,那么这就无关紧要了。仅在将软件包发布到 NPM 时才需要区分开发和正常依赖项,因为软件包的使用者只会安装非开发依赖项。 - Lukas Bach

23

你需要 React => v17,React 脚本 => v5,webpack => v5

解决问题的方法

1)安装

"fs": "^2.0.0",  // npm i fs
"assert": "^2.0.0",  // npm i assert
"https-browserify": "^1.0.0", // npm i https-browserify
"os": "^0.1.2", // npm i os
"os-browserify": "^0.3.0", // npm i os-browserify
"react-app-rewired": "^2.1.9", //npm i react-app-rewired
"stream-browserify": "^3.0.0", // stream-browserify
"stream-http": "^3.2.0", //stream-http

2) 在根目录创建config-overrides.js文件 图像

3) 将配置添加到config-overrides.js文件中

const webpack = require('webpack');
module.exports = function override(config, env) {
    config.resolve.fallback = {
        url: require.resolve('url'),
        fs: require.resolve('fs'),
        assert: require.resolve('assert'),
        crypto: require.resolve('crypto-browserify'),
        http: require.resolve('stream-http'),
        https: require.resolve('https-browserify'),
        os: require.resolve('os-browserify/browser'),
        buffer: require.resolve('buffer'),
        stream: require.resolve('stream-browserify'),
    };
    config.plugins.push(
        new webpack.ProvidePlugin({
            process: 'process/browser',
            Buffer: ['buffer', 'Buffer'],
        }),
    );

    return config;
}

3) 更改 packages.json 文件

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-app-rewired eject"
}

问题已解决 :)


不需要 / browser,使用以下代码:os:require.resolve('os-browserify/browser') - David Peer
这个对我有用,解决了问题。 - S. N
对我有用!非常感谢。我像个疯子一样搜索了一个小时,寻找解决方法。 - csgeek
1
fs似乎没有进行polyfill。 npm i fs无法工作,该包在安全保持中。 - Harshit Narang
1
react-app-rewired的文档中说:“不要翻转eject脚本的调用”。 - Octopus
我尝试在浏览器中直接使用svgr,但它一直抱怨os.homedir不是一个函数,尽管它使用了最新版本的os-browserify。可悲的是,我找不到任何关于我特定问题的答案,但我猜这种方式尝试使用Node应用程序可能有点巧妙。 - bas

18

最近Create React App发布了v5版本,现在采用Webpack v5. 这将会完全打破很多库,包括web3,因为所需的Node核心库polyfills将缺失。

要快速解决此问题,您可以在package.json中进行更改:

"react-scripts": "^5.0.0"

对于这个

"react-scripts": "4.0.3"

之后:

rm -r node_modules

rm package-lock.json

npm install

1
不幸的是,这个解决方案让我陷入了这种令人沮丧的情况:https://dev59.com/5FEG5IYBdhLWcg3wM2Zu - Gus T Butt
1
我遇到了Gus T Butt指出的相同情况,但我更喜欢将react-scripts降级到4.0.3,直到这个问题得到解决。正如@chokshen在这个线程[1]中提到的那样,在package.json的resolutions部分中添加固定的依赖版本可以很好地解决问题。 "resolutions": { "//": "See https://github.com/facebook/create-react-app/issues/11773", "react-error-overlay": "6.0.9" },我的环境: Node: 16.14.2 react-scripts: 4.0.3 react: 17.0.2[1]https://dev59.com/5FEG5IYBdhLWcg3wM2Zu - Kelei Ren

14

当我重新安装节点模块时,我遇到了问题,我的webpack当前版本是5.38.1,我通过npm i path-browserify -D解决了这个问题。安装后,您需要更新webpack.config.js中的resolve{},添加fallback: {"fs": false, "path": require.resolve("path-browserify")}。如果不使用"fs": false,会显示错误信息,例如:Module not found: Error: Can't resolve 'fs' in '/YOUR DIRECTORY ...',因此不要忘记添加它;与其他内容一起,看起来像:

module.exports = {
   ...
   resolve: {
    extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],// other stuff
    fallback: {
      "fs": false,
      "path": require.resolve("path-browserify")
    }
  },
};

如果在您的webpack.config.js文件中存在node属性,则删除它。


10

方法一

  • 打开project/node_modules/react-scripts/config/webpack.config.js

  • 在fallback中添加"crypto": require.resolve("crypto-browserify")

resolve: {
   fallback: {
       "crypto": require.resolve("crypto-browserify")
   }
} 
  • 安装 npm i crypto-browserify
  • 重启您的应用程序。

如果您提交了代码,则上述方法不起作用,因为我们没有node_modules

方法2

  • 安装patch-package: yarn add patch-package

  • 安装所需的polyfill(进行应用程序的初始构建并将其告诉您)。

  • 修改node_modules/react-scripts/config/webpack.config.js。这是一个示例。这是来自Webpack文档的内容。

module.exports = {
  //...
  resolve: {
    fallback: {
      assert: require.resolve('assert'),
      buffer: require.resolve('buffer'),
      console: require.resolve('console-browserify'),
      constants: require.resolve('constants-browserify'),
      crypto: require.resolve('crypto-browserify'),
      domain: require.resolve('domain-browser'),
      events: require.resolve('events'),
      http: require.resolve('stream-http'),
      https: require.resolve('https-browserify'),
      os: require.resolve('os-browserify/browser'),
      path: require.resolve('path-browserify'),
      punycode: require.resolve('punycode'),
      process: require.resolve('process/browser'),
      querystring: require.resolve('querystring-es3'),
      stream: require.resolve('stream-browserify'),
      string_decoder: require.resolve('string_decoder'),
      sys: require.resolve('util'),
      timers: require.resolve('timers-browserify'),
      tty: require.resolve('tty-browserify'),
      url: require.resolve('url'),
      util: require.resolve('util'),
      vm: require.resolve('vm-browserify'),
      zlib: require.resolve('browserify-zlib'),
    },
  },
};
  • 不要全部添加,只添加您需要的那些。

确保在修改webpack配置之前先安装软件包。

  • 运行yarn patch-package react-scripts。这将生成一个补丁(这应该在你的仓库中提交)。

  • 在package.json中添加一个postinstall脚本:"postinstall": "yarn patch-package"。现在,任何时候,有人在此项目上安装npm依赖项时,都会自动应用您在步骤3中创建的补丁。

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "postinstall": "yarn patch-package"
  },

10
方法1非常糟糕。永远不要建议更改node_modules中的任何内容!! - BonisTech
方法2不适用于process。请查看其他使用ProvidePlugin的答案。 - lawrence

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接