Thursday, July 30, 2015

Live-reload for Polymer Chrome Apps

While working on a new Chrome App using Polymer (details of which shall remain secret for now) I've encountered the following annoying repetitive steps:
  1. Change some code
  2. Run the code through crisper because the Content Security Policy for Chrome Apps doesn't allow inline scripts
  3. Reload the Chrome App from chrome://extensions/
  4. Repeat
The Polymer Start Kit offers a nice for solution this using Browsersync, which automatically updates all connected browser instances when the source code changes, but that only works for "normal" web apps meant to be hosted on a server which isn't the case for Chrome Apps.

After a bit of googling I found this nice article by Konstantin Raev that deals with the problem of live-reload for (non-Polymer) Chrome Apps and offers a straight-forward, working solution,
using tiny-lr and his own adapation of livereload.js (to work around some Chrome Apps security restrictions).

Using this gulp task will update or reload the Chrome App when any of the source files change, and you can just load your source folder as unpacked extensions, launch your app and start developing/testing:

While this works great for "normal" Chrome Apps the issue with Polymer Chrome Apps is that they at least need one extra crisper step to get all the JavaScript out of the .html as separate .js files.

My first lazy approach was to listen for any changes in the source folders, then run a full build and use the dist folder as unpacked extension.

A full build as per the Polymer Starter Kit involves quite a few steps, like minimizing the css/js/html, optimizing the images and vulcanizing the elements:

The only extra step you have to add in addition to what the Polymer Starter Kit does, is crisper after the vulcanize:

In the dev task (to be started with gulp dev) I first run a build, and then repeat the build step whenever something changes in the app folder. The build creates files in the dist folder (which is loaded as unpacked app), and livereload is triggered by listening to changes in this folder.

Of course this approach has several issues. Not only can the build sometimes take quite a while for even small changes, but you also get a minimized, vulcanized app, which can be terrible for debugging.

So instead I added a simplified dev-build that basically only copies all the files to a `dev` folder (to be loaded as unpacked app)...

and runs crisper on all .html files to get the .js parts out of the elements and their dependencies.

While working on that part I encountered an issue where gulp-crisper would ignore all folder structure and e.g. put all files directly into dev/bower_components/ instead of dev/bower_components/polymer/.  This issue is now fixed so make sure to use the newest version 0.0.5 of gulp-crisper.

When watching for changes I also don't update everything, every time something changes but listen for specific changes and only update the necessary parts.

And to prevent live reload to trigger for each single file change (and the build process creates several file changes for each source change) I'm using gulp-batch, collecting all changes in a batch before sending the info to tiny-lr.

Here's a quick video of how this process looks like now.

So with all of this done I can now proceed to work on my Polymer Chrome App after having learnt far more about gulp than I originally intended ☺