UPDATE: I've submitted a PR to the Ionic team for this. I think it can be useful to others.

I'm finally getting up to speed on Ionic 2 by working my way through the excellent book "Building Mobile Apps with Ionic 2 from Josh Morony.

I've been pleased to see the Ionic Team created a build process so your code is completed in /app and the output is generated in /www. This will replace my previous custom build process when working on Ionic 1.X apps.

I like how the gulp process uses imported scripts to handle the copying of HTML, JS, etc. This keeps your Gulp file from becoming overloaded with JS and makes it much easier to read. They even have a handy Github repo for these simple build scripts.

In Josh's book, he suggests keeping image files in the www directory. For me, I'd rather have EVERYTHING in the /app directory and nothing in the /www directory for version control purposed. This way, the entire /www directory can be ignored. This allows one true source of all app info.

UPDATE: When generating a new Ionic project, the .gitignore file excludes the www/build directory. So, you can safely put images, data, or other content outside the www/build directory for fairly easy version control with Git. However, I still prefer all this be kept in a single location in app.

So, I've put together my own very simple gulp script to do more generic copying / moving of data. I've put it in my project's root directory under /gulp-scripts/gulp-generic-copy.js.

var gulp = require('gulp');

module.exports = function(options) {

  if(!options || !options.src  || !options.dest) {
    return;
  }
  return gulp.src(options.src)
    .pipe(gulp.dest(options.dest));
};

Now, I can do simple generic things like this:

gulp.task('data', function() {
  return copyGeneric({
    src: 'app/data/**/*.json',
    dest: 'www/data'
  });
});

gulp.task('images', function() {
  return copyGeneric({
    src: ['app/images/**/*.jpg', 'app/images/**/*.png'],
    dest: 'www/images'
  });
});

Instead of a unique gulp script for each type of data, I just pass in an options object with the right src and dest files.

Then, I can add these tasks to the build and watch sections of the gulp script.

gulp.task('watch', ['clean'], function(done){
  runSequence(
    ['sass', 'html', 'fonts', 'scripts', 'data', 'images'],
    function(){
      gulpWatch('app/data/**/*.json', function(){ gulp.start('data'); });
      gulpWatch('app/**/*.scss', function(){ gulp.start('sass'); });
      gulpWatch('app/**/*.html', function(){ gulp.start('html'); });
      buildBrowserify({ watch: true }).on('end', done);
    }
  );
});

gulp.task('build', ['clean'], function(done){
  runSequence(
    ['sass', 'html', 'fonts', 'scripts', 'data', 'images'],
    function(){
      buildBrowserify({
        minify: isRelease,
        browserifyOptions: {
          debug: !isRelease
        },
        uglifyOptions: {
          mangle: false
        }
      }).on('end', done);
    }
  );
});

P.S. You probably should NOT add your images directory to the list of watched files. Doing so really tends to eat up CPU space if you have lots of files. Gulp wasn't really made for analyzing images.