CommonJS Libs in Ambly

June 17, 2015

ClojureScript is being updated to support foreign libs packaged using the CommonJS module system. A good explanation is Maria Neise's blog. From the big picture, this helps with using ClojureScript to work with React Native, which uses CommonJS.

For Ambly, the salient aspect of the ClojureScript compiler strategy is that, when invoking cljs.build.api/build, the CommonJS foreign libs are converted to “native” Google Closure libs, putting them in :output-dir where they can subsequently be loaded into the JavaScript environment.




But, since Ambly involves a remote compilation architecture, :output-dir isn't established until the remote device is discovered and the WebDAV volume is mounted. Additionally, the device may have an onboard :output-dir that is pre-populated to support app bootstrap. These essentially preclude doing a build step prior to setting up the Ambly REPL.

Instead, Ambly relies on dynamic (remote) compilation whenever a namespace is required. Additionally, :analyze-path can be used to cause the REPL to reflect the symbols that are actually loaded on the particular device being connected to. And :watch can be used to cause files to be complied to the device when saved.

Given the above considerations, an experimental approach is currently being employed to cause Ambly to work with the new CommonJS support: Ambly can invoke the same logic that would be invoked during a build, but inside the REPL setup code after :output-dir is established. (The :foreign-libs compiler option is passed to the REPL.)

This involves calling process-js-modules, followed by updating the :js-dependency-index and conveying the resulting revision to the compiler options (in particular, the :libs compiler option entries that are set up to replace the :commonjs subset of :foreign-libs by Maria's code) to the ClojureScript REPL and compilation environment via the :merge-opts feature of -setup:

(let [...
      opts (process-js-modules 
            (assoc opts :output-dir 
             webdav-mount-point))
      _ (swap! *compiler* 
          assoc :js-dependency-index 
          (js-dependency-index opts))
      ...]
      ...
      {:merge-opts opts})

This is a bit technical but is fortunately all fairly straightforward. It works! Here is a demo.

 




 

While this approach is experimental, it provides a path to using CommonJS modules with Ambly and eliminates one more hurdle torwards being able to use Ambly for React Native development!

Tags: Ambly React Native ClojureScript