ipfs / js-ipfs

IPFS implementation in JavaScript

Home Page:https://js.ipfs.tech

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Runtime Support: Electron & Muon

daviddias opened this issue · comments

More and more user's have been having trouble using js-ipfs with Electron due to the native module dependencies, see:

The solution found passes by following this example: https://github.com/electron/electron/blob/master/docs/tutorial/using-native-node-modules.md

We should include instructions to guide users to follow that and also run tests in Electron's Node.js Process + Browser process just to be sure #697

Update: I've started tackling this issue, follow the rest of the thread to check the state of things. tl;dr; You should be able to run js-ipfs in the browser process of Electron just fine if you webpack/browserify js-ipfs, running in the main process (aka Node.js) is stil a ❓ due to native dependencies.

I believe that the short term solution is making libp2p recipe's pluggable on node boot so that libp2p-webrtc-star can be added if the user wants. Then I can break libp2p-webrtc-star into libp2p-webrtc-star-browser and libp2p-webrtc-star-nodejs, having the nodejs one installed a posteriori by the users if the user wants.

What would others say it is the best approach here:

  • a) Have two versions of webrtc-star published: -nodejs and -browser
  • b) Support for DI of the wrtc module.

Initially, I was more thinking of a), but to avoid code duplication and double publishing to npm, I'm not more inclined to b).

The end result is the same if you are running js-ipfs in Node.js, it doesn't bring webrtc-star out of the box, however, if you:

const IPFS = require('ipfs')
const wrtc = require('wrtc')
const WStar = require('libp2p-webrtc-star'))

const node = new IPFS({
  libp2p: {
    modules: {
      transports: [
         new WStar(wrtc)
      ]
    }
  }
})

You get WebRTC in Node.js again.

This would take out all of the compilation issues with electron and enable users to use IPFS with the other transports.

except for wrtc, libp2p-webrtc-star doesn't seam to have any logic specific to any environment, so I suggest using DI, with detailed instructions specific for electron on js-ipfs..

Ok, the first 🐉, wrtc, is slayed with #884.

I'm still seeing issues with other native dependencies. #884 adds an electron example so that it is quick to test. Any experienced electron devs out there that could check it as well?

@kenshyx, @josselinchevalay, @kyledrake, @negamaxi et all :)

Hello, I just tested it in renderer process. Unfortunately it doesn't work because I need to install it with --no-optional and it breaks the node-webcrypto-ossl dependency which doesnt work on electron.
Module not found: Error: Can't resolve 'node-webcrypto-ossl' in 'node_modules/libp2p-crypto/src/crypto'

webpack: v3.0.0

Are you using latest js-ipfs master? node-webcrypto-ossl is just used in Node.js, in the Browser it uses WebCrypto directly. Investigating..

Yes, I used latest js-ipfs from master. I forgot to specify that error Module not found: Error: Can't resolve 'node-webcrypto-ossl' in 'node_modules/libp2p-crypto/src/crypto' comes from webpack.

Hi there. Just cloned this repo, main npm install ends well, npm install in examples/electron ends with an error on electron-rebuild stage (some localized text inside):


> js-ipfs-in-electron@0.0.0 postinstall /mnt/sda5/Projects/js-ipfs/examples/electron
> electron-rebuild

✖ Rebuild Failed
An unhandled error occurred inside electron-rebuild
make: вход в каталог «/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/execSync/build»
  CXX(target) Release/obj.target/shell/src/shell.o
../src/shell.cpp:138:26: ошибка: «Arguments» не является именем типа
 Handle<Value> Exec(const Arguments& args) {
                          ^~~~~~~~~
../src/shell.cpp: В функции «v8::Handle<v8::Value> Exec(const int&)»:
../src/shell.cpp:139:17: ошибка: «v8::HandleScope::HandleScope()» is protected within this context
     HandleScope scope;
                 ^~~~~
In file included from /home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/src/node.h:42:0,
                 from ../src/shell.cpp:1:
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:874:13: замечание: declared protected here
   V8_INLINE HandleScope() {}
             ^~~~~~~~~~~
../src/shell.cpp:141:14: ошибка: запрос элемента «Length» в «args», имеющего не классовый тип «const int»
     if (args.Length() < 1) {
              ^~~~~~
../src/shell.cpp:143:34: ошибка: «New» не является элементом «v8::String»
             Exception::TypeError(String::New("First argument must be a string"))
                                  ^~~~~~
../src/shell.cpp:144:9: ошибка: нет декларации «ThrowException» в этой области видимости
         );
         ^
../src/shell.cpp:147:31: ошибка: некорректные типы «const int[int]» для индекса массива
     Local<String> str = args[0]->ToString();
                               ^
../src/shell.cpp:151:18: ошибка: «class v8::HandleScope» has no member named «Close»
     return scope.Close(Integer::New(result));
                  ^~~~~
../src/shell.cpp:151:43: ошибка: нет подходящей функции для вызова «v8::Integer::New(int&)»
     return scope.Close(Integer::New(result));
                                           ^
In file included from /home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/src/node.h:42:0,
                 from ../src/shell.cpp:1:
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:2756:25: замечание: candidate: static v8::Local<v8::Integer> v8::Integer::New(v8::Isolate*, int32_t)
   static Local<Integer> New(Isolate* isolate, int32_t value);
                         ^~~
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:2756:25: замечание:   кандидат ожидает 2 аргумента, 1 предоставлено
../src/shell.cpp: В функции «void RegisterModule(v8::Handle<v8::Object>)»:
../src/shell.cpp:155:17: ошибка: «NewSymbol» не является элементом «v8::String»
     target->Set(String::NewSymbol("exec"),
                 ^~~~~~
../src/shell.cpp:156:39: ошибка: нет подходящей функции для вызова «v8::FunctionTemplate::New(v8::Handle<v8::Value> (&)(const int&))»
             FunctionTemplate::New(Exec)->GetFunction());
                                       ^
In file included from /home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/src/node.h:42:0,
                 from ../src/shell.cpp:1:
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:5090:34: замечание: candidate: static v8::Local<v8::FunctionTemplate> v8::FunctionTemplate::New(v8::Isolate*, v8::FunctionCallback, v8::Local<v8::Value>, v8::Local<v8::Signature>, int, v8::ConstructorBehavior)
   static Local<FunctionTemplate> New(
                                  ^~~
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:5090:34: замечание:   нет известных преобразований для аргумента 1 из «v8::Handle<v8::Value>(const int&) {aka v8::Local<v8::Value>(const int&)}» в «v8::Isolate*»
shell.target.mk:92: ошибка выполнения рецепта для цели «Release/obj.target/shell/src/shell.o»
make: выход из каталога «/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/execSync/build»
make: *** [Release/obj.target/shell/src/shell.o] Ошибка 1
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/node-gyp/lib/build.js:258:23)
gyp ERR! stack     at emitTwo (events.js:106:13)
gyp ERR! stack     at ChildProcess.emit (events.js:194:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:215:12)
gyp ERR! System Linux 4.11.8-200.fc25.x86_64
gyp ERR! command "/usr/bin/node" "/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/.bin/node-gyp" "rebuild" "--target=1.6.11" "--arch=x64" "--dist-url=https://atom.io/download/electron" "--build-from-source"
gyp ERR! cwd /mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/execSync
gyp ERR! node -v v7.10.0
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok 

Failed with exit code: 1

Error: make: вход в каталог «/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/execSync/build»
  CXX(target) Release/obj.target/shell/src/shell.o
../src/shell.cpp:138:26: ошибка: «Arguments» не является именем типа
 Handle<Value> Exec(const Arguments& args) {
                          ^~~~~~~~~
../src/shell.cpp: В функции «v8::Handle<v8::Value> Exec(const int&)»:
../src/shell.cpp:139:17: ошибка: «v8::HandleScope::HandleScope()» is protected within this context
     HandleScope scope;
                 ^~~~~
In file included from /home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/src/node.h:42:0,
                 from ../src/shell.cpp:1:
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:874:13: замечание: declared protected here
   V8_INLINE HandleScope() {}
             ^~~~~~~~~~~
../src/shell.cpp:141:14: ошибка: запрос элемента «Length» в «args», имеющего не классовый тип «const int»
     if (args.Length() < 1) {
              ^~~~~~
../src/shell.cpp:143:34: ошибка: «New» не является элементом «v8::String»
             Exception::TypeError(String::New("First argument must be a string"))
                                  ^~~~~~
../src/shell.cpp:144:9: ошибка: нет декларации «ThrowException» в этой области видимости
         );
         ^
../src/shell.cpp:147:31: ошибка: некорректные типы «const int[int]» для индекса массива
     Local<String> str = args[0]->ToString();
                               ^
../src/shell.cpp:151:18: ошибка: «class v8::HandleScope» has no member named «Close»
     return scope.Close(Integer::New(result));
                  ^~~~~
../src/shell.cpp:151:43: ошибка: нет подходящей функции для вызова «v8::Integer::New(int&)»
     return scope.Close(Integer::New(result));
                                           ^
In file included from /home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/src/node.h:42:0,
                 from ../src/shell.cpp:1:
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:2756:25: замечание: candidate: static v8::Local<v8::Integer> v8::Integer::New(v8::Isolate*, int32_t)
   static Local<Integer> New(Isolate* isolate, int32_t value);
                         ^~~
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:2756:25: замечание:   кандидат ожидает 2 аргумента, 1 предоставлено
../src/shell.cpp: В функции «void RegisterModule(v8::Handle<v8::Object>)»:
../src/shell.cpp:155:17: ошибка: «NewSymbol» не является элементом «v8::String»
     target->Set(String::NewSymbol("exec"),
                 ^~~~~~
../src/shell.cpp:156:39: ошибка: нет подходящей функции для вызова «v8::FunctionTemplate::New(v8::Handle<v8::Value> (&)(const int&))»
             FunctionTemplate::New(Exec)->GetFunction());
                                       ^
In file included from /home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/src/node.h:42:0,
                 from ../src/shell.cpp:1:
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:5090:34: замечание: candidate: static v8::Local<v8::FunctionTemplate> v8::FunctionTemplate::New(v8::Isolate*, v8::FunctionCallback, v8::Local<v8::Value>, v8::Local<v8::Signature>, int, v8::ConstructorBehavior)
   static Local<FunctionTemplate> New(
                                  ^~~
/home/negamaxi/.electron-gyp/.node-gyp/iojs-1.6.11/deps/v8/include/v8.h:5090:34: замечание:   нет известных преобразований для аргумента 1 из «v8::Handle<v8::Value>(const int&) {aka v8::Local<v8::Value>(const int&)}» в «v8::Isolate*»
shell.target.mk:92: ошибка выполнения рецепта для цели «Release/obj.target/shell/src/shell.o»
make: выход из каталога «/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/execSync/build»
make: *** [Release/obj.target/shell/src/shell.o] Ошибка 1
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/node-gyp/lib/build.js:258:23)
gyp ERR! stack     at emitTwo (events.js:106:13)
gyp ERR! stack     at ChildProcess.emit (events.js:194:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:215:12)
gyp ERR! System Linux 4.11.8-200.fc25.x86_64
gyp ERR! command "/usr/bin/node" "/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/.bin/node-gyp" "rebuild" "--target=1.6.11" "--arch=x64" "--dist-url=https://atom.io/download/electron" "--build-from-source"
gyp ERR! cwd /mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/execSync
gyp ERR! node -v v7.10.0
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok 

Failed with exit code: 1
    at SafeSubscriber._error (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/spawn-rx/lib/src/index.js:267:84)
    at SafeSubscriber.__tryOrUnsub (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:238:16)
    at SafeSubscriber.error (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:197:26)
    at Subscriber._error (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:128:26)
    at Subscriber.error (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:102:18)
    at MapSubscriber.Subscriber._error (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:128:26)
    at MapSubscriber.Subscriber.error (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:102:18)
    at SafeSubscriber._next (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/spawn-rx/lib/src/index.js:241:65)
    at SafeSubscriber.__tryOrSetError (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:247:16)
    at SafeSubscriber.next (/mnt/sda5/Projects/js-ipfs/examples/electron/node_modules/rxjs/Subscriber.js:187:27)

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN js-ipfs-in-electron@0.0.0 No repository field.
npm ERR! Linux 4.11.8-200.fc25.x86_64
npm ERR! argv "/usr/bin/node" "/usr/bin/npm" "install"
npm ERR! node v7.10.0
npm ERR! npm  v4.2.0
npm ERR! code ELIFECYCLE
npm ERR! errno 255
npm ERR! js-ipfs-in-electron@0.0.0 postinstall: `electron-rebuild`
npm ERR! Exit status 255
npm ERR! 
npm ERR! Failed at the js-ipfs-in-electron@0.0.0 postinstall script 'electron-rebuild'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the js-ipfs-in-electron package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     electron-rebuild
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs js-ipfs-in-electron
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls js-ipfs-in-electron
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/negamaxi/.npm/_logs/2017-07-07T17_46_54_901Z-debug.log

Just finished migrating off one of the offenders to make this happen (node-webcrypto-ossl). Now, the new one is: uws:

An unhandled error occurred inside electron-rebuild
  CXX(target) Release/obj.target/uws/src/Extensions.o
  CXX(target) Release/obj.target/uws/src/Group.o
In file included from ../src/Group.cpp:1:
In file included from ../src/Group.h:4:
In file included from ../src/WebSocket.h:4:
In file included from ../src/WebSocketProtocol.h:5:
../src/Networking.h:7:10: fatal error: 'openssl/opensslv.h' file not found
#include <openssl/opensslv.h>

this one comes from libp2p-webrtc-star use of socket.io. We can move away from socket.io

Is this still an issue? I've haven't been able to reproduce any of the issues linked here. I've so far been successful in running IPFS in the main and renderer processes.

I'll be concentrating on - ipfs/aegir#157.

  1. Still experiencing Uncaught TypeError: createServer is not a function using 0.26.0 IPFS bundle from cdn via script tag and trying to start ipfs node in a renderer.js.

  2. Using 0.26.0 npm module in the renderer.js I get an error with following message in devTools:
    "Failed to require LevelDOWN (The module '/mnt/sda5/Projects/electron-ipfs-quick-start/node_modules/leveldown/build/Release/leveldown.node'↵was compiled against a different Node.js version using↵NODE_MODULE_VERSION 51. This version of Node.js requires↵NODE_MODULE_VERSION 54. Please try re-compiling or re-installing↵the module (for instance, using `npm rebuild` or`npm install`).). Try `npm install leveldown` if it's missing".
    2.1 doing npm rebuild or npm install or npm install leveldown didn't help.
    2.2 same error popups in a modal window trying to use ipfs in a main.js.

Node.js 7.9.0, Chromium 58.0.3029.110, and Electron 1.7.6.

@negamaxi I was able to reproduce the error with electron version - 1.7.6.

The issues is not specifically related to the version of electron, but the version that the native modules are built with - electron 1.7.6 is using a different node version (7.9.0 in this case) that the one the modules are being installed with - electron-rebuild should help with that however it is breaking for me when I try running it. I'll continue to troubleshoot this issue.

@negamaxi

Building with npm by executing the bellow script works for me:

# Electron's version.
export npm_config_target=1.7.6
# The architecture of Electron, can be ia32 or x64.
export npm_config_arch=x64
export npm_config_target_arch=x64
# Download headers for Electron.
export npm_config_disturl=https://atom.io/download/electron
# Tell node-pre-gyp that we are building for Electron.
export npm_config_runtime=electron
# Tell node-pre-gyp to build module from source code.
export npm_config_build_from_source=true
# Install all dependencies, and store cache to ~/.electron-gyp.
HOME=~/.electron-gyp npm install

Could you try it out and let me know if it works for you as well?

Building with electron-rebuild is still an issue.

@dryajov confirmed, it works.

You could use a postinstall script like:

"postinstall":
      "cd ./src && cross-env npm_config_target=1.7.12 npm_config_arch=x64 npm_config_target_arch=x64 npm_config_disturl=https://atom.io/download/electron npm_config_runtime=electron npm_config_build_from_source=true HOME=~/.electron-gyp yarn"

copy from @dryajov 's example and change the electron version.

I was building an Electron / IPFS app and it had a devil of a time with Windows builds because of UWS. The UWS author appears disinclined to support Electron, and but it can be made to work by fixing how the binding.gyp links SSL libraries. Simply put you need to add 'libraries': ['libeay32', 'ssleay32'] to the stanza in there which refers to os == 'win'. I haven't got the energy to pursue this with the upstream author but if you or anyone else wants to get it working, that's how.

The previous problem noted above (missing opensslv.h) is solved by following the directions on the UWS repo: install vcpkg, and then install the UWS dependencies he lists there.

If you are using ipfsd-ctl to start an ipfs instance and run into trouble like NODE_MODULE_VERSION 57 NODE_MODULE_VERSION 59 xxx, you can try

const DaemonFactory = require('ipfsd-ctl');
const ipfsDaemon = DaemonFactory.create({ type: 'proc', exec: require('ipfs') });

Instead of DaemonFactory.create({ type: 'js' });

Since we have built native modules to match nodejs version inside the electron, and ipfsd-ctl will try to run your built module on the nodejs outside the electron (the one on your working environment).

There is now full support with the last dragon slayed by @leo6104! \o/