Using browser-sync with Cordova

BrowserSync Capabilities (live reload, click/scroll mirroring) in Cordova Apps - Link
As a web developer, I have always loved the quick edit-preview cycle when working on web pages.Tools like BrowserSync enable features like live reloading when HTML/CSS/JS change and even synchronize scrolls, clicks and form inputs across multiple devices.
Since Apache Cordova is based on similar web technologies, the goodness of web development can also be transferred over to Cordova projects. There are a couple of plugins like gap-reload, and they seem to integrate pretty well with live reload. This blog is about my experiment to build something that leverage the capabilities of Browsersync.


Here is a quick 2 minute demo showing the usage and capabilities of using browser-sync with Cordova. The video shows features like automatically reloading the app when files are edited, mirroring clicks, scrolls and form filling, and even the ability to use native, platform specific plugins.

Integrating into your projects

The video above shows how this can simply be added as a Cordova plugin. The project's repository also describes how to use this as project hook, instead of having to install it as a plugin. The repo was also structured to be used in any existing workflow and to that effect, the individual modules can also be "required" and used in grunt or gulp.

How does it work? 

BrowserSync watches for file changes and then reloads the web page, or injects the HTML or CSS into the page. Cordova is similar since is displays content using Webviews. The steps for this plugin are
  1. Module lib/changeHosts changes platform specific config.xml to serve content from a web server (like http://localhost:3000/platforms/android/assets/www/index.html) instead of the default local index.html 
  2. The lib/browserSyncServer starts up browser-sync, watching for changes in your project's www folder, and serving the entire project folder using its static web server.
  3. When anything in your project's www folder changes, cordova prepare is run to copy over the changes to platform specific folders. Other hooks are also run to ensure that any transformations you have in your workflow (like compiling less/sass files) continue to work.
  4. BrowserSync mirrors scrolls and clicks using the current page's path as the key. This is a little tricky for Cordova since the webview content is loaded from platform specific locations (like platforms/android/assets/www/index.html and platforms/ios/www/index.html). To normalize this the hack that I had to put it was to monkeyPatch the canSync function that checks if events are from the same page; the change was to ignore platform specific folders. 


The fact that the webview content is served from a http:// server rather than the local file system makes it a little different from the actual Cordova app. Things like cross origin ajax requests, local storage and cookies, cdv:// files, etc work differently. This is not a major issue since most things like visual layouts and plugins work fine and account for most of the development time. Once the app is ready, the plugin/hook can be removed to test it one final time with the actual app.


 Next Steps

To deal with the above caveat, I am looking at ways to use the HTML injector and continue serving the contents from regular cordova webview's origin. Watch out this space for my experiments with Cordova