DTeam 技术日志

Doer、Delivery、Dream

排错:Angular 项目构建 web3 报错 Module not found: Can't resolve XXX

冯宇 Posted at — Mar 10, 2021 阅读

症状

某个 Angular 项目引入 web3 依赖时,构建出现了类似于下面的错误:

ERROR in ./node_modules/@pedrouid/iso-crypto/dist/cjs/helpers/env/node.js
Module not found: Error: Can't resolve 'crypto' in 'node_modules/@pedrouid/iso-crypto/dist/cjs/helpers/env'

ERROR in ./node_modules/@ethersproject/web/lib.esm/geturl.js
Module not found: Error: Can't resolve 'http' in 'node_modules/@ethersproject/web/lib.esm'

ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js
Module not found: Error: Can't resolve 'http' in 'node_modules/xhr2-cookies/dist'

ERROR in ./node_modules/@ethersproject/web/lib.esm/geturl.js
Module not found: Error: Can't resolve 'https' in 'node_modules/@ethersproject/web/lib.esm'

ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js
Module not found: Error: Can't resolve 'https' in 'node_modules/xhr2-cookies/dist'
resolve 'https' in 'node_modules/xhr2-cookies/dist'

ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js
Module not found: Error: Can't resolve 'os' in 'node_modules/xhr2-cookies/dist'

ERROR in ./node_modules/cipher-base/index.js
Module not found: Error: Can't resolve 'stream' in 'node_modules/cipher-base'

ERROR in ./node_modules/keccak/lib/api/keccak.js
Module not found: Error: Can't resolve 'stream' in 'node_modules/keccak/lib/api'

ERROR in ./node_modules/keccak/lib/api/shake.js
Module not found: Error: Can't resolve 'stream' in 'node_modules/keccak/lib/api'

ERROR in ./node_modules/@ethersproject/web/lib.esm/geturl.js
Module not found: Error: Can't resolve 'zlib' in 'node_modules/@ethersproject/web/lib.esm'

分析

由于 Angular 主要是将项目按照浏览器规格进行构建,而报错的这几个 module 比如os, stream, fs之流的是 Node API 提供的,在浏览器运行环境是不提供这几个 API 的,因此构建报错,找不到这些 Node 运行环境的 module。

解决方案

Angular 底层使用 webpack,而 webpack 是支持 browserify 的,即在浏览器环境中填充部分 Node API,以便这些模块能在浏览器环境运行起来(如 web3.js 等等)。但是 Angular 本身的配置并不支持自定义 webpack 配置,因此我们需要通过打补丁的方案修正这个配置。

以下内容参考自 gist

package.json:

{...
  "scripts": {
    "postinstall": "node patch.js",
    ...
  }
}

patch.js:

// Angular >= 11
const fs = require("fs");
const f =
  "node_modules/@angular-devkit/build-angular/src/webpack/configs/browser.js";

fs.readFile(f, "utf8", function (err, data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(
    /node: false/g,
    'node: {crypto: true, stream: true, fs: "empty"}'
  );

  fs.writeFile(f, result, "utf8", function (err) {
    if (err) return console.log(err);
  });
});
// ----

// For Angular <11
const fs = require("fs");
const f =
  "node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js";

fs.readFile(f, "utf8", function (err, data) {
  if (err) {
    return console.log(err);
  }
  var result = data.replace(
    /node: false/g,
    "node: {crypto: true, stream: true}"
  );

  fs.writeFile(f, result, "utf8", function (err) {
    if (err) return console.log(err);
  });
});
// ----

重新npm i之后再构建项目应该就可以修复这个错误了。


友情链接


相关文章