electron / forge

:electron: A complete tool for building and publishing Electron applications
https://electronforge.io
MIT License
6.41k stars 506 forks source link

Conflict between two versions of jsonfile #2144

Closed raphael10-collab closed 3 years ago

raphael10-collab commented 3 years ago

As you can see from here: https://github.com/ipfs/js-ipfs/issues/3508#issuecomment-772772507 and from here: https://github.com/ipfs/js-ipfs/issues/3508#issuecomment-773151528 I have this situation:

This is the package.json

{
  "name": "IpfsPlaying",
  "version": "2.0.2",
  "description": "IpfsPlaying",
  "main": ".webpack/main",
  "scripts": {
    "start": "cross-env NODE_ENV=development electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make",
    "publish": "electron-forge publish",
    "lint": "eslint --ext .ts ."
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/raphael10-collab/IpfsPlaying"
  },
  "license": "MIT",
  "config": {
    "forge": "./tools/forge/forge.config.js"
  },
  "devDependencies": {
    "@electron-forge/cli": "^6.0.0-beta.54",
    "@electron-forge/maker-deb": "6.0.0-beta.53",
    "@electron-forge/maker-rpm": "6.0.0-beta.53",
    "@electron-forge/maker-squirrel": "^6.0.0-beta.54",
    "@electron-forge/maker-zip": "6.0.0-beta.53",
    "@electron-forge/plugin-webpack": "6.0.0-beta.53",
    "@types/react": "^16.9.49",
    "@types/react-dom": "^16.9.8",
    "@types/webpack-env": "^1.15.2",
    "@typescript-eslint/eslint-plugin": "^4.1.1",
    "@typescript-eslint/parser": "^4.1.1",
    "copy-webpack-plugin": "6",
    "cross-env": "^7.0.2",
    "electron": "^10.1.2",
    "eslint": "^7.9.0",
    "eslint-import-resolver-alias": "^1.1.2",
    "eslint-plugin-import": "^2.20.0",
    "eslint-plugin-react": "^7.20.6",
    "fork-ts-checker-webpack-plugin": "^5.2.0",
    "less": "^3.12.2",
    "node-loader": "^1.0.1",
    "react-hot-loader": "^4.12.21",
    "ts-loader": "^8.0.3",
    "typescript": "^4.0.2",
    "webpack": "4"
 },
 "dependencies": {
    "@hot-loader/react-dom": "^16.13.0",
    "ipfs": "^0.54.1",
    "ipfs-http-client": "^49.0.1",
    "ipfs-utils": "^6.0.0",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-viewer": "^3.2.2",
    "react-window": "^1.8.6"
  } 
}

When using ipfs in main.ts I get this error:

A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot find module 'jsonfile/utils'

A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot find module 'jsonfile/utils'
    at webpackMissingModule (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:78837:87)
    at Object../node_modules/fs-extra/lib/json/output-json.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:78837:176)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/fs-extra/lib/json/index.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:78765:25)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/fs-extra/lib/index.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:78731:6)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/ipfs-utils/src/files/glob-source.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:115083:12)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack/main/index.js:21:30)
    at Object../node_modules/ipfs-core/src/index.js (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:107575:20)

People of IPFS Project made, kindly, thoughrough analysis of the problem, discovering that there is a collision between two versions of jsonfile:

There are two copies of jsonfile in my node_modules folder:

$ find . -type d -name jsonfile
./node_modules/jsonfile                          <-- v4.0.0
./node_modules/fs-extra/node_modules/jsonfile    <-- v6.1.0

I removed all the packages not stricly required for ipfs and for a bare minimum electron-react-typescript app. And discovered that, in accordance what was already found by IPFS's people, these are the modules which depend on jsonfile :

(base) marco@pc01:~/webMatters/electronMatters/IpfsPlaying$ npm ls jsonfile
IpfsPlaying@2.0.2 /home/marco/webMatters/electronMatters/IpfsPlaying
├─┬ @electron-forge/cli@6.0.0-beta.54
│ ├─┬ @electron-forge/core@6.0.0-beta.54
│ │ └─┬ electron-packager@15.2.0
│ │   └─┬ galactus@0.2.1
│ │     ├─┬ flora-colossus@1.0.1
│ │     │ └─┬ fs-extra@7.0.1
│ │     │   └── jsonfile@4.0.0  deduped
│ │     └─┬ fs-extra@4.0.3
│ │       └── jsonfile@4.0.0  deduped
│ ├─┬ @electron/get@1.12.2
│ │ └─┬ fs-extra@8.1.0
│ │   └── jsonfile@4.0.0 
│ └─┬ fs-extra@9.0.1
│   └── jsonfile@6.1.0 
└─┬ @electron-forge/maker-squirrel@6.0.0-beta.54
  └─┬ electron-winstaller@4.0.1
    └─┬ fs-extra@7.0.1
      └── jsonfile@4.0.0  deduped

If I remove the jsonfile v4 I get the error: "An unhandled exception has occured inside Forge":

(base) marco@pc01:~/webMatters/electronMatters/IpfsPlaying$ rm -rf ./node_modules/jsonfile/
(base) marco@pc01:~/webMatters/electronMatters/IpfsPlaying$ yarn start
yarn run v1.22.5
$ cross-env NODE_ENV=development electron-forge start

An unhandled exception has occurred inside Forge:
Cannot find module 'jsonfile'
Require stack:
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/node_modules/fs-extra/lib/json/jsonfile.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/node_modules/fs-extra/lib/json/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/node_modules/fs-extra/lib/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/dist/cjs/utils.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/dist/cjs/artifact-utils.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/dist/cjs/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/core/dist/api/make.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/core/dist/api/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/cli/dist/util/check-system.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/cli/dist/electron-forge.js
Error: Cannot find module 'jsonfile'
Require stack:
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/node_modules/fs-extra/lib/json/jsonfile.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/node_modules/fs-extra/lib/json/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/node_modules/fs-extra/lib/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/dist/cjs/utils.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/dist/cjs/artifact-utils.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/dist/cjs/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/core/dist/api/make.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/core/dist/api/index.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/cli/dist/util/check-system.js
- /home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron-forge/cli/dist/electron-forge.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1030:15)
    at Function.Module._load (internal/modules/cjs/loader.js:899:27)
    at Module.require (internal/modules/cjs/loader.js:1090:19)
    at require (internal/modules/cjs/helpers.js:75:18)
    at Object.<anonymous> (/home/marco/webMatters/electronMatters/IpfsPlaying/node_modules/@electron/get/node_modules
/fs-extra/lib/json/jsonfile.js:4:18)
    at Module._compile (internal/modules/cjs/loader.js:1201:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1221:10)
    at Module.load (internal/modules/cjs/loader.js:1050:32)
    at Function.Module._load (internal/modules/cjs/loader.js:938:14)
    at Module.require (internal/modules/cjs/loader.js:1090:19)

In a nutshell the problem is that electron-forge uses the version 4 of jsonfile, while Ipfs uses version 6 of jsonfile. And webpack loads the version 4. How to make electron-forge and webpack loading a specific version of a module, if two versions are present within the npm tree?

raphael10-collab commented 3 years ago

This kind of problem seems solved with webpack aliases:

webpack.helpers.js

/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
const path = require('path');
const cwd = process.cwd();

// Creates Webpack Aliases using CWD path
const createWebpackAliases = (als) => {
  const result = {};
  for (const name in als) {
    result[name] = path.join(cwd, als[name]);
  }
  return result;
};

// Export webpack helpers
module.exports = {
  createWebpackAliases,
};

webpack.aliases.js :

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { createWebpackAliases } = require('./webpack.helpers');

// Webpack aliases to resolve
const aliases = createWebpackAliases({
  '@src': 'src',
  '@app': 'src/app',
  '@static': 'src/static',
  'jsonfile': './node_modules/fs-extra/node_modules/jsonfile',
  'nanoid/random': './node_modules/nanoid',
  'nanoid/format': './node_modules/nanoid'
});

// Export aliases
module.exports = aliases;

But now another problem has come :

(node:26402) UnhandledPromiseRejectionWarning: Error: No native build was 
found for platform=linux arch=x64 runtime=electron abi=82 uv=1 libc=glibc 
node=12.16.3 electron=10.2.0 webpack=true
    loaded from: /home/marco/webMatters/electronMatters/IpfsPlaying
/.webpack/main

    at Function.module.exports../node_modules/node-gyp-
build/index.js.load.path (/home/marco/webMatters/electronMatters/IpfsPlaying
/.webpack/main/index.js:193915:9)
    at load (/home/marco/webMatters/electronMatters/IpfsPlaying/.webpack
/main/index.js:193877:30)
    at Object../node_modules/leveldown/binding.js (/home/marco/webMatters
/electronMatters/IpfsPlaying/.webpack/main/index.js:130044:101)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying
/.webpack/main/index.js:21:30)
    at Object../node_modules/leveldown/leveldown.js (/home/marco/webMatters
/electronMatters/IpfsPlaying/.webpack/main/index.js:130158:17)
at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying
/.webpack/main/index.js:21:30)
    at Object../node_modules/level/level.js (/home/marco/webMatters
/electronMatters/IpfsPlaying/.webpack/main/index.js:130032:111)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/IpfsPlaying
/.webpack/main/index.js:21:30)
    at new LevelDatastore (/home/marco/webMatters/electronMatters/IpfsPlaying
/.webpack/main/index.js:62350:23)
    at Object.createBackend [as create] (/home/marco/webMatters
/electronMatters/IpfsPlaying/.webpack/main/index.js:111452:10)
(node:26402) UnhandledPromiseRejectionWarning: Unhandled promise rejection.      
This error originated either by throwing inside of an async function without a 
catch block, or by rejecting a promise which was not handled with .catch(). 
To terminate the node process on unhandled promise rejection, use the CLI flag
 `--unhandled-rejections=strict` (see https://nodejs.org
/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:26402) [DEP0018] DeprecationWarning: Unhandled promise rejections are 
deprecated. In the future, promise rejections that are not handled will 
terminate the Node.js process with a non-zero exit code.