MainframeOS / erebos

JavaScript client and CLI for Swarm
https://erebos.js.org
MIT License
47 stars 12 forks source link

Support React Native #52

Closed PaulLeCam closed 5 years ago

PaulLeCam commented 6 years ago

At the moment the browser and Node.js versions of the Bzz APIs and therefore clients are not compatible with React Native. The main issue is that these modules use browser-specific APIs such as Blob and FormData, or Node.js-specific ones such as streams and filesystem APIs. react-native-fs and rn-fetch-blob might provide good alternatives to implement the necessary APIs for React Native.

agazso commented 5 years ago

I'm trying to use erebos from React Native. There is Blob and FormData in React Native so that's not the issue (see for example https://github.com/facebook/react-native/blob/master/Libraries/Network/FormData.js). When you want to upload a file, you can append an {uri, type, name} object to FormData where uri is the local file path, the type is the MIME-Type and name is the filename, and then upload it with multipart/form-data content-type header. That way the React Native native runtime knows where to find the file it can upload directly, so you avoid reading the file from Javascript, encode it to pass through the native bridge, decode it on the native side and then upload it. For an example see: https://github.com/agazso/postmodern/blob/d169c67c4083d74bc0f563c324c4d858f7360201/src/Swarm.ts#L79

agazso commented 5 years ago

There is another issue that is blocking me to use erebos from React Native. When I am trying to create a new SwarmClient, I get the following error: Error: Creating URL objects is not supported yet. This is because an Url class is used internally in React Native that is not the same Url class that is in the browser. Here is the issue: https://github.com/facebook/react-native/issues/16434

What is your idea handling the React Native specific modifications to the code? Are you planning to create a different subpackage like you have for the browser and node and put the differences there?

PaulLeCam commented 5 years ago

Hey @agazso thanks for digging into this!

If there are significant differences between the RN and browser or node version then I think it makes sense to add an api-bzz-react-native package to handle them. The URL constructor could potentially be replaced by the whatwg-url module and the DirectoryData type support the uri field for contents to be better integrated with RN, what do you think?

agazso commented 5 years ago

Sounds good to me! Let me know if I can help with something.

PaulLeCam commented 5 years ago

My main concern with adding support for React-Native is that we're not using it in any project at Mainframe at the moment, so considering the possible breaking changes between RN releases on one side, and Swarm on the other side, we would need a reliable test framework in order to actually support it.

I hope in the next 3 to 6 months we'll have RN projects that need to use Erebos, but as our team is busy with other priorities I don't think we can work on this integration ourselves in the short to medium term. Is it something you would be willing to help with please? I can help with the package maintenance, but the initial setup and tests in CI would be too time-consuming for me to take care of at the moment.

vmaark commented 5 years ago

I managed to make upload work on a PoC level, but I had some issues setting up erebos as a local development project next to our project, I'm opening a separate issue for that. Always importing locally whatwg-url seems to be the react-native community's answer to this issue at the time being. Another issue is the lack of Buffer in react-native, there are two possible solutions for this: depending on the buffer package and using that, but that can also be solved on the client side, because react-native is not occupying that, like it does with URL.

vmaark commented 5 years ago

There were some build errors using whatwg-url, so I ended up using universal-url which uses whatwg-url under the hood. I can open a PR with the changes, or would you prefer putting it in a separate -react-native package? There are no other issues that I've found using api-bzz-browser in react-native.

Regarding testing: react-native uses JavaScriptCore on both targets (different versions though). It would be really cool if there's a way of having a test runner which uses it, but I had no luck finding one. The more heavy-weight option is using detox.

PaulLeCam commented 5 years ago

@vujevits have you been able to use feeds please? I think this is the main issue with supporting React Native, signing feeds uses the elliptic library which seems to have issues with React Native (such as https://github.com/indutny/elliptic/issues/159) so additional work might be needed to support it.

I think adding a api-bzz-react-native package would be the most convenient so additional features and fixes could be added there, rather than in api-bzz-base, but if the only change required at the moment is using universal-url, that would be simpler to add to api-bzz-base directly.

About the tests detox looks like a good option, I've never used it though so I don't know about the constraints and limitations.

vmaark commented 5 years ago

@PaulLeCam I managed to integrate locally an @erebos/api-bzz-react-native to https://github.com/felfele/felfele, and feeds are working fine! There were no changes needed because of elliptic. I'll have a look at how tests are run in erebos, and see how detox can fit in the picture.

Update: there seems to be an issue which comes up when uploading images, it is probably related to Blob

sshelton76 commented 5 years ago

I'd vote against putting effort into trying to support react-native. I've seen many projects trying to support it and needing to do a whole lot of refactoring to try and get things to work only to break a ton of of things in the process. Support for something like react is something you need to design for from the beginning and once you do that, then you are married to react's treadmill. What happens when react ceases to be the framework dujor?

It's best to keep things vanilla. If it's vanilla, then framework users can easily port to the dujor framework of their choice and maintain it or not as they so desire. To my mind, even having the project directly emit react observables was too much, because at that point I'm stuck with either importing the nasty mess that is the react dependency chain into my project (intended for resource constrained environments), or forking and rewriting that section of code so it does what it needs to without bringing in react as a dependency.

vmaark commented 5 years ago

@sshelton76 maybe the issue / pr name is a bit misleading, it does not have much to do with React or even react-native, but the js environment which runs react-native (of course the point is that it works with react-native, hence the naming). As you can see in the PR, the differences are even smaller then between the browser and the node version.

PaulLeCam commented 5 years ago

Added in https://github.com/MainframeHQ/erebos/pull/98