Closed linonetwo closed 1 year ago
Instead of trying to run IPFS directly, check out how the browser and node versions work.
You'll want to create new versions of those files which only use features available in react-native. I think the only transport that you'll get working is libp2p-websocket-star
.
React-Native is like a more constrained browser environment at the moment, and getting it anywhere as near to the node version of IPFS will require a bunch of new transports that work with RN plugins.
I was able to get ipfs and orbit-db working on react native using janeasystems/nodejs-mobile.
I had to make the following changes though:
git clone https://github.com/janeasystems/nodejs-mobile ~/nodejs-mobile
pushd ~/nodejs-mobile
./tools/ios_framework_prepare.sh
popd
GYP_DEFINES="OS=ios" npm_config_nodedir="~/nodejs-mobile" npm_config_platform="ios" npm_config_node_engine="chakracore" npm --verbose install krahimian/leveldown --build-from-source
/bin/sh
code:
/usr/bin/codesign --force --sign $EXPANDED_CODE_SIGN_IDENTITY --preserve-metadata=identifier,entitlements,flags --timestamp=none $(find "$CODESIGNING_FOLDER_PATH/nodejs-project/" -type f -name "*.node")
I used that build of leveldown for js-datastore-level and ipfs-repo. I also had to update js-datastore-level to work with leveldown@3.0.0 (krahimian/js-datastore-level@9545fe5)
After making those changes, I was able to initialize an ipfs repo. I'm going to do some stress testing this weekend to see how well it works.
@RangerMauve Do you mean making some tweaks to files in https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime to make files like repo-rn.js
?
And why libp2p-websocket-star
is difficult to deal with?
@krahimian Is https://github.com/krahimian/record your project? Can I try it out?
@linonetwo
some tweaks to files
Yes, I think you'll want to do that if you want it to run in a RN context
And why libp2p-websocket-star is difficult to deal with?
I don't think I said it was difficult to deal with, quite the opposite. It's the only transport that can receive connections in the browser AFAIK.
By the way, @krahimian 's suggestion of using nodejs-mobile is way better than trying to get it to run in regular RN.
@linonetwo yea that's the project - there's not much to try out right now. I'll update you when there is.
The goal is to build a proof of concept twitter and soundcloud using just ipfs/orbit-db.
@krahimian hope You succeed soon! How about simply using: https://github.com/janeasystems/nodejs-mobile-react-native ?
I was able to get js-ipfs working on nodejs mobile (react native) both on simulator and a device (after using this fix).
However, I noticed a difference in performance and ipfs boot/start time if I add a swarm address (websocket-star).
I see there are plans for adding libp2p-connection-manager in the next release, which I think would help address performance issues on mobile.
In the meantime, does anyone have any recommendations for any settings/configurations or strategies I can try to boost performance in a mobile environment?
How about https://github.com/textileio/textile-mobile 's approach? They got it worked and is MIT licensed!
@mistakia , have you already tried all the suggestions addressing performance issues ?
Yup! 👍
Bundling the files did have a major impact on CPU usage (not just load times). After nodejs-mobile v0.1.5
and using browserify to bundle, load times and cpu usage are reasonable and the app is running smoothly.
However, I have yet to really battle test it with a large number of peers and under poor network conditions.
@mistakia looking forward, to see your updates, thanks! 👍
What's the status on this issue? I created a react-native project to test @mistakia's approach with nodejs-mobile but I can't get it working with versions higher than 0.31.7, get the following error with 0.34.4:
Failed : error 0:61 [61]
/private/var/containers/Bundle/Application/18B0EE12-3521-4CAD-B769-BFC01D169B41/reactnativenodejsexample.app/nodejs-project/node_modules/proper-lockfile/lib/lockfile.js:47
return acquireLock(file, { ...options, stale: 0 }, callback);
^^^^
SyntaxError: Expected identifier, string or number
at createScript (vm.js:80:3)
at runInThisContext (vm.js:139:3)
at Module.prototype._compile (module.js:588:3)
at Module._extensions[.js] (module.js:635:3)
at Module.prototype.load (module.js:545:3)
at tryModuleLoad (module.js:508:5)
at Module._load (module.js:500:3)
at Module.prototype.require (module.js:568:3)
at require (internal/module.js:11:7)
at Anonymous function (/private/var/containers/Bundle/Application/18B0EE12-3521-4CAD-B769-BFC01D169B41/reactnativenodejsexample.app/nodejs-project/node_modules/proper-lockfile/index.js:3:1)
The problem with sticking with 0.37.1 is that it includes vulnerable dependencies that have been patched already. Here is the example repo:
Looks like it doesnt like the object spread syntax that proper-lockfile is using.
cc @hugomrdias
@pedrouid from what i can see nodejs-mobile is on node 8 and we have stopped supporting that, the solution here is to bundle your js code with rollup (or whatever bundler you prefer) and pass babel-preset-env targeting node 8. this will also keep you safe from any other dependency that uses newer js syntax.
Thanks @hugomrdias, I did try bundling with both browserify and webpack using @babel/preset-env but I still got other object spread errors. I saw that nodejs-mobile
plans to move to the latest nodejs version by the end of Q1 which is too long for my need so I will have to move the ipfs node to a backend.
React-native support or native implementation for mobile is definitely needed for building decentralized solutions. I will keep subscribed to this issue anyway
@pedrouid that seems weird you sure you are running babel on your dependencies? Because that should work. Try explicitly including this plugin in babel https://babeljs.io/docs/en/babel-plugin-proposal-object-rest-spread
Thanks, I also tried that with multiple plugins as well. You can check the branches on my test repo:
https://github.com/pedrouid/react-native-nodejs-example
I always get an error on the line that has ...trail[index]
even after bundling when running nodejs-mobile
asyncMap(pathComponents.map((part, index) => ({ part, index })), ({ part, index }, cb) => {
if (trail[index]) {
return cb(null, {
name: part,
...trail[index]
})
}
// if we are not at the last path component and we are
// not creating intermediate directories make a fuss
if (index !== pathComponents.length - 1 && !options.parents) {
return cb(new Error('file does not exist'))
}
waterfall([
(done) => createNode(context, 'directory', options, done),
({ cid, node }, done) => {
done(null, {
cid,
size: node.size,
name: part
})
}
], cb)
}, cb)
I was able to get ipfs and orbit-db working on react native using janeasystems/nodejs-mobile.
I had to make the following changes though:
- Clone and build the nodejs-mobile project in your home, so you can use the headers for building the native module (this will take a long time):
git clone https://github.com/janeasystems/nodejs-mobile ~/nodejs-mobile pushd ~/nodejs-mobile ./tools/ios_framework_prepare.sh popd
- Run npm install inside your nodejs-project using the headers from nodejs-mobile and different settings for building leveldown@3.0.0 for iOS (mistakia/leveldown@5cc1c2d):
GYP_DEFINES="OS=ios" npm_config_nodedir="~/nodejs-mobile" npm_config_platform="ios" npm_config_node_engine="chakracore" npm --verbose install krahimian/leveldown --build-from-source
- Open the iOS project in Xcode and add a "New Run Script Phase" to your target's Build Phases, containing the following Shell
/bin/sh
code:/usr/bin/codesign --force --sign $EXPANDED_CODE_SIGN_IDENTITY --preserve-metadata=identifier,entitlements,flags --timestamp=none $(find "$CODESIGNING_FOLDER_PATH/nodejs-project/" -type f -name "*.node")
I used that build of leveldown for js-datastore-level and ipfs-repo. I also had to update js-datastore-level to work with leveldown@3.0.0 (mistakia/js-datastore-level@9545fe5)
After making those changes, I was able to initialize an ipfs repo. I'm going to do some stress testing this weekend to see how well it works.
Can you guys inform procedure for Android to use ipfs and ipfs-pubsub in React-Native ? I m searched in more ways there is no proper solution and i cant use that.
@kesavananbu this is related to leveldb and not @pedrouid 's problem right ?
can't you just use another datastore instead of going through that trouble ?
The attempt below are using nodejs-mobile-react-native
.
I used zeit/ncc to compile the code of the nodejs-project
, but this way the problem with the node version remains. After that I used babel to convert to Node 8.
Running the compiled script in my computer with Node 8.6 works. In the React Native side I always receive the error below:
*/Backoff.prototype.setJitter=function(jitter){this.jitter=jitter;};/***/},/***/2453:/***/function(module,__unusedexports,__webpack_require__){/* Copyright (c) 2017 Rod Vagg, MIT License */var xtend=__webpack_require__(6667);var AbstractIterator=__webpack_require__(3701);var AbstractChainedBatch=__webpack_require__(6356);var hasOwnProperty=Object.prototype.hasOwnProperty;var rangeOptions='start end gt gte lt lte'.split(' ');function AbstractLevelDOWN(location){if(!arguments.length||location===undefined){throw new Error('constructor requires at least a location argument');}if(typeof location!=='string'){throw new Error('constructor requires a location string argument');}this.location=location;this.status='new';}AbstractLevelDOWN.prototype.open=function(options,callback){var self=this;var oldStatus=
SyntaxError: Invalid character
at createScript (vm.js:80:3)
at runInThisContext (vm.js:139:3)
at Module.prototype._compile (module.js:588:3)
at Module._extensions[.js] (module.js:635:3)
at Module.prototype.load (module.js:545:3)
at tryModuleLoad (module.js:508:5)
at Module._load (module.js:500:3)
at Module.runMain (module.js:665:3)
at startup (bootstrap_node.js:188:9)
at Anonymous function (bootstrap_node.js:611:3)
Before the experiment I described above I tried using noderify + babel but I received the same Invalid character
error in a different part of the code.
OK, the problem about Invalid character
is because of human-to-milliseconds
, this bug: https://github.com/hacdias/human-to-milliseconds/issues/1. I fixed it like described in the bug.
Now, it's partially working. The nodejs side is not breaking the app but it's not executing nothing after I create the node: e.g. const ipfs = new IPFS(ipfsConfig);
.
I'm able to get version 0.34.4
(as thats the latest working version with ipfs-log/OrbitDB) running on version 0.4.1
of nodejs-mobile-react-native
which ships with node 10.13.0
. I'm still needing to browserify and babilify for performance reasons and to avoid the issues @pedrouid was seeing. Also, I'm still patching the human-to-milliseconds
package.
browserify -o bundle.js -g [ babelify --presets [ @babel/preset-env --targets [ --node 10.13.0 ] ] ] --node --im -u 'leveldown' main.js
Everything works when no repo exists. However, when starting ipfs after a repo has been created/initialized from a previous time, I get this runtime issue:
bundle.js referenced in the stacktrace.
To save some time, I've tracked it down to this line: https://github.com/ipfs/js-ipfs-mfs/blob/v0.8.0/src/core/utils/with-mfs-root.js#L39
ipfs remains in the starting
state. Any insights or suggestions are greatly appreciated.
Update: passing in { preload: { enabled: false } }
bypasses the runtime issue. Seems to be related to preload-mfs
.
@mistakia I tried all of your fixes and I keep getting the following error:
/Users/Username/Library/Developer/CoreSimulator/Devices/F7B46EA3-1AE3-4DF2-B02E-81A54CDDC694/data/Containers/Bundle/Application/66E4C6E1-FB32-4E2F-936C-E585D6D64EC0/VIVA.app/nodejs-project/node_modules/proper-lockfile/lib/lockfile.js:61
return acquireLock(file, { ...options, stale: 0 }, callback);
^^^^
SyntaxError: Expected identifier, string or number
at Script (vm.js:87:7)
at createScript (vm.js:251:3)
at runInThisContext (vm.js:303:3)
at Module.prototype._compile (internal/modules/cjs/loader.js:656:3)
at Module._extensions[.js] (internal/modules/cjs/loader.js:699:3)
at Module.prototype.load (internal/modules/cjs/loader.js:598:3)
at tryModuleLoad (internal/modules/cjs/loader.js:537:5)
at Module._load (internal/modules/cjs/loader.js:529:3)
at Module.prototype.require (internal/modules/cjs/loader.js:636:3)
at require (internal/modules/cjs/helpers.js:20:7)
Any idea how to fix this error specifically?
I believe the babelify transform for browserify should fix this. See my previous comment for the full command. I used the @babel/preset-env
preset and passed in the node target. Also note that I ran the browserify transform with -g
and not -t
otherwise it won't transform stuff in node_modules
.
@mistakia Thanks for the tip! Is it normal for it to attempt to transform the node_modules
in the root of my project outside of the the nodejs-project folder?
Also do I run the babelify command in the root of my entire project or in the nodejs-project
directory?
You want to run browserify/babelify in ./nodejs-assets/nodejs-project/
in which case it shouldnt be accessing anything in the node_modules
in the root of the project.
@mistakia That's what I thought, but for some reason I'm getting conflict errors from libraries like @react-native-community/react-native-asyncstorage
in the node_modules
folder of my project's root. I'm just copying and pasting this line in the nodejs-project
folder:
browserify -o bundle.js -g [ babelify --presets [ @babel/preset-env --targets [ --node 10.13.0 ] ] ] --node --im -u 'leveldown' main.js
When I remove those the libraries in my root node_modules
the command finishes without errors but doesn't seem to change anything, which leads me to believe it's not affecting my nodejs-project
folder for some reason?
I don't know if this has to do with my issue, but I'm getting
[BABEL] Note: The code generator has deoptimised the styling of /Users/Admin/Documents/APP/nodejs-assets/nodejs-project/node_modules/lodash/lodash.js as it exceeds the max of 500KB.
before the script attempts to work on the project root's modules in APP/node_modules
I don't know if this has to do with my issue, but I'm getting
[BABEL] Note: The code generator has deoptimised the styling of /Users/Admin/Documents/APP/nodejs-assets/nodejs-project/node_modules/lodash/lodash.js as it exceeds the max of 500KB.
before the script attempts to work on the project root's modules in
APP/node_modules
Seeing the same here with the latest nodejs-mobile and libp2p dependencies. A lot of things seem to depend on lodash though. Maybe there's a way to make Babel avoid processing this file?
Don't worry about that [BABEL] Note:
message. It's just saying that it's stopped trying to track the styling information because the file is too big.
I am seting up IPFS 0.4.0 with nodejs-mobile-react-native 0.5.0 on MacOS. But always failed with build when launch npx react-native run-ios. Here is my issue post. The React Native version is 0.61.5 and 3 node version 10.13.0/10.16.0/10.17.0 all failed with launch build. It is related to node-gyp and I am not sure what exactly is wrong.
Any suggestion about how to fix?
js-ipfs is being deprecated in favor of Helia. You can https://github.com/ipfs/js-ipfs/issues/4336 and read the migration guide.
Please feel to reopen with any comments by 2023-06-02. We will do a final pass on reopened issues afterwards (see https://github.com/ipfs/js-ipfs/issues/4336).
I completely agree that we want IPFS to be able to run in react-native flawlessly. I believe this is possible with Helia, as we've already "proven" that we can "almost" replace public gateways with in-app service workers. Please try out Helia and let us know if you run into issues when using it in React-Native!
To use IPFS on react-native, I have done following things:
core-js
to polyfillset
andSymbol
react-native-browser-polyfill
to polyfillself
rn-nodeify
to installreact-native-crypto
Dragons just come one by one, can we make it easier to use js-ipfs on react-native?
Reproducible example https://github.com/linonetwo/sermover .