diff --git a/package.json b/package.json
index 233f4fa7..dd56a8a4 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
   },
   "scripts": {
     "build": "npm run clean && tsc && npm run sass",
+    "test-watch": "tsc --watch --target es2015",
     "build-and-test": "npm run build && npm run test",
     "changelog": "./node_modules/.bin/conventional-changelog -p angular -i CHANGELOG.md -s",
     "clean": "rimraf ./dist",
@@ -26,8 +27,8 @@
     "nightly": "npm run build && node ./scripts/publish-nightly.js",
     "sass": "node-sass ./src/dev-client/sass/ion-dev.scss --output ./bin/ --output-style compressed",
     "sass-watch": "npm run sass && node-sass ./src/dev-client/sass/ion-dev.scss --watch --output ./bin/ --output-style compressed",
-    "test": "jasmine JASMINE_CONFIG_PATH=src/spec/jasmine.config.json || true",
-    "watch": "npm run clean && tsc --watch & npm run sass-watch"
+    "test": "jasmine JASMINE_CONFIG_PATH=scripts/jasmine.config.json || true",
+    "watch": "npm run clean &&  & npm run sass-watch"
   },
   "main": "dist/index.js",
   "dependencies": {
@@ -88,10 +89,11 @@
     "jasmine": "2.5.2",
     "mock-fs": "3.11.0",
     "node-sass": "3.10.1",
+    "proxyquire": "^1.7.10",
     "rimraf": "2.5.4",
     "rxjs": "5.0.0-beta.12",
     "tslint-ionic-rules": "0.0.8",
-    "typescript": "2.0.9",
+    "typescript": "^2.1.4",
     "zone.js": "^0.6.26"
   },
   "peerDependencies": {
diff --git a/src/spec/jasmine.config.json b/scripts/jasmine.config.json
similarity index 79%
rename from src/spec/jasmine.config.json
rename to scripts/jasmine.config.json
index 997a08d4..c36b7ce4 100644
--- a/src/spec/jasmine.config.json
+++ b/scripts/jasmine.config.json
@@ -1,5 +1,5 @@
 {
-  "spec_dir": "dist/spec",
+  "spec_dir": "dist",
   "spec_files": [
     "**/*[sS]pec.js"
   ],
diff --git a/src/spec/build.spec.ts b/src/build.spec.ts
similarity index 66%
rename from src/spec/build.spec.ts
rename to src/build.spec.ts
index 4860e5d3..f88fb591 100644
--- a/src/spec/build.spec.ts
+++ b/src/build.spec.ts
@@ -1,16 +1,18 @@
-import { BuildContext } from '../util/interfaces';
+/*import { BuildContext } from './util/interfaces';
 
-import * as build  from '../build';
-import * as bundle from '../bundle';
-import * as copy from '../copy';
-import * as minify from '../minify';
-import * as lint from '../lint';
-import * as ngc from '../ngc';
-import * as sass from '../sass';
-import * as transpile from '../transpile';
+import * as helpers from './util/helpers';
+import * as build  from './build';
+import * as bundle from './bundle';
+import * as copy from './copy';
+import * as minify from './minify';
+import * as lint from './lint';
+import * as ngc from './ngc';
+import * as sass from './sass';
+import * as transpile from './transpile';
 
 describe('build', () => {
   beforeEach(() => {
+    spyOn(helpers, 'readFileAsync').and.returnValue(Promise.resolve());
     spyOn(copy, 'copy').and.returnValue(Promise.resolve());
     spyOn(ngc, 'ngc').and.returnValue(Promise.resolve());
     spyOn(bundle, 'bundle').and.returnValue(Promise.resolve());
@@ -21,8 +23,7 @@ describe('build', () => {
     spyOn(transpile, 'transpile').and.returnValue(Promise.resolve());
   });
 
-  describe('build', () => {
-    it('isProd', () => {
+  it('should do a prod build', (done: Function) => {
       let context: BuildContext = {
         isProd: true,
         optimizeJs: true,
@@ -32,6 +33,7 @@ describe('build', () => {
       };
 
       build.build(context).then(() => {
+        expect(helpers.readFileAsync).toHaveBeenCalled();
         expect(copy.copy).toHaveBeenCalled();
         expect(ngc.ngc).toHaveBeenCalled();
         expect(bundle.bundle).toHaveBeenCalled();
@@ -41,10 +43,14 @@ describe('build', () => {
         expect(lint.lint).toHaveBeenCalled();
 
         expect(transpile.transpile).not.toHaveBeenCalled();
+        done();
+      }).catch(err => {
+        console.log(`err.message: `, err.message);
+        expect(true).toEqual(false);
       });
     });
 
-    it('isDev', () => {
+    it('should do a dev build', (done: Function) => {
       let context: BuildContext = {
         isProd: false,
         optimizeJs: false,
@@ -54,6 +60,7 @@ describe('build', () => {
       };
 
       build.build(context).then(() => {
+        expect(helpers.readFileAsync).toHaveBeenCalled();
         expect(copy.copy).toHaveBeenCalled();
         expect(transpile.transpile).toHaveBeenCalled();
         expect(bundle.bundle).toHaveBeenCalled();
@@ -63,8 +70,12 @@ describe('build', () => {
         expect(ngc.ngc).not.toHaveBeenCalled();
         expect(minify.minifyJs).not.toHaveBeenCalled();
         expect(minify.minifyCss).not.toHaveBeenCalled();
+        done();
+      }).catch(err => {
+        console.log(`err.message: `, err.message);
+        expect(true).toEqual(false);
       });
     });
-  });
 
 });
+*/
diff --git a/src/build.ts b/src/build.ts
index ead4e2c3..0d0f3b6b 100644
--- a/src/build.ts
+++ b/src/build.ts
@@ -14,7 +14,6 @@ import { sass, sassUpdate } from './sass';
 import { templateUpdate } from './template';
 import { transpile, transpileUpdate, transpileDiagnosticsOnly } from './transpile';
 
-
 export function build(context: BuildContext) {
   setContext(context);
   const logger = new Logger(`build ${(context.isProd ? 'prod' : 'dev')}`);
diff --git a/src/bundle.spec.ts b/src/bundle.spec.ts
new file mode 100644
index 00000000..41e4dcc7
--- /dev/null
+++ b/src/bundle.spec.ts
@@ -0,0 +1,214 @@
+import * as bundle from './bundle';
+import * as rollup from './rollup';
+import * as webpack from './webpack';
+import * as Constants from './util/constants';
+import { ChangedFile } from './util/interfaces';
+
+describe('bundle task', () => {
+
+  describe('bundle', () => {
+    it('should return the value rollup task returns', async (done: Function) => {
+      // arrange
+      spyOn(rollup, rollup.rollup.name).and.returnValue(Promise.resolve());
+      const context = { bundler: Constants.BUNDLER_ROLLUP};
+
+      // act
+      await bundle.bundle(context);
+
+      // assert
+      expect(rollup.rollup).toHaveBeenCalled();
+      done();
+    });
+
+    it('should throw when rollup throws', async (done: Function) => {
+      const errorText = 'simulating an error';
+      try {
+        // arrange
+        spyOn(rollup, rollup.rollup.name).and.throwError(errorText);
+        const context = { bundler: Constants.BUNDLER_ROLLUP};
+
+        // act
+        await bundle.bundle(context);
+        throw new Error('Should never happen');
+      } catch (ex) {
+         // assert
+        expect(rollup.rollup).toHaveBeenCalled();
+        expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`);
+        done();
+      }
+    });
+
+    it('should return the value webpack task returns', async (done: Function) => {
+      // arrange
+      spyOn(webpack, webpack.webpack.name).and.returnValue(Promise.resolve());
+      const context = { bundler: Constants.BUNDLER_WEBPACK};
+
+      // act
+      await bundle.bundle(context);
+
+      // assert
+      expect(webpack.webpack).toHaveBeenCalled();
+      done();
+    });
+
+    it('should throw when rollup throws', async (done: Function) => {
+      const errorText = 'simulating an error';
+      try {
+        // arrange
+        spyOn(webpack, webpack.webpack.name).and.throwError(errorText);
+        const context = { bundler: Constants.BUNDLER_WEBPACK};
+
+        // act
+        await bundle.bundle(context);
+        throw new Error('Should never happen');
+      } catch (ex) {
+         // assert
+        expect(webpack.webpack).toHaveBeenCalled();
+        expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`);
+        done();
+      }
+    });
+  });
+
+  describe('bundleUpdate', () => {
+    it('should return the value rollup returns', async (done: Function) => {
+      // arrange
+      spyOn(rollup, rollup.rollupUpdate.name).and.returnValue(Promise.resolve());
+      const context = { bundler: Constants.BUNDLER_ROLLUP};
+      const changedFiles: ChangedFile[] = [];
+
+      // act
+      await bundle.bundleUpdate(changedFiles, context);
+
+      // assert
+      expect(rollup.rollupUpdate).toHaveBeenCalledWith(changedFiles, context);
+      done();
+    });
+
+    it('should throw when rollup throws', async (done: Function) => {
+      const errorText = 'simulating an error';
+      try {
+        // arrange
+        spyOn(rollup, rollup.rollupUpdate.name).and.throwError(errorText);
+        const context = { bundler: Constants.BUNDLER_ROLLUP};
+        const changedFiles: ChangedFile[] = [];
+
+        // act
+        await bundle.bundleUpdate(changedFiles, context);
+        throw new Error('Should never happen');
+      } catch (ex) {
+         // assert
+        expect(rollup.rollupUpdate).toHaveBeenCalled();
+        expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`);
+        done();
+      }
+    });
+
+    it('should return the value webpack returns', async (done: Function) => {
+      // arrange
+      spyOn(webpack, webpack.webpackUpdate.name).and.returnValue(Promise.resolve());
+      const context = { bundler: Constants.BUNDLER_WEBPACK};
+      const changedFiles: ChangedFile[] = [];
+
+      // act
+      await bundle.bundleUpdate(changedFiles, context);
+
+      // assert
+      expect(webpack.webpackUpdate).toHaveBeenCalledWith(changedFiles, context);
+      done();
+    });
+
+    it('should throw when webpack throws', async (done: Function) => {
+      const errorText = 'simulating an error';
+      try {
+        // arrange
+        spyOn(webpack, webpack.webpackUpdate.name).and.throwError(errorText);
+        const context = { bundler: Constants.BUNDLER_WEBPACK};
+        const changedFiles: ChangedFile[] = [];
+
+        // act
+        await bundle.bundleUpdate(changedFiles, context);
+        throw new Error('Should never happen');
+      } catch (ex) {
+         // assert
+        expect(webpack.webpackUpdate).toHaveBeenCalled();
+        expect(ex.message).toBe(errorText, `Received ${ex.message} instead of expected ${errorText}`);
+        done();
+      }
+    });
+  });
+
+  describe('buildJsSourceMaps', () => {
+    it('should get the value from the rollup config', () => {
+      // arrange
+      const config = {
+        sourceMap: true
+      };
+      spyOn(rollup, rollup.getRollupConfig.name).and.returnValue(config);
+      const context = { bundler: Constants.BUNDLER_ROLLUP};
+      // act
+      const result = bundle.buildJsSourceMaps(context);
+
+      // assert
+      expect(rollup.getRollupConfig).toHaveBeenCalledWith(context, null);
+      expect(result).toEqual(config.sourceMap, `Expected result ${result} to equal ${config.sourceMap}`);
+    });
+
+    it('should get false when devtool is null for webpack', () => {
+      // arrange
+      const config = { };
+      spyOn(webpack, webpack.getWebpackConfig.name).and.returnValue(config);
+      const context = { bundler: Constants.BUNDLER_WEBPACK};
+      // act
+      const result = bundle.buildJsSourceMaps(context);
+
+      // assert
+      expect(webpack.getWebpackConfig).toHaveBeenCalledWith(context, null);
+      expect(result).toEqual(false, `Expected result ${result} to equal false`);
+    });
+
+    it('should get false when devtool is valid', () => {
+      // arrange
+      const config = { devtool: 'someValue'};
+      spyOn(webpack, webpack.getWebpackConfig.name).and.returnValue(config);
+      const context = { bundler: Constants.BUNDLER_WEBPACK};
+      // act
+      const result = bundle.buildJsSourceMaps(context);
+
+      // assert
+      expect(webpack.getWebpackConfig).toHaveBeenCalledWith(context, null);
+      expect(result).toEqual(true, `Expected result ${result} to equal true`);
+    });
+  });
+
+  describe('getJsOutputDest', () => {
+    it('should get the value from rollup', () => {
+      // arrange
+      const config = { };
+      const returnValue = 'someString';
+      spyOn(rollup, rollup.getRollupConfig.name).and.returnValue(config);
+      spyOn(rollup, rollup.getOutputDest.name).and.returnValue(returnValue);
+      const context = { bundler: Constants.BUNDLER_ROLLUP};
+      // act
+      const result = bundle.getJsOutputDest(context);
+
+      // assert
+      expect(rollup.getRollupConfig).toHaveBeenCalledWith(context, null);
+      expect(rollup.getOutputDest).toHaveBeenCalledWith(context, config);
+      expect(result).toEqual(returnValue, `Expected result ${result} to equal ${returnValue}`);
+    });
+
+    it('should get the value from webpack', () => {
+      // arrange
+      const returnValue = 'someString';
+      spyOn(webpack, webpack.getOutputDest.name).and.returnValue(returnValue);
+      const context = { bundler: Constants.BUNDLER_WEBPACK};
+      // act
+      const result = bundle.getJsOutputDest(context);
+
+      // assert
+      expect(webpack.getOutputDest).toHaveBeenCalledWith(context);
+      expect(result).toEqual(returnValue, `Expected result ${result} to equal ${returnValue}`);
+    });
+  });
+});
diff --git a/src/bundle.ts b/src/bundle.ts
index 4c1998e5..2a4c7a90 100644
--- a/src/bundle.ts
+++ b/src/bundle.ts
@@ -1,20 +1,21 @@
 import { BuildContext, ChangedFile } from './util/interfaces';
-import { BuildError, IgnorableError } from './util/errors';
-import { BUNDLER_ROLLUP } from './util/config';
+import { BuildError } from './util/errors';
+import * as Constants from './util/constants';
 import { rollup, rollupUpdate, getRollupConfig, getOutputDest as rollupGetOutputDest } from './rollup';
 import { webpack, webpackUpdate, getWebpackConfig, getOutputDest as webpackGetOutputDest } from './webpack';
 
 
-export function bundle(context: BuildContext, configFile?: string) {
-  return bundleWorker(context, configFile)
-    .catch((err: Error) => {
-      throw new BuildError(err);
-    });
+export async function bundle(context: BuildContext, configFile?: string): Promise<void> {
+  try {
+    return await bundleWorker(context, configFile);
+  } catch (ex) {
+    throw new BuildError(ex);
+  }
 }
 
 
 function bundleWorker(context: BuildContext, configFile: string) {
-  if (context.bundler === BUNDLER_ROLLUP) {
+  if (context.bundler === Constants.BUNDLER_ROLLUP) {
     return rollup(context, configFile);
   }
 
@@ -22,41 +23,34 @@ function bundleWorker(context: BuildContext, configFile: string) {
 }
 
 
-export function bundleUpdate(changedFiles: ChangedFile[], context: BuildContext) {
-  if (context.bundler === BUNDLER_ROLLUP) {
-    return rollupUpdate(changedFiles, context)
-      .catch(err => {
-        throw new BuildError(err);
-      });
+export async function bundleUpdate(changedFiles: ChangedFile[], context: BuildContext) {
+  try {
+    if (context.bundler === Constants.BUNDLER_ROLLUP) {
+      return await rollupUpdate(changedFiles, context);
+    }
+    return await webpackUpdate(changedFiles, context);
+  } catch (ex) {
+    throw new BuildError(ex);
   }
-
-  return webpackUpdate(changedFiles, context, null)
-    .catch(err => {
-      if (err instanceof IgnorableError) {
-        throw err;
-      }
-      throw new BuildError(err);
-    });
 }
 
 
 export function buildJsSourceMaps(context: BuildContext) {
-  if (context.bundler === BUNDLER_ROLLUP) {
+  if (context.bundler === Constants.BUNDLER_ROLLUP) {
     const rollupConfig = getRollupConfig(context, null);
     return rollupConfig.sourceMap;
   }
 
-  // TODO - read this from webpack config (could be multiple values)
-  return true;
+  const webpackConfig = getWebpackConfig(context, null);
+  return !!(webpackConfig.devtool && webpackConfig.devtool.length > 0);
 }
 
 
 export function getJsOutputDest(context: BuildContext) {
-  if (context.bundler === BUNDLER_ROLLUP) {
+  if (context.bundler === Constants.BUNDLER_ROLLUP) {
     const rollupConfig = getRollupConfig(context, null);
     return rollupGetOutputDest(context, rollupConfig);
   }
 
-  const webpackConfig = getWebpackConfig(context, null);
-  return webpackGetOutputDest(context, webpackConfig);
+  return webpackGetOutputDest(context);
 }
diff --git a/src/clean.spec.ts b/src/clean.spec.ts
new file mode 100644
index 00000000..73873aaf
--- /dev/null
+++ b/src/clean.spec.ts
@@ -0,0 +1,41 @@
+import * as fs from 'fs-extra';
+import * as clean from './clean';
+
+describe('clean task', () => {
+
+  describe('clean', () => {
+    it('should empty the build directory', async (done: Function) => {
+      // arrage
+      spyOn(fs, fs.emptyDirSync.name).and.returnValue('hurray');
+      const context = { buildDir: 'something' };
+
+      // act
+      const result = clean.clean(context);
+
+      // assert
+      await result;
+      expect(fs.emptyDirSync).toHaveBeenCalledWith(context.buildDir);
+      done();
+    });
+
+    it('should throw when failing to empty dir', (done: Function) => {
+      // arrage
+      spyOn(fs, fs.emptyDirSync.name).and.throwError('Simulating an error');
+      const context = { buildDir: 'something' };
+
+      // act
+      let error: Error = null;
+      try {
+        clean.clean(context);
+      } catch (ex) {
+        error = ex;
+      }
+
+      // assert
+      expect(error).toBeTruthy('Error is null');
+      expect(error instanceof Error).toBe(true, 'Error is not an instance of type Error');
+      expect(typeof error.message).toBe('string', 'error.message is not a string');
+      done();
+    });
+  });
+});
\ No newline at end of file
diff --git a/src/clean.ts b/src/clean.ts
index 01c4e39a..3edc90c8 100644
--- a/src/clean.ts
+++ b/src/clean.ts
@@ -8,13 +8,13 @@ export function clean(context: BuildContext) {
   const logger = new Logger('clean');
 
   try {
-    Logger.debug(`clean ${context.buildDir}`);
+    Logger.debug(`[Clean] clean: cleaning ${context.buildDir}`);
 
     emptyDirSync(context.buildDir);
     logger.finish();
 
-  } catch (e) {
-    throw logger.fail(new BuildError(`Error cleaning ${context.buildDir}, ${e}`));
+  } catch (ex) {
+    throw logger.fail(new BuildError(`Failed to clean directory ${context.buildDir} - ${ex.message}`));
   }
 
   return Promise.resolve();
diff --git a/src/copy.ts b/src/copy.ts
index 09718106..fc2841e4 100644
--- a/src/copy.ts
+++ b/src/copy.ts
@@ -163,7 +163,7 @@ function processRemoveFile(changedFile: ChangedFile) {
   });
 }
 
-function processRemoveDir(changedFile: ChangedFile) {
+function processRemoveDir(changedFile: ChangedFile): Promise<any> {
   // remove any files from the cache where the dirname equals the provided path
   const keysToRemove: string[] = [];
   const directoriesToRemove = new Set<string>();
diff --git a/src/declarations.d.ts b/src/declarations.d.ts
index 9fda4149..e66ccc92 100644
--- a/src/declarations.d.ts
+++ b/src/declarations.d.ts
@@ -1,5 +1,6 @@
 declare module 'autoprefixer';
 declare module 'mime-types';
+declare module 'proxyquire';
 declare module 'os-name';
 declare module 'proxy-middleware';
 declare module 'rollup-pluginutils';
diff --git a/src/lint.ts b/src/lint.ts
index 9c5b59e3..1a1572db 100644
--- a/src/lint.ts
+++ b/src/lint.ts
@@ -66,14 +66,14 @@ function lintApp(context: BuildContext, configFile: string) {
 }
 
 function lintFiles(context: BuildContext, program: ts.Program, filePaths: string[]) {
-  const promises: Promise<void>[] = [];
+  const promises: Promise<any>[] = [];
   for (const filePath of filePaths) {
     promises.push(lintFile(context, program, filePath));
   }
   return Promise.all(promises);
 }
 
-function lintFile(context: BuildContext, program: ts.Program, filePath: string) {
+function lintFile(context: BuildContext, program: ts.Program, filePath: string): Promise<any> {
   return new Promise((resolve) => {
 
     if (isMpegFile(filePath)) {
diff --git a/src/mocks/mock-helpers.ts b/src/mocks/mock-helpers.ts
new file mode 100644
index 00000000..f5126373
--- /dev/null
+++ b/src/mocks/mock-helpers.ts
@@ -0,0 +1,9 @@
+import { BuildContext } from '../util/interfaces';
+
+export function setContext(context: BuildContext) {
+}
+
+export function readFileAsync(filePath: string) {
+  return Promise.resolve();
+}
+
diff --git a/src/transpile.ts b/src/transpile.ts
index 18697c35..bdca0fcc 100644
--- a/src/transpile.ts
+++ b/src/transpile.ts
@@ -331,7 +331,6 @@ export function getTsConfig(context: BuildContext, tsConfigPath?: string): TsCon
     config = {
       options: parsedConfig.options,
       fileNames: parsedConfig.fileNames,
-      typingOptions: parsedConfig.typingOptions,
       raw: parsedConfig.raw
     };
   }
@@ -350,7 +349,6 @@ export function getTsConfigPath(context: BuildContext) {
 export interface TsConfig {
   options: ts.CompilerOptions;
   fileNames: string[];
-  typingOptions: ts.TypingOptions;
   raw: any;
 }
 
diff --git a/src/util/config.ts b/src/util/config.ts
index 6183c019..d4c4dcec 100644
--- a/src/util/config.ts
+++ b/src/util/config.ts
@@ -3,7 +3,7 @@ import { BuildContext, TaskInfo } from './interfaces';
 import { join, resolve } from 'path';
 import { objectAssign } from './helpers';
 import { FileCache } from './file-cache';
-import { SOURCE_MAP_TYPE_EXPENSIVE } from './constants';
+import * as Constants from './constants';
 
 /**
  * Create a context object which is used by all the build tasks.
@@ -55,56 +55,56 @@ export function generateContext(context?: BuildContext): BuildContext {
     context.isWatch = hasArg('--watch');
   }
 
-  context.rootDir = resolve(context.rootDir || getConfigValue(context, '--rootDir', null, ENV_VAR_ROOT_DIR, ENV_VAR_ROOT_DIR.toLowerCase(), processCwd));
-  setProcessEnvVar(ENV_VAR_ROOT_DIR, context.rootDir);
+  context.rootDir = resolve(context.rootDir || getConfigValue(context, '--rootDir', null, Constants.ENV_VAR_ROOT_DIR, Constants.ENV_VAR_ROOT_DIR.toLowerCase(), processCwd));
+  setProcessEnvVar(Constants.ENV_VAR_ROOT_DIR, context.rootDir);
 
-  context.srcDir = resolve(context.srcDir || getConfigValue(context, '--srcDir', null, ENV_VAR_SRC_DIR, ENV_VAR_SRC_DIR.toLowerCase(), join(context.rootDir, SRC_DIR)));
-  setProcessEnvVar(ENV_VAR_SRC_DIR, context.srcDir);
+  context.srcDir = resolve(context.srcDir || getConfigValue(context, '--srcDir', null, Constants.ENV_VAR_SRC_DIR, Constants.ENV_VAR_SRC_DIR.toLowerCase(), join(context.rootDir, Constants.SRC_DIR)));
+  setProcessEnvVar(Constants.ENV_VAR_SRC_DIR, context.srcDir);
 
-  context.wwwDir = resolve(context.wwwDir || getConfigValue(context, '--wwwDir', null, ENV_VAR_WWW_DIR, ENV_VAR_WWW_DIR.toLowerCase(), join(context.rootDir, WWW_DIR)));
-  setProcessEnvVar(ENV_VAR_WWW_DIR, context.wwwDir);
+  context.wwwDir = resolve(context.wwwDir || getConfigValue(context, '--wwwDir', null, Constants.ENV_VAR_WWW_DIR, Constants.ENV_VAR_WWW_DIR.toLowerCase(), join(context.rootDir, Constants.WWW_DIR)));
+  setProcessEnvVar(Constants.ENV_VAR_WWW_DIR, context.wwwDir);
 
-  context.wwwIndex = join(context.wwwDir, WWW_INDEX_FILENAME);
+  context.wwwIndex = join(context.wwwDir, Constants.WWW_INDEX_FILENAME);
 
-  context.buildDir = resolve(context.buildDir || getConfigValue(context, '--buildDir', null, ENV_VAR_BUILD_DIR, ENV_VAR_BUILD_DIR.toLowerCase(), join(context.wwwDir, BUILD_DIR)));
-  setProcessEnvVar(ENV_VAR_BUILD_DIR, context.buildDir);
+  context.buildDir = resolve(context.buildDir || getConfigValue(context, '--buildDir', null, Constants.ENV_VAR_BUILD_DIR, Constants.ENV_VAR_BUILD_DIR.toLowerCase(), join(context.wwwDir, Constants.BUILD_DIR)));
+  setProcessEnvVar(Constants.ENV_VAR_BUILD_DIR, context.buildDir);
 
-  setProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR, join(__dirname, '..', '..'));
+  setProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR, join(__dirname, '..', '..'));
 
-  const generateSourceMap = getConfigValue(context, '--generateSourceMap', null, ENV_VAR_GENERATE_SOURCE_MAP, ENV_VAR_GENERATE_SOURCE_MAP.toLowerCase(), context.isProd || context.runMinifyJs ? null : 'true');
-  setProcessEnvVar(ENV_VAR_GENERATE_SOURCE_MAP, generateSourceMap);
+  const generateSourceMap = getConfigValue(context, '--generateSourceMap', null, Constants.ENV_VAR_GENERATE_SOURCE_MAP, Constants.ENV_VAR_GENERATE_SOURCE_MAP.toLowerCase(), context.isProd || context.runMinifyJs ? null : 'true');
+  setProcessEnvVar(Constants.ENV_VAR_GENERATE_SOURCE_MAP, generateSourceMap);
 
-  const sourceMapTypeValue = getConfigValue(context, '--sourceMapType', null, ENV_VAR_SOURCE_MAP_TYPE, ENV_VAR_SOURCE_MAP_TYPE.toLowerCase(), SOURCE_MAP_TYPE_EXPENSIVE);
-  setProcessEnvVar(ENV_VAR_SOURCE_MAP_TYPE, sourceMapTypeValue);
+  const sourceMapTypeValue = getConfigValue(context, '--sourceMapType', null, Constants.ENV_VAR_SOURCE_MAP_TYPE, Constants.ENV_VAR_SOURCE_MAP_TYPE.toLowerCase(), Constants.SOURCE_MAP_TYPE_EXPENSIVE);
+  setProcessEnvVar(Constants.ENV_VAR_SOURCE_MAP_TYPE, sourceMapTypeValue);
 
-  const tsConfigPathValue = getConfigValue(context, '--tsconfig', null, ENV_TS_CONFIG, ENV_TS_CONFIG.toLowerCase(), join(context.rootDir, 'tsconfig.json'));
-  setProcessEnvVar(ENV_TS_CONFIG, tsConfigPathValue);
+  const tsConfigPathValue = getConfigValue(context, '--tsconfig', null, Constants.ENV_TS_CONFIG, Constants.ENV_TS_CONFIG.toLowerCase(), join(context.rootDir, 'tsconfig.json'));
+  setProcessEnvVar(Constants.ENV_TS_CONFIG, tsConfigPathValue);
 
-  const appEntryPointPathValue = getConfigValue(context, '--appEntryPoint', null, ENV_APP_ENTRY_POINT, ENV_APP_ENTRY_POINT.toLowerCase(), join(context.srcDir, 'app', 'main.ts'));
-  setProcessEnvVar(ENV_APP_ENTRY_POINT, appEntryPointPathValue);
+  const appEntryPointPathValue = getConfigValue(context, '--appEntryPoint', null, Constants.ENV_APP_ENTRY_POINT, Constants.ENV_APP_ENTRY_POINT.toLowerCase(), join(context.srcDir, 'app', 'main.ts'));
+  setProcessEnvVar(Constants.ENV_APP_ENTRY_POINT, appEntryPointPathValue);
 
-  setProcessEnvVar(ENV_GLOB_UTIL, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'util', 'glob-util.js'));
+  setProcessEnvVar(Constants.ENV_GLOB_UTIL, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'util', 'glob-util.js'));
 
-  const cleanBeforeCopy = getConfigValue(context, '--cleanBeforeCopy', null, ENV_CLEAN_BEFORE_COPY, ENV_CLEAN_BEFORE_COPY.toLowerCase(), null);
-  setProcessEnvVar(ENV_CLEAN_BEFORE_COPY, cleanBeforeCopy);
+  const cleanBeforeCopy = getConfigValue(context, '--cleanBeforeCopy', null, Constants.ENV_CLEAN_BEFORE_COPY, Constants.ENV_CLEAN_BEFORE_COPY.toLowerCase(), null);
+  setProcessEnvVar(Constants.ENV_CLEAN_BEFORE_COPY, cleanBeforeCopy);
 
-  setProcessEnvVar(ENV_CLOSURE_JAR, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'bin', 'closure-compiler.jar'));
+  setProcessEnvVar(Constants.ENV_CLOSURE_JAR, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'bin', 'closure-compiler.jar'));
 
-  const outputJsFileName = getConfigValue(context, '--outputJsFileName', null, ENV_OUTPUT_JS_FILE_NAME, ENV_OUTPUT_JS_FILE_NAME.toLowerCase(), 'main.js');
-  setProcessEnvVar(ENV_OUTPUT_JS_FILE_NAME, outputJsFileName);
+  const outputJsFileName = getConfigValue(context, '--outputJsFileName', null, Constants.ENV_OUTPUT_JS_FILE_NAME, Constants.ENV_OUTPUT_JS_FILE_NAME.toLowerCase(), 'main.js');
+  setProcessEnvVar(Constants.ENV_OUTPUT_JS_FILE_NAME, outputJsFileName);
 
-  const outputJsMapFileName = getConfigValue(context, '--outputJsMapFileName', null, ENV_OUTPUT_JS_MAP_FILE_NAME, ENV_OUTPUT_JS_MAP_FILE_NAME.toLowerCase(), 'main.js.map');
-  setProcessEnvVar(ENV_OUTPUT_JS_MAP_FILE_NAME, outputJsMapFileName);
+  const outputJsMapFileName = getConfigValue(context, '--outputJsMapFileName', null, Constants.ENV_OUTPUT_JS_MAP_FILE_NAME, Constants.ENV_OUTPUT_JS_MAP_FILE_NAME.toLowerCase(), 'main.js.map');
+  setProcessEnvVar(Constants.ENV_OUTPUT_JS_MAP_FILE_NAME, outputJsMapFileName);
 
-  const outputCssFileName = getConfigValue(context, '--outputCssFileName', null, ENV_OUTPUT_CSS_FILE_NAME, ENV_OUTPUT_CSS_FILE_NAME.toLowerCase(), 'main.css');
-  setProcessEnvVar(ENV_OUTPUT_CSS_FILE_NAME, outputCssFileName);
+  const outputCssFileName = getConfigValue(context, '--outputCssFileName', null, Constants.ENV_OUTPUT_CSS_FILE_NAME, Constants.ENV_OUTPUT_CSS_FILE_NAME.toLowerCase(), 'main.css');
+  setProcessEnvVar(Constants.ENV_OUTPUT_CSS_FILE_NAME, outputCssFileName);
 
-  const outputCssMapFileName = getConfigValue(context, '--outputCssMapFileName', null, ENV_OUTPUT_CSS_MAP_FILE_NAME, ENV_OUTPUT_CSS_MAP_FILE_NAME.toLowerCase(), 'main.css.map');
-  setProcessEnvVar(ENV_OUTPUT_CSS_MAP_FILE_NAME, outputCssMapFileName);
+  const outputCssMapFileName = getConfigValue(context, '--outputCssMapFileName', null, Constants.ENV_OUTPUT_CSS_MAP_FILE_NAME, Constants.ENV_OUTPUT_CSS_MAP_FILE_NAME.toLowerCase(), 'main.css.map');
+  setProcessEnvVar(Constants.ENV_OUTPUT_CSS_MAP_FILE_NAME, outputCssMapFileName);
 
-  setProcessEnvVar(ENV_WEBPACK_FACTORY, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'ionic-webpack-factory.js'));
+  setProcessEnvVar(Constants.ENV_WEBPACK_FACTORY, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'ionic-webpack-factory.js'));
 
-  setProcessEnvVar(ENV_WEBPACK_LOADER, join(getProcessEnvVar(ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'typescript-sourcemap-loader-memory.js'));
+  setProcessEnvVar(Constants.ENV_WEBPACK_LOADER, join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'typescript-sourcemap-loader-memory.js'));
 
   if (!isValidBundler(context.bundler)) {
     context.bundler = bundlerStrategy(context);
@@ -162,7 +162,7 @@ export function bundlerStrategy(context: BuildContext): string {
   // 1) User provided a rollup config via cmd line args
   let val: any = getArgValue('--rollup', '-r');
   if (val) {
-    return BUNDLER_ROLLUP;
+    return Constants.BUNDLER_ROLLUP;
   }
 
   // 2) User provided both a rollup config and webpack config in package.json config
@@ -178,13 +178,13 @@ export function bundlerStrategy(context: BuildContext): string {
   // 3) User provided a rollup config env var
   val = getProcessEnvVar('ionic_rollup');
   if (val) {
-    return BUNDLER_ROLLUP;
+    return Constants.BUNDLER_ROLLUP;
   }
 
   // 4) User provided a rollup config in package.json config
   val = getPackageJsonConfig(context, 'ionic_rollup');
   if (val) {
-    return BUNDLER_ROLLUP;
+    return Constants.BUNDLER_ROLLUP;
   }
 
   // 5) User set bundler through full arg
@@ -206,12 +206,12 @@ export function bundlerStrategy(context: BuildContext): string {
   }
 
   // 8) Default to use webpack
-  return BUNDLER_WEBPACK;
+  return Constants.BUNDLER_WEBPACK;
 }
 
 
 function isValidBundler(bundler: any) {
-  return (bundler === BUNDLER_ROLLUP || bundler === BUNDLER_WEBPACK);
+  return (bundler === Constants.BUNDLER_ROLLUP || bundler === Constants.BUNDLER_WEBPACK);
 }
 
 
@@ -405,32 +405,3 @@ function getAppPackageJsonData(context: BuildContext) {
 
   return appPackageJsonData;
 }
-
-
-const BUILD_DIR = 'build';
-const SRC_DIR = 'src';
-const TMP_DIR = '.tmp';
-const WWW_DIR = 'www';
-const WWW_INDEX_FILENAME = 'index.html';
-
-const ENV_VAR_ROOT_DIR = 'IONIC_ROOT_DIR';
-const ENV_VAR_SRC_DIR = 'IONIC_SRC_DIR';
-const ENV_VAR_WWW_DIR = 'IONIC_WWW_DIR';
-const ENV_VAR_BUILD_DIR = 'IONIC_BUILD_DIR';
-const ENV_VAR_APP_SCRIPTS_DIR = 'IONIC_APP_SCRIPTS_DIR';
-const ENV_VAR_GENERATE_SOURCE_MAP = 'IONIC_GENERATE_SOURCE_MAP';
-const ENV_VAR_SOURCE_MAP_TYPE = 'IONIC_SOURCE_MAP_TYPE';
-const ENV_TS_CONFIG = 'IONIC_TS_CONFIG';
-const ENV_APP_ENTRY_POINT = 'IONIC_APP_ENTRY_POINT';
-const ENV_GLOB_UTIL = 'IONIC_GLOB_UTIL';
-const ENV_CLEAN_BEFORE_COPY = 'IONIC_CLEAN_BEFORE_COPY';
-const ENV_CLOSURE_JAR = 'IONIC_CLOSURE_JAR';
-const ENV_OUTPUT_JS_FILE_NAME = 'IONIC_OUTPUT_JS_FILE_NAME';
-const ENV_OUTPUT_JS_MAP_FILE_NAME = 'IONIC_OUTPUT_JS_MAP_FILE_NAME';
-const ENV_OUTPUT_CSS_FILE_NAME = 'IONIC_OUTPUT_CSS_FILE_NAME';
-const ENV_OUTPUT_CSS_MAP_FILE_NAME = 'IONIC_OUTPUT_CSS_MAP_FILE_NAME';
-const ENV_WEBPACK_FACTORY = 'IONIC_WEBPACK_FACTORY';
-const ENV_WEBPACK_LOADER = 'IONIC_WEBPACK_LOADER';
-
-export const BUNDLER_ROLLUP = 'rollup';
-export const BUNDLER_WEBPACK = 'webpack';
diff --git a/src/util/constants.ts b/src/util/constants.ts
index 3b382e5e..1433be2d 100644
--- a/src/util/constants.ts
+++ b/src/util/constants.ts
@@ -6,3 +6,30 @@ export const DIRECTORY_DELETE_EVENT = 'unlinkDir';
 
 export const SOURCE_MAP_TYPE_CHEAP = 'eval';
 export const SOURCE_MAP_TYPE_EXPENSIVE = 'source-map';
+
+export const BUILD_DIR = 'build';
+export const SRC_DIR = 'src';
+export const WWW_DIR = 'www';
+export const WWW_INDEX_FILENAME = 'index.html';
+
+export const ENV_VAR_ROOT_DIR = 'IONIC_ROOT_DIR';
+export const ENV_VAR_SRC_DIR = 'IONIC_SRC_DIR';
+export const ENV_VAR_WWW_DIR = 'IONIC_WWW_DIR';
+export const ENV_VAR_BUILD_DIR = 'IONIC_BUILD_DIR';
+export const ENV_VAR_APP_SCRIPTS_DIR = 'IONIC_APP_SCRIPTS_DIR';
+export const ENV_VAR_GENERATE_SOURCE_MAP = 'IONIC_GENERATE_SOURCE_MAP';
+export const ENV_VAR_SOURCE_MAP_TYPE = 'IONIC_SOURCE_MAP_TYPE';
+export const ENV_TS_CONFIG = 'IONIC_TS_CONFIG';
+export const ENV_APP_ENTRY_POINT = 'IONIC_APP_ENTRY_POINT';
+export const ENV_GLOB_UTIL = 'IONIC_GLOB_UTIL';
+export const ENV_CLEAN_BEFORE_COPY = 'IONIC_CLEAN_BEFORE_COPY';
+export const ENV_CLOSURE_JAR = 'IONIC_CLOSURE_JAR';
+export const ENV_OUTPUT_JS_FILE_NAME = 'IONIC_OUTPUT_JS_FILE_NAME';
+export const ENV_OUTPUT_JS_MAP_FILE_NAME = 'IONIC_OUTPUT_JS_MAP_FILE_NAME';
+export const ENV_OUTPUT_CSS_FILE_NAME = 'IONIC_OUTPUT_CSS_FILE_NAME';
+export const ENV_OUTPUT_CSS_MAP_FILE_NAME = 'IONIC_OUTPUT_CSS_MAP_FILE_NAME';
+export const ENV_WEBPACK_FACTORY = 'IONIC_WEBPACK_FACTORY';
+export const ENV_WEBPACK_LOADER = 'IONIC_WEBPACK_LOADER';
+
+export const BUNDLER_ROLLUP = 'rollup';
+export const BUNDLER_WEBPACK = 'webpack';
\ No newline at end of file
diff --git a/src/util/helpers.ts b/src/util/helpers.ts
index 82e70d08..73d8b99f 100644
--- a/src/util/helpers.ts
+++ b/src/util/helpers.ts
@@ -116,7 +116,7 @@ export function readFileAsync(filePath: string): Promise<string> {
   });
 }
 
-export function unlinkAsync(filePath: string): Promise<void> {
+export function unlinkAsync(filePath: string): Promise<any> {
   return new Promise((resolve, reject) => {
     unlink(filePath, (err: Error) => {
       if (err) {
@@ -125,9 +125,11 @@ export function unlinkAsync(filePath: string): Promise<void> {
       return resolve();
     });
   });
+
+
 }
 
-export function rimRafAsync(directoryPath: string) {
+export function rimRafAsync(directoryPath: string): Promise<null> {
   return new Promise((resolve, reject) => {
     remove(directoryPath, (err: Error) => {
       if (err) {
@@ -138,7 +140,7 @@ export function rimRafAsync(directoryPath: string) {
   });
 }
 
-export function copyFileAsync(srcPath: string, destPath: string) {
+export function copyFileAsync(srcPath: string, destPath: string): Promise<any> {
   return new Promise((resolve, reject) => {
     const writeStream = createWriteStream(destPath);
 
@@ -206,4 +208,4 @@ export function stringSplice(source: string, startIndex: number, numToDelete: nu
 
 export function toUnixPath(filePath: string) {
   return filePath.replace(/\\/g, '/');
-}
\ No newline at end of file
+}
diff --git a/src/watch.ts b/src/watch.ts
index a50f8f59..d3a8000e 100644
--- a/src/watch.ts
+++ b/src/watch.ts
@@ -53,7 +53,7 @@ export function watch(context?: BuildContext, configFile?: string) {
 function startWatchers(context: BuildContext, configFile: string) {
   const watchConfig: WatchConfig = fillConfigDefaults(configFile, taskInfo.defaultConfigFile);
 
-  const promises: Promise<void>[] = [];
+  const promises: Promise<any>[] = [];
   Object.keys(watchConfig).forEach((key) => {
     promises.push(startWatcher(key, watchConfig[key], context));
   });
diff --git a/src/webpack.ts b/src/webpack.ts
index 82b33f6b..d6182ab8 100644
--- a/src/webpack.ts
+++ b/src/webpack.ts
@@ -21,7 +21,7 @@ const INCREMENTAL_BUILD_SUCCESS = 'incremental_build_success';
  * To mitigate this, store pending "webpack watch"/bundle update promises in this array and only resolve the
  * the most recent one. reject all others at that time with an IgnorableError.
  */
-let pendingPromises: Promise<void>[] = [];
+let pendingPromises: Promise<any>[] = [];
 
 export function webpack(context: BuildContext, configFile: string) {
   configFile = getUserConfigFile(context, taskInfo, configFile);
@@ -40,7 +40,7 @@ export function webpack(context: BuildContext, configFile: string) {
 }
 
 
-export function webpackUpdate(changedFiles: ChangedFile[], context: BuildContext, configFile: string) {
+export function webpackUpdate(changedFiles: ChangedFile[], context: BuildContext, configFile?: string) {
   const logger = new Logger('webpack update');
   const webpackConfig = getWebpackConfig(context, configFile);
   Logger.debug('webpackUpdate: Starting Incremental Build');
@@ -68,7 +68,7 @@ export function webpackUpdate(changedFiles: ChangedFile[], context: BuildContext
 export function webpackWorker(context: BuildContext, configFile: string): Promise<any> {
   const webpackConfig = getWebpackConfig(context, configFile);
 
-  let promise: Promise<void> = null;
+  let promise: Promise<any> = null;
   if (context.isWatch) {
     promise = runWebpackIncrementalBuild(!context.webpackWatch, context, webpackConfig);
   } else {
@@ -140,7 +140,7 @@ function runWebpackIncrementalBuild(initializeWatch: boolean, context: BuildCont
   return promise;
 }
 
-function handleWebpackBuildFailure(resolve: Function, reject: Function, error: Error, promise: Promise<void>, pendingPromises: Promise<void>[]) {
+function handleWebpackBuildFailure(resolve: Function, reject: Function, error: Error, promise: Promise<any>, pendingPromises: Promise<void>[]) {
   // check if the promise if the last promise in the list of pending promises
   if (pendingPromises.length > 0 && pendingPromises[pendingPromises.length - 1] === promise) {
     // reject this one with a build error
@@ -151,7 +151,7 @@ function handleWebpackBuildFailure(resolve: Function, reject: Function, error: E
   reject(new IgnorableError());
 }
 
-function handleWebpackBuildSuccess(resolve: Function, reject: Function, stats: any, promise: Promise<void>, pendingPromises: Promise<void>[]) {
+function handleWebpackBuildSuccess(resolve: Function, reject: Function, stats: any, promise: Promise<any>, pendingPromises: Promise<void>[]) {
   // check if the promise if the last promise in the list of pending promises
   if (pendingPromises.length > 0 && pendingPromises[pendingPromises.length - 1] === promise) {
     Logger.debug('handleWebpackBuildSuccess: Resolving with Webpack data');
@@ -186,7 +186,8 @@ export function getWebpackConfig(context: BuildContext, configFile: string): Web
 }
 
 
-export function getOutputDest(context: BuildContext, webpackConfig: WebpackConfig) {
+export function getOutputDest(context: BuildContext) {
+  const webpackConfig = getWebpackConfig(context, null);
   return join(webpackConfig.output.path, webpackConfig.output.filename);
 }