I like to write down my notes while setup a Cordova based application with Webpack, AnuglarJS and Onsen UI using Babel for ES2015 support. It’s not my first Cordova project but I like to write down all the things I touched and thoughts I had so maybe next time I don’t have to dig it out all over again.

Clients stack

Basically I’d like to combine the following tools with the following motivation:

Tool Motivation
Cordova I like to use JavaScript and it’s tools. For me it’s the best compromise in many ways (performance, code quality, community, tools, libraries, fun).
Webpack + Babel Would be nice to write ES2015 style classes, use friends like [...someArray] and modules but still run it on older JS engines.
Onsen UI Brilliant UI with many options and excellent performance.
AngularJS As a simple enough binding engine to organize the UI and screen flow.

Setting up Cordova and Webpack

As a very first step I create a new Cordova app and integrate Webpack with babel. This allows me to write modern JavaScript which is a must for me.

# Create the app using Cordovas cli
cordova create mcabc de.cschnack.mcabc mcabc
cordova platform add android

Once that’s done I add cordova-plugin-webpack. It enables support for Webpack in Cordova apps and improves the overall workflow with features like: hot module reloading.

Following the instruction of the plugin page:

cordova plugin add cordova-plugin-webpack

Update Cordova App to work with cordova-plugin-webpack
Update Cordova App to work with cordova-plugin-webpack

  • (a) + (b) create webpack.config.js
  • (c) create src folder and move index.js into it
  • (d) let the the app point to the build result

To build and test it I just write

cordova build
cordova run -- --livereload

Configure Babel for Webpack

To have support for ES2015 language features I need to configure Babel:

Add Babel to Webpack
Add Babel to Webpack

  • (a) add Babel core, loader and preset in the package.js
  • (b) update Webpack configuration

The preset-env does not yet support the spread-syntax for objects. To have that I also added @babel/plugin-proposal-object-rest-spread.

Once I called npm install the additional dependencies are downloaded. Now the code under src/* can contain new language features. Thanks to Babel they are transpiled to classic JavaScript:

Babel in action
Babel in action

Love it!

Bootstrap AngularJS in Cordova/Webpack environment

Running AngularJS in a Webpack ES2015 transpiled context is something that can lead to confusion. AngularJS provides a dependency framework which kind of solves the same thing as modules do. I found some more plugins for Webpack to specifically take care of modules and AngularJS dependencies. However, as I’m not sure how those plugins work within the cordova-webpack-plugin environment and as they seem to favor AngularJS components - which I don’t - I’d like to work around that.

Bootstrap AngularJS
Bootstrap AngularJS

  • (a) In index.html I provide a ID to the HTML element. This is going to be our app element. As I need to wait for Cordova to initialize before I initialize AngularJS I do not set an ng-app here. I do that later in code
  • (b) For first testing I added a binding for testString as part of the ng-Controller="TestController"
  • (c) I have to update index.js and added module.js the TestController.js.

Bootstrap AngularJS
Bootstrap AngularJS

  • (d) In index.js I make sure that first Cordova signals deviceready before AngularJS starts to work on DOM. Importing the TestController here registers the controller globally.
  • (e) With module.js I make sure that no matter how often I import the module I only create one instance. Here the module configuration should go.
  • (f) An example controller for the <div ng-controller="TestController"> of (b). Thanks to Webpack I can use ES2015 modules and import the configured module and create our AngularJS style controllers.

So, technically it works like this. However, AngularJS offers it’s own module system and a dependency injection mechanic. This feels of on top of the ES2015 modules but for now I just accept it as the price I have to pay to use the oldish AngularJS.

Integrate Onsen UI

Having AngularJS, Webpack, Babel and Cordova running I already have an environment to work with. With Onsen UI I add a pure HTML UI which simulates a good enough native look & feel.

Onsen UI comes with a core library and CSS. To make it run with AngularJS I have to load a driver called angularjs-onsen. To make it work in a webpacked environment I have to import it in a certain order.

Inject Onsen UI
Inject Onsen UI

  • (a) I have to make sure the Onsen UI is loaded from the package into our index.bundle.js. For that I simply import it in module.js.
  • (b) This is part of a hackish solution to let the angularjs-onsen-ui driver being able to find Onsen UI. Naturally having a dependency to a global variable is a big no no in module based environment. However, for the given context it’s okay.
  • (c) I update the module creation by adding Onsen UI.
  • (d) Here I import the AngularJS driver. Putting this into index.js makes sure that (b) is executed the driver is imported. This is part 2 of the hackish solution to get it run.
  • (e) Load the Onsen UI CSS files. I do that by a simple import (notice the " instead of '). To make CSS imports work I have to…
  • (f) …add rules into webpack.config.js. I make sure that Webpack is able to recognize CSS files and copies font-dependency into www/import_fonts. To use this rules and also Onsen UI, I also have to…
  • (g) …update the package.json and added: onsenui, angularjs-onsenui, style-loader, css-loader and file-loader.
  • (i)/(k) With all that I now can use the Onsen UI elements in our HTML files. I put the Onsen html files into www/views/* so they are just normal Cordova resources. The controllers I put into src folder so they are transpiled and packed.

Having all this I now have a nice enough environment to implement content into the app.

Run it and access console.log

Running the app using cordova run -- --livereload the emulator starts automatically. The image at the bottom nicely shows livereload means. One can make a change in the source and thanks to all the stuff I did before it automatically refreshes content within the running app. Onsen UI and AngularJS work as they should.

This works with the emulator and with a device. On Android it is possible to access the log-output and inspect the entire application using Chrome. For that one simply has to simply do this:

Debug on remote device or emulator
Debug on remote device or emulator

From there it’s easy to connect to the running emulator or device.

Final result

If put all things together I have a nice list of feature:

  • Modern ES2015-language features can be used
  • Resulting app code is compatible with older devices
  • Cordova and Onsen UI together offer a good user experience with a lot of flexibility
  • Dependency management for libraries is under control of npm and package.json
  • Livereload allows quick prototyping
  • Babel checks for syntax errors

Working develop environment
Working develop environment