developmentseed / field-data-collection

MIT License
0 stars 4 forks source link

react-native prototype #1

Open sethvincent opened 7 years ago

sethvincent commented 7 years ago

So far I've been having issues getting react-native and osm-p2p working together.

The challenge is getting react-native to run node modules.

Here are some things I've tried:

react-native doesn't support indexeddb, but that should be solved with the react-native-level module: https://github.com/developmentseed/field-data-collection/blob/master/prototypes/react-native/FieldDataCollection/lib/osm-p2p.js

mojodna commented 7 years ago

I seem to have gotten slightly further along with https://github.com/mojodna/surveyor-prototype

In order for it to pick up node_modules, I had to restart the packager. Next was that hyperlog and other dependencies require "core" Node libraries, so I had to install browser polyfills (see package.json) and manually patch some files in node_modules according to what I ran into.

The last error I ran into was:

error: bundling: UnableToResolveError: Unable to resolve module `stream` from `/Users/seth/src/mojodna/Surveyor/node_modules/level-logs/node_modules/from2/node_modules/readable-stream/readable.js`: Module does not exist in the module map or in these directories:
  /Users/seth/src/mojodna/Surveyor/node_modules/level-logs/node_modules/from2/node_modules
,   /Users/seth/src/mojodna/Surveyor/node_modules/level-logs/node_modules
,   /Users/seth/src/mojodna/Surveyor/node_modules
mojodna commented 7 years ago

FTR, node_modules/hyperlog/lib/messages.js looks like this after I patched it:

var protobuf = require('protocol-buffers')
var fs = require('browserify-fs')
var path = require('path-browserify')

module.exports = protobuf(fs.readFileSync(path.join(__dirname, '..', 'schema.proto'), 'utf-8'))
mojodna commented 7 years ago

IIRC, there's a way to configure Webpack to provide alternative versions of dependencies when imported or required, possibly https://webpack.js.org/plugins/normal-module-replacement-plugin/ or https://webpack.js.org/configuration/resolve/ (better).

Related:

osm-p2p, etc. are all built to target browsers using browserify, so to wedge them into a React Native app, we'll either need to incorporate browserify into RN's packager or figure out how to achieve similar results. Haul uses Webpack, which seems promising.

mojodna commented 7 years ago

After mojodna/surveyor-prototype@8f33146, it gets much further along, but RN now bails with:

SyntaxError: Unexpected token '>' (http://localhost:8081/index.android.bundle?platform-android&dev=true&hot=false&minify=false:3263
mojodna commented 7 years ago

Vaguely relevant: https://github.com/pouchdb/pouchdb/issues/3787

mojodna commented 7 years ago

The source of the "unexpected token" error is asyncstorage-down, which ships with arrow functions. Haul does not transcode node_modules, per https://github.com/callstack-io/haul/blob/master/README.md#limitations, unlike react-native-cli's packager, so a workaround was to manually use babel to replace them (after removing encoding.js, which isn't in git and was probably included by accident). Longer-term, we can probably use the babel webpack loader to do this for us.

mojodna commented 7 years ago

With that addressed, I'm back to TypeError: undefined is not an object (evaluating 'this.idb.open')..., which means that something is trying to use IndexedDB (node_modules/idbwrapper/idbstore.js).

mojodna commented 7 years ago

...which is not from osm-p2p at all, but rather from browserify-fs, which was configured as the fs shim that hyperlog needed, so we've gone full circle and could probably use osm-p2p (not osm-p2p-db) directly, since it'd be using the same abstraction layer.

mojodna commented 7 years ago

react-native-level-fs wraps https://www.npmjs.com/package/level-filesystem, which only implements the async methods in fs, so hyperlog/lib/messages.js doesn't work:

module.exports = protobuf(fs.readFileSync(path.join(__dirname, '..', 'schema.proto'), 'utf-8'))

Inlining it (which is what brfs would be doing if we were using browserify; there's probably a similar way to do this with Webpack (https://github.com/webpack-contrib/transform-loader)) potentially eliminates any uses of fs and allows us to keep going...

module.exports = protobuf('message Node {\n  required uint32 change   = 1;\n  required string key      = 2;\n  required string log      = 3;\n  optional uint32 seq      = 4;\n  optional bytes identity  = 7;\n  optional bytes signature = 8;\n  required bytes value     = 5;\n  repeated string links    = 6;\n}\n\nmessage Entry {\n  required uint32 change = 1;\n  required string node   = 2;\n  repeated string links  = 3;\n  optional string log = 4;\n  optional uint32 seq = 5;\n}\n\nmessage Log {\n  required string log = 1;\n  required uint32 seq = 2;\n}\n\nmessage Handshake {\n  required uint32 version = 1;\n  optional string mode    = 2 [default = "sync"];\n  optional bytes metadata = 3;\n  optional bool live      = 4;\n}');

And now, after mojodna/surveyor-prototype@a88d632, we have a non-build-related error:

secure random number generation not supported by this browser
use chrome, FireFox, or Internet Explorer 11
mojodna commented 7 years ago

There's a react-native variant of randombytes (responsible for that error), but installing it is a little tricky: https://www.npmjs.com/package/react-native-randombytes

Sidenote: why am I spending so much time on this? @gmaclennan and I are (I think) convinced that React Native is a better path than Cordova, etc, and this represents a pretty fundamental challenge that we need to overcome in order to be successful (and is likely to be a similar problem within the Cordova world).

mojodna commented 7 years ago

GitHub link to that: https://github.com/mvayngrib/react-native-randombytes

mojodna commented 7 years ago

This simplifies the installation process:

yard add react-native-randombytes
react-native-link react-native-randombytes

but I still end up with:

Object is not a function (evaluating 'randomBytes(8)')

(which I thought was a result of react-native-randombytes needing to be transpiled, but apparently not.)

mojodna commented 7 years ago

From deep in the weeds: osm-p2p / leveldb is probably going to need native filesystem access to have decent performance, so we'll likely need to see whether / how to expose native FS functions (or native leveldb).