ipfs / js-ipfs

IPFS implementation in JavaScript
https://js.ipfs.tech
Other
7.44k stars 1.25k forks source link

Module not found: Error: Can't resolve 'electron' in one of the deps of ipfs-utils #4024

Closed gouravkhator closed 2 years ago

gouravkhator commented 2 years ago

Version Details

Severity: High

Description:

ipfs-utils/src/fetch.js relies on electron-fetch/lib/index.es.js.

In the full project, I can log process.versions but electron does not exist in process.versions object, and that is why electron variable is also not set.

So, it gives error as below, when I run npx preact build:

✖ ERROR ../node_modules/electron-fetch/lib/index.es.js
Module not found: Error: Can't resolve 'electron' in './node_modules/electron-fetch/lib'
 @ ../node_modules/electron-fetch/lib/index.es.js 1271:13-32
 @ ../node_modules/ipfs-utils/src/fetch.js
 @ ../node_modules/ipfs-utils/src/http/fetch.browser.js
 @ ../node_modules/ipfs-utils/src/http/fetch.js
 @ ../node_modules/ipfs-utils/src/http.js
 @ ../node_modules/ipfs-utils/src/files/url-source.js
 @ ../node_modules/ipfs-core/cjs/src/index.js
 @ ./utils/ipfs.util.ts

Side Notes

I have been using ipfs-core npm package in my preact project.

Preact uses webpack to bundle the application. I have not modified the default webpack config, which comes pre-packed in with mentioned preact package.

Steps to reproduce the error:

My code

In the stacktrace mentioned above,

The ./utils/ipfs.util.ts file is my code.

import {create, IPFS} from 'ipfs-core';

export async function createIPFSNode() {
    return await create();
}

export async function addDataToIPFS(ipfsNode: IPFS, data: string) {
    if (ipfsNode) {
        const results = await ipfsNode.add(data);
        return results.cid.toString();
    }

    throw new Error("IPFS Node not created.. Please create one, before adding the data to IPFS");
}

Root cause

After tracing the files from the stacktrace, I found that, there is some issue in ../node_modules/electron-fetch/lib/index.es.js file:

Pasting some parts of ../node_modules/electron-fetch/lib/index.es.js file, which causes the issue:

let electron; // istanbul ignore else

if (process.versions.electron) {
  electron = require('electron');
}

// .. some more code which depends on electron variable.

As the process.versions.electron is not there, the electron variable is not set, which leads to the issue.

Note: the main issue is that the ../node_modules/ipfs-utils/src/fetch.js file relies on electron-fetch. There, the electron property is not defined in process.versions.


My package.json file

{
  "private": true,
  "name": "client",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "build": "preact build",
    "serve": "sirv build --port 3000 --cors --single",
    "dev": "preact watch",
    "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
    "test": "jest ./tests"
  },
  "eslintConfig": {
    "parser": "@typescript-eslint/parser",
    "extends": [
      "preact",
      "plugin:@typescript-eslint/recommended"
    ],
    "ignorePatterns": [
      "build/"
    ]
  },
  "dependencies": {
    "ipfs-core": "^0.13.0",
    "preact": "^10.3.1",
    "preact-render-to-string": "^5.1.4",
    "preact-router": "^3.2.1"
  },
  "devDependencies": {
    "@types/enzyme": "^3.10.5",
    "@types/jest": "^26.0.8",
    "@typescript-eslint/eslint-plugin": "^2.25.0",
    "@typescript-eslint/parser": "^2.25.0",
    "enzyme": "^3.11.0",
    "enzyme-adapter-preact-pure": "^3.1.0",
    "eslint": "^6.8.0",
    "eslint-config-preact": "^1.1.1",
    "jest": "^27.2.5",
    "jest-preset-preact": "^4.0.2",
    "preact-cli": "^3.0.0",
    "sirv-cli": "^1.0.0-next.3",
    "typescript": "^4.5.2"
  },
  "jest": {
    "preset": "jest-preset-preact",
    "setupFiles": [
      "<rootDir>/tests/__mocks__/browserMocks.ts",
      "<rootDir>/tests/__mocks__/setupTests.ts"
    ]
  },
  "browserslist": {
    "production": [
      "chrome >= 67",
      "edge >= 79",
      "firefox >= 68",
      "opera >= 54",
      "safari >= 14"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Output of process.versions when run from my project files:

{
  node: '16.13.0',
  v8: '9.4.146.19-node.13',
  uv: '1.42.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.17.2',
  modules: '93',
  nghttp2: '1.45.1',
  napi: '8',
  llhttp: '6.0.4',
  openssl: '1.1.1l+quic',
  cldr: '39.0',
  icu: '69.1',
  tz: '2021a',
  unicode: '13.0',
  ngtcp2: '0.1.0-DEV',
  nghttp3: '0.1.0-DEV'
}

@IPFS Developers, I humbly request you to provide support on this issue. It is impacting my side project and delaying my work.

welcome[bot] commented 2 years ago

Thank you for submitting your first issue to this repository! A maintainer will be here shortly to triage and review. In the meantime, please double-check that you have provided all the necessary information to make this process easy! Any information that can help save additional round trips is useful! We currently aim to give initial feedback within two business days. If this does not happen, feel free to leave a comment. Please keep an eye on how this issue will be labeled, as labels give an overview of priorities, assignments and additional actions requested by the maintainers:

Finally, remember to use https://discuss.ipfs.io if you just need general support.

gouravkhator commented 2 years ago

Also note that I have tried following solutions from https://github.com/electron/electron/issues/27961 But no luck. It didn't resolve my error.

I think the IPFS team needs to edit their versions of electron-fetch npm package, because this issue can be solved as suggested by this comment

gouravkhator commented 2 years ago

Seems like electron-fetch uses node-gyp, and as node-gyp does not work in browsers, it was having issues.

That's why process.versions did not have electron property.

Thus, I realised that the package might work, when used in a server. So, I created a server and in that server (i.e., nodejs environment), the ipfs-core package works fine.

Kindly check on how to enable the node-gyp in browsers.

amandesai01 commented 2 years ago

IPFS uses electron-fetch only when it detects that it is running inside electron. (It uses is-electron to do that.) Else, it uses native fetch. This piece of code can be found here.

node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js. Since it interacts with machine and filesystem, using it in browser is not possible.

Lastly, Try some insights from Issue #4011

gouravkhator commented 2 years ago

But why I was getting the issue then, is there some dependency, which is causing the electron environment to be set partially, without setting the process.versions.electron property.

Please check my package.json file and help me resolve this issue, if there is some dependency which causes the electron environment to be set, which indirectly causes ipfs-utils to import electron-fetch module.

CallumGrindle commented 2 years ago

Having this same issue when using ipfs-utils in browser

lidel commented 2 years ago

Looks like a duplicate of https://github.com/ipfs/js-ipfs/issues/4011 ?

brickpop commented 2 years ago

Why was this issue closed?