Livereload with Cordova and Gulp

I recently started on an Ionic/Cordova app that uses Gulp as the main build system. While I’ve used Grunt several times in the past I have found Gulp to be much more of an intuitive approach and definitely easier to work with.

In a Cordova project, you develop the application in the $ROOT_DIR/www/ directory. When you build the project for ios, Cordova copies those files from that directory to $ROOT_DIR/platforms/ios/www directory. In order to streamline the development process, I wanted to make use of
livereload via the gulp-livereload and cordova-gapreload plugins. The basic setup is to use Gulp to watch for changes in the www/ directory and when a change is detected, copy the file to the appropriate location in the platforms/ios/www directory before triggering livereload. The main reason for copying files is that the gapreload plugin looks for assets served relative to the platforms/ directory.

As you’d expect with any project, asset files can be numerous and the build system itself should not impose a restriction on nested folders. These requirements make manually listing files and structures an onerous task that should be avoided. Fortunately, file globbing) exists precisely to simplify this task. When specifying files to watch, you can use a glob pattern to match multiple files in many directories with a single expression. For example, to watch all files in the www/ directory, you could specify a route glob as such: www/**

Important: Pretty much every JS library I’ve found that does any sort of route matching with globs uses the minimatch library. Currently this library has what I consider to be unintuitive, undocumented, and even incorrect behavior. The library does not do path normalization before matching which leads to the library not recognizing the equality of paths prefixed with the relative “./“ compared to those that are not. Thus a glob specified as ./www/**/*.js would NOT match the path www/app/test.js . In the Gulp ecosystem at least, it seems that path names are piped between processes without the “./“ so I would recommend that any relative paths or globs you manually specify not have the “./“ prefix.

Once you have Gulp setup to properly watch your asset files and copy them to the appropriate directory, the next step is to configure a basic http server to serve those assets, then trigger a livereload. I fulfilled the first requirement using the simple ecstatic module configured to serve all files from the platforms/ios/www/ directory on port 8000. Make sure your assets are served with a very short cache time . This can be done with ecstatic by specifying cache: 0 in the config object. Once Gulp copies a changed file to the appropriate directory, pipe the new file to livereload to trigger the change.

The final step is to install the the Cordova plugin. From your root directory type: cordova plugin add pro.fing.cordova.gapreload --variable SERVER\_HOST="<host>" where is the is the computer the files are hosted from. If you’re developing with the emulator, this would probably be localhost however you can also specify any IP you want meaning you can use this setup when developing with an actual device

Conclusion That’s pretty much it! Now when you save a file, Gulp should

automatically detect the file has changed, copy it to the platforms directory, then trigger a livereload action. You app running in the emulator should instantly receive the livereload notification, load the changed file from the server, then refresh the webview so the changes take effect.

Caveats This setup has been working pretty well for me however there are

some caveats that are important to mention. First of all, when using the gapreload plugin XMLHttpRequests will be subject to cross origin restrictions meaning you won’t be able to make normal requests to servers that don’t have CORS enabled, even if you whitelist the domain in your config.xml.

Below are the relevant portions of my Gulpfile.js:

Homebrew and Python - A tale of Installing Powerline

Introduction

The other day I was attempting to install powerline to make my Vim setup look prettier when I ran into some trouble with how my system was configured. For those who don’t know, powerline is a neat status bar written in Python that provides various visual cues like what mode you are currently in. The instructions for Mac told me install the package via pip, a Python package management system. This sounded easy enough however I quickly ran into some nuanced issues that had to be resolved.

Default Python on Mac

By default, OSX comes preinstalled with several versions of Python. Theses version are used as dependencies for various software and, in general, should not really be messed with. The executables are made available via the /usr/bin directory and should link back to /System/Library/Frameworks/Python.framework/Versions/2.7/bin/ . This is all well and good, however, there are a few problems: firstly, the version of Python in this directory is not necessarily up to day. For me, /usr/bin/python —version yields version 2.7.5 while the most recent version is 2.7.6. More importantly, installing Python packages via the included version of pip require root access (sudo pip install ) because packages are saved to /Library/Python/2.7/site-packages. Automatically running install scripts that are downloaded form the internet with root privileges is generally considered a possibly security risk and is something I strive to avoid at all cost.

Enter Homebrew

To rectify both these issues, I used the wonderful Homebrew (brew) package management system. By design, brew promises to never write files outside the directory specified by brew —prefix which defaults to /usr/local/. Package information is saved to /usr/local/Cellar and executables are linked to /usr/local/bin . The beauty of this is that these directories don’t require root privileges to write to meaning if you ever need to sudo brew anything, you’re probably doing something wrong.

To install an updated version of python, simple enter brew install python. Because brew will detect you already have a version of python installed on your system, it may be necessary to run brew link python, which will symlink the appropriate executables to /usr/local/bin . Now, assuming you have /usr/local/bin in your $PATH (which you should), invoking which python should show you that you are now running the brewed version of python and python --version should now yield 2.7.6.

Rejoice! You should now have an updated version of python installed and managed by brew. which pip should also show you are running the version that accompanied the brewed python.

Installing powerline

As mentioned earlier, powerline can be installed using pip. The exact command given by the documentation is pip install --user git+git://github.com/Lokaltog/powerline.

Unfortunately, this presents an issue for brewed python. According to the brew-python documentation at https://github.com/Homebrew/homebrew/wiki/Homebrew-and-Python. The normal pip install --user is disabled for brewed Python. This is because of a bug in distutils, because Homebrew writes a distutils.cfg which sets the package prefix. Fortunately, the fix is quite simple. If you’ve installed python via brew, you can safely remove the —user flag, which instructs pip to install the package into the ~/Library/Python/<x>.<y>/lib/python/site-packages/ directory. Instead, pip will install the package into /usr/local/lib/python2.7/site-packages, which shouldn’t require root privileges.

Configuring Vim

The final step is to configure Vim (or whatever else you’d like to user powerline for). If, like me, you use vim or macvim installed through brew, you may have to do one last step. In order for powerline to work, Vim needs to be compiled with python support. Brew does this automatically at install time howeve, it relies on the first version of python found in the user’s $PATH when the program is installed. If you did not have brew installed python at the time you installed vim or macvim, you will need to reinstall these versions using something like brew reinstall macvim . Vim will now be linked against the correct version of python and have access to the installed modules.

You should now be able to add the following lines to your vimrc file and bask in the glory of a nifty status bar

1
2
3
python from powerline.vim import setup as powerline_setup
python powerline_setup()
python del powerline_setup

Those are some of the things I learned while wrestling with brew and python for several hours. I have been using brew for a year or so prior to this without necessarily understanding some of the finer points of the system and no doubt had a lot of cruft on my machine as a result. Hopefully something in this post can save someone out there some time and/or headaches.