Book Image

Mastering PhoneGap Mobile Application Development

By : Kerri Shotts
Book Image

Mastering PhoneGap Mobile Application Development

By: Kerri Shotts

Overview of this book

PhoneGap is a useful and flexible tool that enables you to create complex hybrid applications for mobile platforms. In addition to the core technology, there is a large and vibrant community that creates third-party plugins that can take your app to the next level. This book will guide you through the process of creating a complex data-driven hybrid mobile application using PhoneGap, web technologies, and third-party plugins. A good foundation is critical, so you will learn how to create a useful workflow to make development easier. From there, the next version of JavaScript (ES6) and the CSS pre-processor SASS are introduced as a way to simplify creating the look of the mobile application. Responsive design techniques are also covered, including the flexbox layout module. As many apps are data-driven, you'll build an application throughout the course of the book that relies upon IndexedDB and SQLite. You'll also download additional content and address how to handle in-app purchases. Furthermore, you’ll build your own customized plugins for your particular use case. When the app is complete, the book will guide you through the steps necessary to submit your app to the Google Play and Apple iTunes stores.
Table of Contents (19 chapters)
Mastering PhoneGap Mobile Application Development
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Creating a modular Gulp configuration


Although you can add all the tasks that you want to run to a single configuration file, this quickly becomes unwieldy as you add more tasks to your environment. In order to keep your configuration maintenance easy, it's best to split everything up into separate files.

This means that aside from our project's directory structure, our Gulp configuration has its own structure. The following shows how I like to structure my configuration:

project-root/
  gulpfile.js            # Stub (loads in everything else)
  gulp/
    config.js            # Configuration – files to copy,
                         # output paths, etc.
    settings.js          # values of command-line flags
    tasks.js             # Stub (loads in all the tasks)
    tasks/               # Contains each task, in its own
      some-task.js       # JavaScript file
      another-task.js
    utils/               # Utility functions all tasks share
      paths.js           # path manipulation methods

Let's go over the code that is in some of the above files. First, let's look at a simplified gulp/config.js file, which stores the base paths, as well as source and destination paths for our project:

var config = {
    paths: {
        base: process.cwd(), // [1]
        dest: "build",       // [2]
        src: "src",          // [3]
        config: "config"     // [4]
    },
    assets: { // [5]
        copy: [ // [6]
                {src:  "www/*.*",         dest: "www"},
                {src:  "www/html/**/*",   dest: "www/html"},
                {src:  "www/img/**/*",    dest: "www/img"},
                {src:  "www/js/lib/**/*", dest: "www/js/lib"},
                {src:  "res/**/*",        dest: "res"}
              ]
    }
}
module.exports = config; // [7]

This is a fairly simple configuration file—we'll end up adding much more to it as the book progresses.

The first section defines the various paths that Gulp will need to know in order to copy our project files as well as those necessary for transforming our code. The base path ([1]) is used as the foundation for every other path, and as such, every other path you see will be relative, not absolute.

The output directory is specified in [2], and the source directory is specified in [3]. Configuration files that we might need for code transformation and style checking are specified in [4]. Each one is relative to the base path.

Every project has a set of assets, and ours is no exception – these are specified in section [5]. In this case, we don't have very many, but even so, they need to be specified so that our tasks know what files they need to work with. We may have many different assets, some of which may require different processing, so we can add to this section as we need. For now, we just need to copy some files, and so we add them to the copy section ([6]). Notice that we specify them in terms of a source wildcard string and a destination path. These will automatically be made relative to the src ([3]) and dest ([2]) paths.

The final line ([7]) is used to export the information out of this file. We can then require the file later in another file (and most of our tasks and the like will do so). This means that our asset and path configuration only needs to be maintained in one place.

Gulp can accept custom command-line arguments, and these can be used to control how various tasks operate. A typical argument might specify the amount of logging that is generated. This is all handled by the gulp/settings.js file. Let's take a look:

var gutil = require("gulp-util");
var settings = {
    VERBOSE: gutil.env.verbose ? (gutil.env.verbose === "yes") 
                               : false
}
module.exports = settings;

Right now, there's not a lot going on in this file, and that's because we really don't have tasks that need to be configured using command line arguments. But we'll be adding to this file as the book goes on.

By itself, this file doesn't do much. All it is doing is using gutil.env to read the arguments passed on the command line. In this case, it's checking to see if we passed verbose on the command line. If we did, and the value was yes, settings.VERBOSE would be set to true. If we didn't (or if we did and the value was no), settings.VERBOSE would be set to false. If we want to take advantage of this setting later on in a task, we can do so.

There's one other file in the gulp/ directory, so let's take a look at gulp/tasks.js:

var path = require("path");
var tasks = require("require-all")(path.join(__dirname, "tasks"));
module.exports = tasks;

As you can see, it's a very short file. All it does is find all the tasks within gulp/tasks/ and load them into the tasks object. Right now that would return an empty object, but by the end of the chapter, the tasks object will contain several methods that Gulp can use. We use the require-all package to make life easier on us—that way we don't have to individually require each and every task. Later on, when we add additional tasks to our Gulp configuration, it means we don't have to later come back and edit this file.

Next, let's look at gulp/utils/paths.js:

var path = require("path"),
    config = require("../config"); // [1]
function makeFullPath(filepath, relativeTo) {
    var pathComponents = [config.paths.base];
    if (relativeTo) {
        pathComponents.push(config.paths[relativeTo]);
    }
    pathComponents = pathComponents.concat(filepath.split("/"));
    return path.join.apply(path, pathComponents);
}
module.exports = {
    SRC: "src",
    DEST: "dest",
    CONFIG: "config",
    makeFullPath: makeFullPath
};

This utility file provides a mechanism our tasks can use to craft paths that are relative to the source, destination, configuration, and base paths in our project. It makes heavy use of Node.js' path library so that our Gulp tasks can work across different platforms.

Finally, we need to create the actual gulpfile.js file that kicks everything off. It doesn't do much on its own; instead it loads everything else in and configures any available tasks with Gulp:

require ("babel/register"); // [1]
var gulp = require("gulp"),
    tasks = require("./gulp/tasks"); // [2]
Object.keys(tasks).forEach(function(taskName) { // [3]
    var taskOpts = tasks[taskName];
    if (typeof taskOpts === "function") {
        gulp.task(taskName, taskOpts); // [4]
    } else {
        gulp.task(taskName, taskOpts.deps, taskOpts.task); // [5]
    }
});

The first line ([1]) imports Babel so that we can use ES2015 code in our tasks should we choose to. The third line ([2]) imports all the tasks that are available. Right now this will be an empty object, but as we add tasks, it will contain more and more functions that Gulp can use to copy and transform files.

The code starting at [3] just takes all the available tasks and creates a corresponding Gulp task. Each task can either be a function, or it can be an object that specifies dependencies (and more), hence the two different method invocations at [4] and [5].