Ambly App Bootstrapping

March 5, 2015

A couple of weeks ago Ambly gained the ability to work with ClojureScript apps that bootstrap themselves.

Previously, the focus had been on bootstrapping a ClojureScript REPL into an empty JavaScriptCore environment. This involved compiling cljs.core, transmitting the JavaScript to the iOS device using WebDAV, etc. This is the pattern followed with the demo iOS app included in the Ambly source tree.

The Ambly Demo app is nice in that it lets you quickly fire up the REPL and try things out. But, most hybrid ClojureScript / native iOS apps won’t be this simple. In particular, non-trivial apps will need application-specific JavaScript on the device and available during the app initialization sequence.

A simple app illustrating this need is Shrimp, where the first screen shown upon launch is a list of items taken from its database. In Shrimp’s case, the code used to populate the list is derived from ClojureScript.

We also expect that ClojureScript-based React Native apps will have the same characteristic: Needing the JavaScript runtime fully up and running in order to launch the app.

Also, when developing an app, you should be able to launch it without requiring a REPL to first connect to it as a launch dependency.

The approach being taken with Ambly involves having the developer first invoke lein cljsbuild once to compile a copy of the app’s JavaScript (and other associated compiler output metadata) into a local "out" directory. The Xcode project refers to this "out" directory in order to include it in the app bundle. Then the challenge becomes: When the iOS app launches, the ClojureScript environment needs to be bootstrapped within the app without the REPL.

Ambly's solution effectively duplicates the bootstrapping logic which was previously in the Clojure REPL implementation in Objective C in order to handle this case. This way, during the app initialization sequence, things can be properly set up and the app can begin running.

As part of the bootstrapping process, the bundled JavaScript and other compiler output files are copied into the on-device WebDAV target directory. Then later, when the user connects with the REPL, Ambly detects that bootstrapping has already been done, and it skips that bit and simply establishes the other aspects that are needed for proper REPL operation (so that WebDAV can be used for remote compilation, etc.)

This approach has a side benefit in that it allows the developer to disconnect the REPL and reconnect it again later, with subsequent reconnects avoiding unnecessary bootstrapping.

The Shrimp app has been updated to use Ambly in this mode. I've also updated my production App Store app, which is based on Goby, to use Ambly in the same way.

This gets Ambly in good shape to help support targeting ClojureScript to React Native.

Tags: Ambly