There are many powerful tools and technologies surrounding the Web, and we can reuse them to develop cross platform mobile and desktop apps, especially in light of installable apps appearing on platforms such as Firefox OS. This article looks at the best way to do this, and presents Webapplate, a powerful new template to help facilitate this.
Why invent the wheel (for the new frontier)
As is the nature of the whole web, web apps are simple to write but hard to get done right. Even though the Web doesn’t provide an SDK or simple ready-to-use templates like other mobile platforms, you can still come out with a workable web app from candidates like Mozilla Open Web Apps, Chrome Apps, or Apache Cordova. But developers who want to quickly build a web app usually take longer time than say, an iOS developer.
Here is the state of web app support by those candidates:
- Firefox (desktop), Firefox OS, Firefox for Android support hosted web apps. Those web apps could be hosted on a static or dynamic web server just like normal web sites. Hosted web apps don’t allow some certified web APIs such as the TCP socket API because of security concerns.
- Firefox OS and Chrome (desktop) support packaged web apps with different APIs for different purposes, because currently they focus on different types of devices.
- Cordova provides device adapters for many platforms, including Android, iOS and Firefox OS.
- Google has its Cordova variant to adapt Chrome App’s specific APIs to run on Android devices.
In quick summary, the web app concept is not totally unified yet, but powerful enough to compete with native apps. Currently packaged web apps are mainstream because of the security concerns with new web API’s. Mozilla is mainly focusing on exposing new web APIs to mobile devices, Google is developing new web APIs for desktop. Apache Cordova is a good container to expose web APIs to different platforms.
To make things harder, provided examples are often focused on teaching you how to pick up new web APIs rather than utilizing proper web app concepts with your development process.
I’ve had the chance to join the development of an evolving web app project called Gaia, the Firefox OS user interface. The Gaia project contains the very first Mozilla installable web app implementation, including apps for music, photo gallery, e-mail, calendar and much more. According to GitHub’s pulse monthly, there are about 850 commits per month to the Gaia web apps. In the Gaia project, Mozilla developers and community members devoted lots of time and effort to bring it from the prototype stage to a shippable product within 2 years, and iteratively make it a competitive option for smartphone consumers. As a living large web app project, there are many lessons that can be learned from it, and applied to general web app development.
Like other software projects, there are many things beside commiting code to develop a web app, such as:
- How to organize the source code
- How to handle library dependencies
- How to keep the coding style in convention
- How to optimize web app load performance
- How to unit/integrate test your web app
- How to localize your web app
- How to automate those processes
Those are topics that need to be resolved to develop a quality web app. In Gaia we have addressed these issues by utilizing a bunch of build scripts (Makefiles).
You may wonder why we didn’t use Grunt or gulp for building? The answer: at the time Firefox OS was started, these tools didn’t exist. And the module owner wanted to make the core build process run in a Firefox extension one day.
For general web app development, we didn’t have to follow those constraints. And we could do some experiments rapidly by reusing 3rd-party tools and libraries. From 2013, I’ve initiated a side project called webapplate, the open-sourced web app template that attempts to make Gaia’s solutions compatible with emerging toolkits like npm, Grunt and Bower. It also tries to transport good practices from Gaia to make new web apps more maintainable.
How to setup webapplate
You need to install node.js in your desktop first. With Node.js installed, you’ll have the
npm tool to manage Node.js modules. Now run this command:
$ npm install -g grunt-cli bower karma
to install the primary tools.
Bower is a management tool for the front-end libraries. It helps developer manage different library versions. In webapplate, Bower will download client side libraries into the
public/vendor folder when you run
$ bower install
Karma is the test runner that runs test code for each of the browsers. karma.conf.js defines the detail settings to specify how the test runner goes.
Next, enter the webapplate folder and run:
$ npm install
npm will reference package.json to install all dependent node modules. The command will trigger
Bower to install client-side library dependencies as well.
Then you are all set! What you get is:
- Pre-commit lint checking
- Firefox and Chrome web app-compatible templates
- Library dependency management
- Client-side localization framework
- Unit test and mock framework
- Deployable web server
If you use Firefox nightly, you could open the
webapplate/public folder as a packaged app in the WebIDE developer tool.
WebIDE allows you to edit, debug or execute your web app in the Simulator or on the device, with your favorite Firefox Developer Tools.
With the Chrome Apps & Extensions developer tool, you can import the
webapplate/public folder as a Chrome App and check the UI on desktop.
Pre-commit lint checking
The very first good practice that Gaia and webapplate provide is git pre-commit lint checking.
It has exactly the same settings as Gaia for JSHint and also comes with the whitelist. Gaia is also planning to migrate to jscs to replace gjslint. If you use
git for version control, run:
$ grunt githooks
to bind the git pre-commit code style check to your development process.
Firefox OS- and Chrome App- compatible templates
Webapplate uses HTML5 mobile boilerplate as the template base, and adds web app install helpers, icon links and usemin annotation for web app optimization on top. The main web app source is located in the public/ folder. You could check the webapplate wiki to see the full webapplate structure.
Currently, Firefox web apps use manifest.webapp and Chrome Apps use manifest.json as the manifest file. The syntaxes are mutually compatible, except the localization part (we’ll address this issue later).
After you edit one of these files, use:
# firefox to chrome $ grunt f2c
# chrome to firefox $ grunt c2f
manifest.json, or viceversa.
To generate a Firefox OS packaged app or Chrome App, run this command:
$ grunt pack
to package your web app to an uploadable zip file. With the default settings, webapplate-generated packaged web apps could be uploaded to the Firefox Marketplace and the Chrome App store.
Library dependency management
For Gaia we manage development tools via
npm and generally don’t use many 3rd-party client side libraries. We host commonly-used libraries between apps in a
shared/ folder, and then copy them in at build time via a build script.
webapplate defines these libraries in package.json, uses
npm to require build tools, and doesn’t assume any app framework (e.g. Backbone or Angular.js, or a UI framework such as Bootstrap.) Client-side libraries could be managed via Bower in bower.json.
Client side localization framework
Since web apps might be run without an Internet connection, we can’t count on the server to detect multiple languages. Currently Firefox OS uses navigator.mozL10n and Chrome Apps uses chrome.i18n for localization. Both of them are non-standard.
In webapplate we take the l20n library to address the client-side localization issue. l20n is crafted by Mozilla and the developers are currently working on enhancing the Firefox OS localization framework as well.
Check out index.html; the localization syntax looks exactly like what we used in Gaia:
The locale file however is in a different format, locales.en.l20n:
Also, check out the Multiple Language Support Framework section for how l20n is integrated with webapplate.
Unit test and mock framework
Gaia uses its own test-agent to trigger unit tests on Firefox. Gaia uses the Mocha test framework, Chai assertion library and the Sinon test helper library for unit tests.
Webapplate uses the above unit test libraries plus the Karma test runner to run unit tests on all mainstream browsers.
Deployable web server
Running the command:
$ grunt server
will trigger the Express-powered server with django-like Swig template support. It’s been pre-configured for performance. Measure with YSlow and you’ll get a pretty good grade for your web site.
Webapplate has been tested on some free dynamic web page hosting providers such as openshift, heroku and appfog. Check the deployment section to find out more details.
If you like to host your web apps on a static web server, run:
$ grunt static
to generate optimized web pages for hosting.
If you want to deploy your web app on a GitHub page (as a free static hosting server), run:
$ grunt github
Start your new web app project with webapplate!
About Fred Lin
Fred Yu-Min Lin, a.k.a. "gasolin", is a front-end web developer working on "Gaia", the user interface for Firefox OS. He is also the book author of Android and FIrefox OS Gaia development. He regularly blogs at http://blog.gasolin.idv.tw and gives presentations to share open web and mobile technologies.
About Robert Nyman [Editor emeritus]