cordova-tasks v0.2.0
Cordova Tasks
This module was created in order to more easily interface Cordova with Gulp (and potentially other build systems). It does so by using cordova-lib rather than using the Cordova CLI. Even so, the functionality is the same, and is compatible with the CLI.
This module is somewhat opinionated — it makes the assumption (founded or not) that your Cordova app is a build artifact. Hence the tasks typically assume that your Cordova project itself is in a build directory or the like (though you can configure the location). It also assumes that you will be copying from a template project (rather than downloading the default Hello World project). Finally, because of the expectation that your Cordova project is a build artifact, it does not offer the entire functionality of the Cordova CLI. For example, it doesn’t support platform updates or removals — the expectation is that you’d rm your build directory instead.
IMPORTANT: This is a 0.2 version. Take that into consideration when using it. It might blow up in your face, run away with your computer, or reach out and throttle you at the most inopportune moment. More likely, it just won’t work the way you expect. (In that case, feel free to contribute or file a bug. In the other cases: I’m not liable!) Furthermore, the interface is extremely apt to change, especially as the functionality is fleshed out.
ALSO VERY IMPORTANT: If you rely on keeping any information in the
.cordovadirectory (like the PhoneGap Build App ID), be very careful! If you delete thebuilddirectory (like I do) without saving this information, you may be in a world of hurt.
Installing Cordova Tasks
Cordova Tasks is available via NPM, and depends on Gulp and gulp-replace-task if you want to utilize the substitution functionality.
$ npm install --save-dev cordova-tasks gulp-replace-taskYou should also install whatever platforms you intend to target:
$ npm install --save-dev cordova-ios cordova-android ...Using Cordova Tasks
First, you need to require Cordova Tasks in your gulpfile, like so:
var cordova = require("cordova-tasks");You’ll need to get a reference to your project’s package.son file (which is where most of the configuration lives), gulp, and gulp-replace-task:
var pkg = require("./package.json"),
gulp = require("gulp"),
replace = require("gulp-replace-task");By itself, this doesn’t do much. Next, you need to instantiate an instance of CordovaTasks:
var cordovaTasks = new cordova.CordovaTasks({
pkg: pkg, # your app's package.json
basePath: __dirname, # app's root
buildDir: "build", # target directory, relative to basePath
sourceDir: "src", # source directory, relative to basePath
gulp: gulp, # gulp
replace: replace}); # gulp-replace-taskBefore you can start using this instance, however, you need to ensure your package.json file is appropriately configured.
Cordova Project Configuration
Most of the configuration for the generated Cordova Project will come from your package.json. The form is as follows:
{
...,
"version": "0.1.0",
...,
"cordova": {
"name": "your-app's-name",
"id": "com.example.reverse-domain",
"description": "Description of your app",
"author": {
"name": "Your name",
"email": "you@example.com",
"site": "http://www.example.com"
},
"template": "./blank",
"platforms": [ "ios", "android" ],
"icon": {
"ios": [
{ "src": "res/icon/ios/icon-60.png", "w": 60, "h": 60 }, ...
],
"android": [
{ "src": "res/icon/android/ldpi.png", "d": "ldpi" }, ...
]
},
"splash": {
"ios": [
{ "src": "res/splash/ios/Default~iphone.png", "w": 320, "h": 480 }, ...
],
"android": [
{ "src": "res/splash/android/splash-land-hdpi.png", "d": "land-hdpi" }, ...
]
},
"preferences": {
"orientation": "default", ...
},
"plugins": [
"cordova-plugin-device", ...
]
}, ...Some notes about this format:
- The top-level
versionis used to give your Cordova project a version. Required - Your app’s title, description, ID, etc. come from the
cordovaobject. Required cordova.nameis your app’s visible name. Requiredcordova.idis your app’s reverse domain ID. Requiredcordova.descriptionis your app’s description. This is only visible inconfig.xml. Requiredcordova.authorsupplies yourconfig.xmlfile with author information. You must supply yourname,email, andsite. Requiredcordova.templateindicates the template to use when creating the Cordova project. This is equivalent to--copy-fromwhen using the CLI. This should usually be a directory with a blankwwwdirectory inside. Requiredcordova.platformsindicates which platforms your project targets. You must have installed them usingnpm install --save-dev cordova-<platform>, not via the CLI. Requiredcordova.iconandcordova.splashindicate where your icons and splash screens are located.srcis relative to the created Cordova project directory, and so in the above example, it would resolve to$PROJECT_ROOT/build/res/….w,hspecify the width and height, respectively (for iOS), whiledspecifies the density (for Android). An array should be present for each supported platform. If the files don’t exist, that’s OK; the build will complain but it isn’t fatal.cordova.preferencesis an array containing key/value strings. The value should always be a string, even for boolean or numeric values.cordova.pluginsis an array of plugins that should be added to the project. These can be plugin IDs (and optionally@version), or URL/local paths -- anything supported bycordova plugin addshould work.
config.xml template
You also need to create a config.xml template in basePath/sourceDir /config.xml. Here’s an example template:
<?xml version='1.0' encoding='utf-8'?>
<widget id="{{{ID}}}" version="{{{VERSION}}}"
xmlns="http://www.w3.org/ns/widgets"
xmlns:cdv="http://cordova.apache.org/ns/1.0"
xmlns:gap="http://phonegap.com/ns/1.0">
<name>{{{NAME}}}</name>
<description>
{{{DESCRIPTION}}}}
</description>
<author email="{{{AUTHOR.EMAIL}}}" href="{{{AUTHOR.SITE}}}">
{{{AUTHOR.NAME}}}
</author>
<content src="index.html" />
<!-- local phonegap/cordova -->
{{{PREFS}}}
{{{PLUGINS}}}
{{{ICONS}}}
{{{SPLASHES}}}
<!-- phonegap build; experimental -->
{{{GAP:PLUGINS}}}
{{{GAP:ICONS}}}
{{{GAP:SPLASHES}}}
<access origin="*" />
</widget>This file is used as a template when creating the Cordova project. The substitution variables are described in the following section.
Cordova Tasks Documentation
The following constants are present on the object returned from require('cordova-tasks'):
BUILD_MODE_DEBUG: Build indebugmodeBUILD_MODE_RELEASE: Build inreleasemode
The following methods are present on the cordovaTasks object:
init(): initializes the project. It’s actually a combination ofcreate,copyConfig,addPlatforms, andaddPlugins. Returns apromise.create(): creates a new project. The project is created inbasePath/buildDir. Returns apromise. Note: If this directory already exists, it must be empty. You canrimrafor similar plugin to clear this prior to calling this command if you want, like so:var path = require("path"), rimraf = require("rimraf"), basePath = __dirname, buildDir = "build"; function clean(cb) { rimraf(path.join(basePath, buildDir), cb); }addPlugins(): adds the plugins listed incordova.pluginsto the project. Returns apromise.addPlatforms(): adds the platforms listed incordova.platformsand installed inbasePath/node_modulesinto the project. Returns apromise.prepare(): Copies the files frombuild/wwwto each platform directory. This is the same ascordova prepare. There’s typically no need to do this, sincebuild,emulate, andruntake care of this step automatically. Returns apromise.build({buildMode, platforms, options}): builds the project. IfbuildModeisn’t supplied, it defaults todebug. If platforms is specified, it should be an array of platforms to build for. If it isn't specified, all platforms will be built. Ifoptionsis specified, it must be an array, and it is concatenated to the array passed tocordoba-lib'sbuildcommand. Returns apromise.emulate|run({platform, buildMode, options}): emulates/runs the project for the specified platform (required). ThebuildModeis passed tobuildand defaults todebugif not supplied. Ifoptionsis specified, it must be an array, and it will be concatenated to the array passed tocordoba-lib'srunoremulatecommand. Returns apromise.cdProject(): Changes to thewwwdirectory withinbasePath/buildDir. This is due to the waycordoba-librequires all commands (other thancreate) to be within a Cordova project. Returns immediately.cdUp(): Changes back up to the original path.copyConfig(): Copies the templateconfig.xmlfile inbasePath/sourceDirtobasePath/buildDirand processes the following substitution variables:{{{VERSION}}}→pkg.version(wherepkgis your project’spackage.json){{{ID}}}→pkg.cordova.id{{{NAME}}}→pkg.cordova.name{{{DESCRIPTION}}}→pkg.cordova.description{{{AUTHOR.NAME}}}→pkg.cordova.author.name{{{AUTHOR.EMAIL}}}→pkg.cordova.author.email{{{AUTHOR.SITE}}}→pkg.cordova.author.site{{{PLUGINS}}}→ transformspkg.cordova.pluginsto<plugin />tags.{{{PREFS}}}→ transformspkg.cordova.preferencesto the appropriate XML{{{ICONS}}}→ transformspkg.cordova.iconto the appropriate XML{{{SPLASHES}}}→ transformspkg.cordova.splashto the appropriate XMLThere are three replacement variables for PhoneGap Build as well:
{{{GAP:PLUGINS}}},{{{GAP:ICONS}}}and{{{GAP:SPLASHES}}}. These should be considered experimental.
NOTE: If you need to process these substitution variables in your own code, you can. Just call
cordovaTasks.processSubstitutionsas part of your stream process, like this:function copyCode() { var isRelease = (BUILD_MODE === "release"); return browserify("./src/www/js/app/index.js", { debug: !isRelease, standalone: "app" }) .transform(babelify.configure({ experimental: true })) .bundle() .on("error", gutil.log.bind(gutil, "Browserify Error")) .pipe(source("app.js")) .pipe(buffer()) .pipe(cordovaTasks.performSubstitutions()) .pipe(isRelease ? gutil.noop() : sourcemaps.init({ loadMaps: true })) .pipe(isRelease ? uglify({preserveComments:"some"}) : gutil.noop()) .pipe(isRelease ? gutil.noop() : sourcemaps.write()) // writes .map file .pipe(gulp.dest(path.join(BUILD_DIR, "www", "js", "app"))) .pipe(livereload()); }
Workflow
So you’ve read all this and are wondering how the Cordova project gets updates to preferences, plugins and platforms, right?
It doesn’t.
At least, I don’t have a method that does that directly. If you want to add that functionality, feel free to issue a pull request, though.
Technically, it’d be super-cool to have a step that compared the settings in
package.jsonand then made the appropriate changes at the next build. Wanna take that challenge? Submit a PR!
Personally, here’s what I do: blow away the build directory whenever I change my preferences, plugins or platforms. I have a command just for it in my gulpfile, init. It depends on a clean step that nukes the build directory and then init calls cordovaTasks.init. Easy-peasy.
Tests
Not many. Yet. I’m sure there’s a way to do it, but I haven’t taken a crack at it. Instead, I’m going to use the horrible phrase, “it works for me!”. ;-)
There are some tests for some of the internal functionality, but these are slim, and don’t actually verify much. If you really want to run them, you can do so by cloning the repo, executing npm install, and then npm test.
Changes
- 2.0 - Added support for
cordova-lib@5.0.0, updated dependencies, added support for PLUGIN tag, addedplatformstobuild - 1.1 - Initial Release
License.
MIT. See LICENSE.