Making of Peerflix for iOS, or how to embed any nodejs app in iOS app.

This is about building Peerflix for iOS.

What is Peerflix?

In case you don't know, peerflix is a JavaScript app that stream video torrents without fully downloading them. It's like Netflix, but P2P, bought to you by @mafintosh.

It's awesome! But what if I just want to play video my iPad? What if I can run peerflix on iOS?

Cool, can I get it on App Store?

Nope.

Then why bother?

It's fun! Also, it'd be a great example to demonstrate how to run non-trivial JavaScript app on iOS. (and Android, Windows, Mac ...etc)

How It Works

The core of the app is torrent streaming. It's certainly possible to do it natively, but it would be too much for our weekend project.

Instead of reinventing the wheel, how about embed a JavaScript app that use peerflix to do the heavy lifting?

JXcore make it possible. From JXcore's site:

100% Node.JS Compatible - JXcore is a Node.JS fork with additional features.

Is that even possible🤔 ? After a day of tinkering, I finally figure out how to make JXcore work on iOS.

Architecture

This is the architecture of the app:

JXcore is a JavaScript engine embedded in your app. Technically native code can call javascript code and vice versa. To make the app design simpler, I expose a RESTful interface from JS side.

Instead of figure out callbacks and threading between two worlds, the iOS app now work like regular app where it sends query to remote server. The JavaScript app also work like a regular node.js app. Actually with JXcore I can compile it to work on desktop or Android or OpenWRT, what you need is just a frontend.

Some Issues

While most of the node code just worked. There are a few platform specific issues. For example peerflix writes to /tmp and we need override it with iOS sandboxed NSTemporaryDirectory(). network-address return my phone cellar network IP instead of my Wifi IP.

Don't try to use npm package with native extension. JXcore do support native extension on OSX/Windows. But it seems they have not yet provide cross compile toolkit that let you compile native code to target platform (iOS device and simulator). You can still use package that use only built in module, but anything else will just fail on device.

Another problem is ES6 support is not ready. JXcore for iOS is based on Mozilla SpiderMonkey. At this time it don't even support class. Attempt to make webpack or browserify to work on it failed, they just don't seems to know how to bundle a file that JXcore happy to accept (I've got a lot of native dependency).

Last but not least, the JXcore engine take some time to load. In fact it take about 10s to finished loading the engine. It's loading asynchronously so it will not block the app, but the JS part is down so pretty much everything is not working. This is certainly due to very large amount of dependency of the app. The node_modules library is now 40M. It don't load them all, but I'm certainly feel that I could do some optimization here.

What Next?

I might write a bit more about how to actually start a project with JXcore for iOS. And my experiment on using RxSwift. Maybe next week 😈

If you're interested in the app, get it on Github. You will need Xcode, know how to build an iOS app, and determination (it have some big dependency like ffmpeg which can take a loooooooong time to download and build)

Please leave me messages if find this interesting!