diff --git a/examples/learning/helloworld.html b/examples/learning/helloworld.html
index 564c2ce17..685cccd76 100644
--- a/examples/learning/helloworld.html
+++ b/examples/learning/helloworld.html
@@ -13,7 +13,7 @@
 <!-- for legacy browsers add compatibility.js -->
 <!--<script src="../compatibility.js"></script>-->
 
-<script src="../../build/pdf.js"></script>
+<script src="../../build/generic/build/pdf.js"></script>
 
 <script id="script">
   //
@@ -32,7 +32,7 @@
   //
   // The workerSrc property shall be specified.
   //
-  PDFJS.workerSrc = '../../build/pdf.worker.js';
+  PDFJS.workerSrc = '../../build/generic/build/pdf.worker.js';
 
   //
   // Asynchronous download PDF
diff --git a/examples/learning/helloworld64.html b/examples/learning/helloworld64.html
index ea11ef932..891c2351d 100644
--- a/examples/learning/helloworld64.html
+++ b/examples/learning/helloworld64.html
@@ -13,7 +13,7 @@
 <!-- for legacy browsers we need to use compatibility.js -->
 <script src="../../web/compatibility.js"></script>
 
-<script src="../../build/pdf.js"></script>
+<script src="../../build/generic/build/pdf.js"></script>
 
 <script id="script">
   // atob() is used to convert base64 encoded PDF to binary-like data.
@@ -43,7 +43,7 @@
   //
   // The workerSrc property shall be specified.
   //
-  PDFJS.workerSrc = '../../build/pdf.worker.js';
+  PDFJS.workerSrc = '../../build/generic/build/pdf.worker.js';
 
   // Opening PDF by passing its binary data as a string. It is still preferable
   // to use Uint8Array, but string or array-like structure will work too.
diff --git a/examples/learning/prevnext.html b/examples/learning/prevnext.html
index 0da467b79..7513cddf4 100644
--- a/examples/learning/prevnext.html
+++ b/examples/learning/prevnext.html
@@ -22,7 +22,7 @@
 <!-- for legacy browsers add compatibility.js -->
 <!--<script src="../compatibility.js"></script>-->
 
-<script src="../../build/pdf.js"></script>
+<script src="../../build/generic/build/pdf.js"></script>
 
 <script id="script">
   //
@@ -44,7 +44,7 @@
   // pdf.js's one, or the pdf.js is executed via eval(), the workerSrc property
   // shall be specified.
   //
-  // PDFJS.workerSrc = '../../build/pdf.worker.js';
+  // PDFJS.workerSrc = '../../build/generic/build/pdf.worker.js';
 
   var pdfDoc = null,
       pageNum = 1,
diff --git a/examples/text-only/index.html b/examples/text-only/index.html
index 97a38bfa1..df1d607dd 100644
--- a/examples/text-only/index.html
+++ b/examples/text-only/index.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
+    <meta charset="UTF-8">
     <title>Text-only PDF.js example</title>
     <script src="../../build/generic/build/pdf.js"></script>
     <script src="pdf2svg.js"></script>
diff --git a/examples/text-only/pdf2svg.js b/examples/text-only/pdf2svg.js
index 9cdd720bc..c808db44c 100644
--- a/examples/text-only/pdf2svg.js
+++ b/examples/text-only/pdf2svg.js
@@ -18,7 +18,7 @@ var PAGE_NUMBER = 1;
 var PAGE_SCALE = 1.5;
 var SVG_NS = 'http://www.w3.org/2000/svg';
 
-PDFJS.workerSrc = '../../build/pdf.worker.js';
+PDFJS.workerSrc = '../../build/generic/build/pdf.worker.js';
 
 function buildSVG(viewport, textContent) {
   // Building SVG with size of the viewport (for simplicity)
diff --git a/gulpfile.js b/gulpfile.js
index 2667d1e78..81de4ff3c 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -20,6 +20,7 @@
 var fs = require('fs');
 var gulp = require('gulp');
 var gutil = require('gulp-util');
+var rename = require('gulp-rename');
 var mkdirp = require('mkdirp');
 var rimraf = require('rimraf');
 var runSequence = require('run-sequence');
@@ -34,10 +35,19 @@ var BUILD_DIR = 'build/';
 var JSDOC_DIR = 'jsdoc/';
 var L10N_DIR = 'l10n/';
 var TEST_DIR = 'test/';
+var EXTENSION_SRC_DIR = 'extensions/';
 
-var makeFile = require('./make.js');
-var stripCommentHeaders = makeFile.stripCommentHeaders;
-var builder = makeFile.builder;
+var GENERIC_DIR = BUILD_DIR + 'generic/';
+var COMPONENTS_DIR = BUILD_DIR + 'components/';
+var SINGLE_FILE_DIR = BUILD_DIR + 'singlefile/';
+var MINIFIED_DIR = BUILD_DIR + 'minified/';
+var FIREFOX_BUILD_DIR = BUILD_DIR + 'firefox/';
+var COMMON_WEB_FILES = [
+  'web/images/*.{png,svg,gif,cur}',
+  'web/debugger.js'
+];
+
+var builder = require('./external/builder/builder.js');
 
 var CONFIG_FILE = 'pdfjs.config';
 var config = JSON.parse(fs.readFileSync(CONFIG_FILE).toString());
@@ -76,6 +86,16 @@ function stripUMDHeaders(content) {
   return content.replace(reg, '');
 }
 
+function stripCommentHeaders(content) {
+  var notEndOfComment = '(?:[^*]|\\*(?!/))+';
+  var reg = new RegExp(
+    '\n/\\* Copyright' + notEndOfComment + '\\*/\\s*' +
+    '(?:/\\*' + notEndOfComment + '\\*/\\s*|//(?!#).*\n\\s*)*' +
+    '\\s*\'use strict\';', 'g');
+  content = content.replace(reg, '');
+  return content;
+}
+
 function checkChromePreferencesFile(chromePrefsPath, webPrefsPath) {
   var chromePrefs = JSON.parse(fs.readFileSync(chromePrefsPath).toString());
   var chromePrefsKeys = Object.keys(chromePrefs.properties);
@@ -296,6 +316,14 @@ function checkDir(path) {
   }
 }
 
+function getTempFile(prefix, suffix) {
+  mkdirp.sync(BUILD_DIR + 'tmp/');
+  var bytes = require('crypto').randomBytes(6).toString('hex');
+  var path = BUILD_DIR + 'tmp/' + prefix + bytes + suffix;
+  fs.writeFileSync(path, '');
+  return path;
+}
+
 function createTestSource(testsName) {
   var source = stream.Readable({ objectMode: true });
   source._read = function () {
@@ -484,53 +512,326 @@ gulp.task('cmaps', function () {
   compressCmaps(CMAP_INPUT, VIEWER_CMAP_OUTPUT, true);
 });
 
-gulp.task('bundle-firefox', ['buildnumber'], function () {
-  var defines = builder.merge(DEFINES, {FIREFOX: true});
-  return streamqueue({ objectMode: true },
-    createBundle(defines), createWebBundle(defines))
-    .pipe(gulp.dest(BUILD_DIR));
+gulp.task('bundle', ['buildnumber'], function () {
+  return createBundle(DEFINES).pipe(gulp.dest(BUILD_DIR));
 });
 
-gulp.task('bundle-mozcentral', ['buildnumber'], function () {
-  var defines = builder.merge(DEFINES, {MOZCENTRAL: true});
-  return streamqueue({ objectMode: true },
-    createBundle(defines), createWebBundle(defines))
-    .pipe(gulp.dest(BUILD_DIR));
+function preprocessCSS(source, mode, defines, cleanup) {
+  var outName = getTempFile('~preprocess', '.css');
+  var setup = {
+    defines: defines,
+    copy: [],
+    preprocess: [],
+    preprocessCSS: [
+      [mode, source, outName]
+    ]
+  };
+  builder.build(setup);
+  var out = fs.readFileSync(outName).toString();
+  fs.unlinkSync(outName);
+  if (cleanup) {
+    // Strip out all license headers in the middle.
+    var reg = /\n\/\* Copyright(.|\n)*?Mozilla Foundation(.|\n)*?\*\//g;
+    out = out.replace(reg, '');
+  }
+
+  var i = source.lastIndexOf('/');
+  return createStringSource(source.substr(i + 1), out);
+}
+
+function preprocessHTML(source, defines) {
+  var outName = getTempFile('~preprocess', '.html');
+  var setup = {
+    defines: defines,
+    copy: [],
+    preprocess: [
+      [source, outName]
+    ],
+    preprocessCSS: []
+  };
+  builder.build(setup);
+  var out = fs.readFileSync(outName).toString();
+  fs.unlinkSync(outName);
+
+  var i = source.lastIndexOf('/');
+  return createStringSource(source.substr(i + 1), out);
+}
+
+function preprocessJS(source, defines, cleanup) {
+  var outName = getTempFile('~preprocess', '.js');
+  var setup = {
+    defines: defines,
+    copy: [],
+    preprocess: [
+      [source, outName]
+    ],
+    preprocessCSS: []
+  };
+  builder.build(setup);
+  var out = fs.readFileSync(outName).toString();
+  fs.unlinkSync(outName);
+  if (cleanup) {
+    out = stripCommentHeaders(out);
+  }
+
+  var i = source.lastIndexOf('/');
+  return createStringSource(source.substr(i + 1), out);
+}
+
+// Builds the generic production viewer that should be compatible with most
+// modern HTML5 browsers.
+gulp.task('generic', ['buildnumber', 'locale'], function () {
+  console.log();
+  console.log('### Creating generic viewer');
+  var defines = builder.merge(DEFINES, {GENERIC: true});
+
+  rimraf.sync(GENERIC_DIR);
+
+  return merge([
+    createBundle(defines).pipe(gulp.dest(GENERIC_DIR + 'build')),
+    createWebBundle(defines).pipe(gulp.dest(GENERIC_DIR + 'web')),
+    gulp.src(COMMON_WEB_FILES, {base: 'web/'})
+        .pipe(gulp.dest(GENERIC_DIR + 'web')),
+    gulp.src('LICENSE').pipe(gulp.dest(GENERIC_DIR)),
+    gulp.src([
+      'external/webL10n/l10n.js',
+      'web/compatibility.js'
+    ]).pipe(gulp.dest(GENERIC_DIR + 'web')),
+    gulp.src([
+      'web/locale/*/viewer.properties',
+      'web/locale/locale.properties'
+    ], {base: 'web/'}).pipe(gulp.dest(GENERIC_DIR + 'web')),
+    gulp.src(['external/bcmaps/*.bcmap', 'external/bcmaps/LICENSE'],
+             {base: 'external/bcmaps'})
+        .pipe(gulp.dest(GENERIC_DIR + 'web/cmaps')),
+    preprocessHTML('web/viewer.html', defines)
+        .pipe(gulp.dest(GENERIC_DIR + 'web')),
+    preprocessCSS('web/viewer.css', 'generic', defines, true)
+        .pipe(gulp.dest(GENERIC_DIR + 'web')),
+
+    gulp.src('web/compressed.tracemonkey-pldi-09.pdf')
+        .pipe(gulp.dest(GENERIC_DIR + 'web')),
+  ]);
 });
 
-gulp.task('bundle-chromium', ['buildnumber'], function () {
-  var defines = builder.merge(DEFINES, {CHROME: true});
-  return streamqueue({ objectMode: true },
-    createBundle(defines), createWebBundle(defines))
-    .pipe(gulp.dest(BUILD_DIR));
+gulp.task('components', ['buildnumber'], function () {
+  console.log();
+  console.log('### Creating generic components');
+  var defines = builder.merge(DEFINES, {COMPONENTS: true, GENERIC: true});
+
+  rimraf.sync(COMPONENTS_DIR);
+
+  var COMPONENTS_IMAGES = [
+    'web/images/annotation-*.svg',
+    'web/images/loading-icon.gif',
+    'web/images/shadow.png',
+    'web/images/texture.png',
+  ];
+
+  return merge([
+    createWebBundle(defines).pipe(gulp.dest(COMPONENTS_DIR)),
+    gulp.src(COMPONENTS_IMAGES).pipe(gulp.dest(COMPONENTS_DIR + 'images')),
+    gulp.src('web/compatibility.js').pipe(gulp.dest(COMPONENTS_DIR)),
+    preprocessCSS('web/pdf_viewer.css', 'components', defines, true)
+        .pipe(gulp.dest(COMPONENTS_DIR)),
+  ]);
 });
 
-gulp.task('bundle-singlefile', ['buildnumber'], function () {
+gulp.task('singlefile', ['buildnumber'], function () {
+  console.log();
+  console.log('### Creating singlefile build');
   var defines = builder.merge(DEFINES, {SINGLE_FILE: true});
-  return createBundle(defines).pipe(gulp.dest(BUILD_DIR));
-});
 
-gulp.task('bundle-generic', ['buildnumber'], function () {
-  var defines = builder.merge(DEFINES, {GENERIC: true});
-  return streamqueue({ objectMode: true },
-    createBundle(defines), createWebBundle(defines))
-    .pipe(gulp.dest(BUILD_DIR));
+  var SINGLE_FILE_BUILD_DIR = SINGLE_FILE_DIR + 'build/';
+
+  rimraf.sync(SINGLE_FILE_DIR);
+
+  return createBundle(defines).pipe(gulp.dest(SINGLE_FILE_BUILD_DIR));
 });
 
-gulp.task('bundle-minified', ['buildnumber'], function () {
+gulp.task('minified-pre', ['buildnumber', 'locale'], function () {
+  console.log();
+  console.log('### Creating minified viewer');
   var defines = builder.merge(DEFINES, {MINIFIED: true, GENERIC: true});
-  return streamqueue({ objectMode: true },
-    createBundle(defines), createWebBundle(defines))
-    .pipe(gulp.dest(BUILD_DIR));
+
+  rimraf.sync(MINIFIED_DIR);
+
+  return merge([
+    createBundle(defines).pipe(gulp.dest(MINIFIED_DIR + 'build')),
+    createWebBundle(defines).pipe(gulp.dest(MINIFIED_DIR + 'web')),
+    gulp.src(COMMON_WEB_FILES, {base: 'web/'})
+        .pipe(gulp.dest(MINIFIED_DIR + 'web')),
+    gulp.src([
+      'web/locale/*/viewer.properties',
+      'web/locale/locale.properties'
+    ], {base: 'web/'}).pipe(gulp.dest(MINIFIED_DIR + 'web')),
+    gulp.src(['external/bcmaps/*.bcmap', 'external/bcmaps/LICENSE'],
+             {base: 'external/bcmaps'})
+        .pipe(gulp.dest(MINIFIED_DIR + 'web/cmaps')),
+
+    preprocessHTML('web/viewer.html', defines)
+        .pipe(gulp.dest(MINIFIED_DIR + 'web')),
+    preprocessCSS('web/viewer.css', 'minified', defines, true)
+        .pipe(gulp.dest(MINIFIED_DIR + 'web')),
+
+    gulp.src('web/compressed.tracemonkey-pldi-09.pdf')
+        .pipe(gulp.dest(MINIFIED_DIR + 'web')),
+  ]);
 });
 
-gulp.task('bundle-components', ['buildnumber'], function () {
-  var defines = builder.merge(DEFINES, {COMPONENTS: true, GENERIC: true});
-  return createWebBundle(defines).pipe(gulp.dest(BUILD_DIR));
+gulp.task('firefox-pre', ['buildnumber', 'locale'], function () {
+  console.log();
+  console.log('### Building Firefox extension');
+  var defines = builder.merge(DEFINES, {FIREFOX: true});
+
+  var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/',
+      FIREFOX_EXTENSION_DIR = 'extensions/firefox/',
+      FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/';
+
+  // Clear out everything in the firefox extension build directory
+  rimraf.sync(FIREFOX_BUILD_DIR);
+
+  return merge([
+    createBundle(defines).pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'build')),
+    createWebBundle(defines).pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'web')),
+    gulp.src(COMMON_WEB_FILES, {base: 'web/'})
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'web')),
+    gulp.src(FIREFOX_EXTENSION_DIR + 'locale/**/*.properties',
+             {base: FIREFOX_EXTENSION_DIR})
+        .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
+    gulp.src(['external/bcmaps/*.bcmap', 'external/bcmaps/LICENSE'],
+             {base: 'external/bcmaps'})
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'web/cmaps')),
+
+    preprocessHTML('web/viewer.html', defines)
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'web')),
+    preprocessCSS('web/viewer.css', 'firefox', defines, true)
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'web')),
+
+    gulp.src(FIREFOX_CONTENT_DIR + 'PdfJs-stub.jsm')
+        .pipe(rename('PdfJs.jsm'))
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
+    gulp.src(FIREFOX_CONTENT_DIR + 'PdfJsTelemetry-addon.jsm')
+        .pipe(rename('PdfJsTelemetry.jsm'))
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + '**/*.{rdf,png,manifest}',
+             {base: FIREFOX_EXTENSION_DIR})
+        .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + 'chrome/content.js',
+             {base: FIREFOX_EXTENSION_DIR})
+        .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
+    gulp.src('LICENSE').pipe(gulp.dest(FIREFOX_BUILD_DIR)),
+
+    gulp.src(FIREFOX_EXTENSION_DIR + 'tools/l10n.js')
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + '/web')),
+
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm', defines, true)
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfJsNetwork.jsm', defines, true)
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsContentUtils.jsm', defines, true)
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsChromeUtils.jsm', defines, true)
+        .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
+    preprocessJS(FIREFOX_EXTENSION_DIR + 'bootstrap.js', defines, true)
+        .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
+  ]);
 });
 
-gulp.task('bundle', ['buildnumber'], function () {
-  return createBundle(DEFINES).pipe(gulp.dest(BUILD_DIR));
+gulp.task('mozcentral-pre', ['buildnumber', 'locale'], function () {
+  console.log();
+  console.log('### Building mozilla-central extension');
+  var defines = builder.merge(DEFINES, {MOZCENTRAL: true});
+
+  var MOZCENTRAL_DIR = BUILD_DIR + 'mozcentral/',
+      MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + 'browser/extensions/pdfjs/',
+      MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + 'content/',
+      FIREFOX_EXTENSION_DIR = 'extensions/firefox/',
+      MOZCENTRAL_L10N_DIR = MOZCENTRAL_DIR + 'browser/locales/en-US/pdfviewer/',
+      FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/';
+
+  // Clear out everything in the firefox extension build directory
+  rimraf.sync(MOZCENTRAL_DIR);
+
+  return merge([
+    createBundle(defines).pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'build')),
+    createWebBundle(defines).pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'web')),
+    gulp.src(COMMON_WEB_FILES, {base: 'web/'})
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'web')),
+    gulp.src(['external/bcmaps/*.bcmap', 'external/bcmaps/LICENSE'],
+             {base: 'external/bcmaps'})
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'web/cmaps')),
+
+    preprocessHTML('web/viewer.html', defines)
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'web')),
+    preprocessCSS('web/viewer.css', 'mozcentral', defines, true)
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'web')),
+
+    gulp.src(FIREFOX_CONTENT_DIR + 'PdfJsTelemetry.jsm')
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + 'chrome-mozcentral.manifest')
+        .pipe(rename('chrome.manifest'))
+        .pipe(gulp.dest(MOZCENTRAL_EXTENSION_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + 'locale/en-US/*.properties',
+             {base: FIREFOX_EXTENSION_DIR})
+        .pipe(gulp.dest(MOZCENTRAL_L10N_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + 'README.mozilla')
+        .pipe(gulp.dest(MOZCENTRAL_EXTENSION_DIR)),
+    gulp.src('LICENSE').pipe(gulp.dest(MOZCENTRAL_EXTENSION_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + 'tools/l10n.js')
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + '/web')),
+
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfJs.jsm', defines, true)
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm', defines, true)
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfJsNetwork.jsm', defines, true)
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsContentUtils.jsm', defines, true)
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
+    preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsChromeUtils.jsm', defines, true)
+        .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
+  ]);
+});
+
+gulp.task('chromium-pre', ['buildnumber', 'locale'], function () {
+  console.log();
+  console.log('### Building Chromium extension');
+  var defines = builder.merge(DEFINES, {CHROME: true});
+
+  var CHROME_BUILD_DIR = BUILD_DIR + '/chromium/',
+      CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/';
+
+  // Clear out everything in the chrome extension build directory
+  rimraf.sync(CHROME_BUILD_DIR);
+  return merge([
+    createBundle(defines).pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'build')),
+    createWebBundle(defines).pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
+    gulp.src(COMMON_WEB_FILES, {base: 'web/'})
+        .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
+
+    gulp.src('external/webL10n/l10n.js')
+        .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
+    gulp.src([
+      'web/locale/*/viewer.properties',
+      'web/locale/locale.properties'
+    ], {base: 'web/'}).pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
+    gulp.src(['external/bcmaps/*.bcmap', 'external/bcmaps/LICENSE'],
+             {base: 'external/bcmaps'})
+        .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web/cmaps')),
+
+    preprocessHTML('web/viewer.html', defines)
+        .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
+    preprocessCSS('web/viewer.css', 'chrome', defines, true)
+        .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
+
+    gulp.src('LICENSE').pipe(gulp.dest(CHROME_BUILD_DIR)),
+    gulp.src('extensions/chromium/*.{json,html,js,css,png}')
+        .pipe(gulp.dest(CHROME_BUILD_DIR)),
+    gulp.src('extensions/chromium/**/*.{json,html,js,css,png}',
+             {base: 'extensions/chromium/'})
+        .pipe(gulp.dest(CHROME_BUILD_DIR)),
+  ]);
 });
 
 gulp.task('jsdoc', function (done) {
@@ -723,6 +1024,8 @@ gulp.task('importl10n', function(done) {
 });
 
 // Getting all shelljs registered tasks and register them with gulp
+require('./make.js');
+
 var gulpContext = false;
 for (var taskName in global.target) {
   if (taskName in gulp.tasks) {
diff --git a/make.js b/make.js
index c6bf6edd9..50f35921e 100644
--- a/make.js
+++ b/make.js
@@ -24,7 +24,6 @@ try {
   return;
 }
 
-var builder = require('./external/builder/builder.js');
 var fs = require('fs');
 
 var CONFIG_FILE = 'pdfjs.config';
@@ -33,15 +32,10 @@ var config = JSON.parse(fs.readFileSync(CONFIG_FILE));
 var ROOT_DIR = __dirname + '/', // absolute path to project's root
     BUILD_DIR = 'build/',
     SRC_DIR = 'src/',
-    BUILD_TARGET = BUILD_DIR + 'pdf.js',
-    BUILD_WORKER_TARGET = BUILD_DIR + 'pdf.worker.js',
-    BUILD_TARGETS = [BUILD_TARGET, BUILD_WORKER_TARGET],
     FIREFOX_BUILD_DIR = BUILD_DIR + '/firefox/',
     CHROME_BUILD_DIR = BUILD_DIR + '/chromium/',
     JSDOC_DIR = BUILD_DIR + 'jsdoc',
     EXTENSION_SRC_DIR = 'extensions/',
-    FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/',
-    LOCALE_SRC_DIR = 'l10n/',
     GH_PAGES_DIR = BUILD_DIR + 'gh-pages/',
     GENERIC_DIR = BUILD_DIR + 'generic/',
     MINIFIED_DIR = BUILD_DIR + 'minified/',
@@ -56,18 +50,6 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root
     MOZCENTRAL_STREAM_CONVERTER2_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2292',
     FIREFOX_STREAM_CONVERTER2_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb2';
 
-var DEFINES = {
-  PRODUCTION: true,
-  // The main build targets:
-  GENERIC: false,
-  FIREFOX: false,
-  MOZCENTRAL: false,
-  CHROME: false,
-  MINIFIED: false,
-  SINGLE_FILE: false,
-  COMPONENTS: false
-};
-
 function getCurrentVersion() {
   // The 'build/version.json' file is created by 'buildnumber' task.
   return JSON.parse(fs.readFileSync(ROOT_DIR + 'build/version.json').toString())
@@ -95,103 +77,17 @@ target.all = function() {
 // Production stuff
 //
 
-// Files that need to be included in every build.
-var COMMON_WEB_FILES =
-      ['web/images',
-       'web/debugger.js'],
-    COMMON_WEB_FILES_PREPROCESS =
-      ['web/viewer.html'],
-    COMMON_FIREFOX_FILES_PREPROCESS =
-      [FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm',
-       FIREFOX_CONTENT_DIR + 'PdfJsNetwork.jsm',
-       FIREFOX_CONTENT_DIR + 'PdfjsContentUtils.jsm',
-       FIREFOX_CONTENT_DIR + 'PdfjsChromeUtils.jsm'];
 //
 // make generic
 // Builds the generic production viewer that should be compatible with most
 // modern HTML5 browsers.
 //
 target.generic = function() {
-  execGulp('bundle-generic');
-
-  target.locale();
-
-  cd(ROOT_DIR);
-  echo();
-  echo('### Creating generic viewer');
-
-  rm('-rf', GENERIC_DIR);
-  mkdir('-p', GENERIC_DIR);
-  mkdir('-p', GENERIC_DIR + BUILD_DIR);
-  mkdir('-p', GENERIC_DIR + '/web');
-  mkdir('-p', GENERIC_DIR + '/web/cmaps');
-
-  var defines = builder.merge(DEFINES, {GENERIC: true});
-
-  var setup = {
-    defines: defines,
-    copy: [
-      [BUILD_TARGETS, GENERIC_DIR + BUILD_DIR],
-      [BUILD_DIR + 'viewer.js', GENERIC_DIR + '/web'],
-      [COMMON_WEB_FILES, GENERIC_DIR + '/web'],
-      ['LICENSE', GENERIC_DIR],
-      ['external/webL10n/l10n.js', GENERIC_DIR + '/web'],
-      ['web/compatibility.js', GENERIC_DIR + '/web'],
-      ['web/compressed.tracemonkey-pldi-09.pdf', GENERIC_DIR + '/web'],
-      ['external/bcmaps/*', GENERIC_DIR + '/web/cmaps/'],
-      ['web/locale', GENERIC_DIR + '/web']
-    ],
-    preprocess: [
-      [COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web']
-    ],
-    preprocessCSS: [
-      ['generic', 'web/viewer.css',
-       GENERIC_DIR + '/web/viewer.css']
-    ]
-  };
-  builder.build(setup);
-
-  cleanupJSSource(GENERIC_DIR + '/build/pdf.js');
-  cleanupJSSource(GENERIC_DIR + '/web/viewer.js');
-  cleanupCSSSource(GENERIC_DIR + '/web/viewer.css');
+  execGulp('generic');
 };
 
 target.components = function() {
-  execGulp('bundle-components');
-
-  cd(ROOT_DIR);
-  echo();
-  echo('### Creating generic components');
-
-  rm('-rf', COMPONENTS_DIR);
-  mkdir('-p', COMPONENTS_DIR);
-  mkdir('-p', COMPONENTS_DIR + 'images');
-
-  var defines = builder.merge(DEFINES, {COMPONENTS: true, GENERIC: true});
-
-  var COMPONENTS_IMAGES = [
-    'web/images/annotation-*.svg',
-    'web/images/loading-icon.gif',
-    'web/images/shadow.png',
-    'web/images/texture.png',
-  ];
-
-  var setup = {
-    defines: defines,
-    copy: [
-      [BUILD_DIR + 'pdf_viewer.js', COMPONENTS_DIR],
-      [COMPONENTS_IMAGES, COMPONENTS_DIR + 'images'],
-      ['web/compatibility.js', COMPONENTS_DIR],
-    ],
-    preprocess: [],
-    preprocessCSS: [
-      ['components', 'web/pdf_viewer.css', COMPONENTS_DIR + 'pdf_viewer.css'],
-    ]
-  };
-  builder.build(setup);
-
-  cleanupJSSource(COMPONENTS_DIR + 'pdf_viewer.js');
-  cleanupCSSSource(COMPONENTS_DIR + 'pdf_viewer.css');
+  execGulp('components');
 };
 
 target.jsdoc = function() {
@@ -400,93 +296,16 @@ target.bundle = function(args) {
 // flags the script loader to not attempt to load the separate worker JS file.
 //
 target.singlefile = function() {
-  cd(ROOT_DIR);
-  echo();
-  echo('### Creating singlefile build');
-
-  var SINGLE_FILE_BUILD_DIR = SINGLE_FILE_DIR + 'build/';
-
-  execGulp('bundle-singlefile');
-
-  cd(ROOT_DIR);
-
-  rm('-rf', SINGLE_FILE_DIR);
-  mkdir('-p', SINGLE_FILE_DIR);
-  mkdir('-p', SINGLE_FILE_BUILD_DIR);
-
-  cp(BUILD_DIR + 'pdf.combined.js', SINGLE_FILE_BUILD_DIR);
+  execGulp('singlefile');
 };
 
-function stripCommentHeaders(content) {
-  var notEndOfComment = '(?:[^*]|\\*(?!/))+';
-  var reg = new RegExp(
-    '\n/\\* Copyright' + notEndOfComment + '\\*/\\s*' +
-    '(?:/\\*' + notEndOfComment + '\\*/\\s*|//(?!#).*\n\\s*)*' +
-    '\\s*\'use strict\';', 'g');
-  content = content.replace(reg, '');
-  return content;
-}
-
-function cleanupJSSource(file) {
-  var content = cat(file);
-
-  content = stripCommentHeaders(content);
-
-  content.to(file);
-}
-
-function cleanupCSSSource(file) {
-  var content = cat(file);
-
-  // Strip out all license headers in the middle.
-  var reg = /\n\/\* Copyright(.|\n)*?Mozilla Foundation(.|\n)*?\*\//g;
-  content = content.replace(reg, '');
-
-  content.to(file);
-}
-
 //
 // make minified
 // Builds the minified production viewer that should be compatible with most
 // modern HTML5 browsers.
 //
 target.minified = function() {
-  execGulp('bundle-minified');
-  target.locale();
-
-  cd(ROOT_DIR);
-  echo();
-  echo('### Creating minified viewer');
-
-  rm('-rf', MINIFIED_DIR);
-  mkdir('-p', MINIFIED_DIR);
-  mkdir('-p', MINIFIED_DIR + BUILD_DIR);
-  mkdir('-p', MINIFIED_DIR + '/web');
-  mkdir('-p', MINIFIED_DIR + '/web/cmaps');
-
-  var defines = builder.merge(DEFINES, {GENERIC: true, MINIFIED: true});
-
-  var setup = {
-    defines: defines,
-    copy: [
-      [BUILD_TARGETS, MINIFIED_DIR + BUILD_DIR],
-      [BUILD_DIR + 'viewer.js', MINIFIED_DIR + '/web'],
-      [COMMON_WEB_FILES, MINIFIED_DIR + '/web'],
-      ['web/compressed.tracemonkey-pldi-09.pdf', MINIFIED_DIR + '/web'],
-      ['external/bcmaps/*', MINIFIED_DIR + '/web/cmaps'],
-      ['web/locale', MINIFIED_DIR + '/web']
-    ],
-    preprocess: [
-      [COMMON_WEB_FILES_PREPROCESS, MINIFIED_DIR + '/web']
-    ],
-    preprocessCSS: [
-      ['minified', 'web/viewer.css',
-       MINIFIED_DIR + '/web/viewer.css']
-    ]
-  };
-  builder.build(setup);
-
-  cleanupCSSSource(MINIFIED_DIR + '/web/viewer.css');
+  execGulp('minified-pre');
 
   var viewerFiles = [
     'web/compatibility.js',
@@ -542,22 +361,10 @@ target.buildnumber = function() {
 // make firefox
 //
 target.firefox = function() {
-  cd(ROOT_DIR);
-  echo();
-  echo('### Building Firefox extension');
-  var defines = builder.merge(DEFINES, {FIREFOX: true});
+  execGulp('firefox-pre');
 
+  cd(ROOT_DIR);
   var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/',
-      FIREFOX_EXTENSION_DIR = 'extensions/firefox/',
-      FIREFOX_EXTENSION_FILES_TO_COPY =
-        ['*.js',
-         '*.rdf',
-         '*.svg',
-         '*.png',
-         '*.manifest',
-         'locale',
-         'chrome',
-         '../../LICENSE'],
       FIREFOX_EXTENSION_FILES =
         ['bootstrap.js',
          'install.rdf',
@@ -570,55 +377,6 @@ target.firefox = function() {
          'LICENSE'],
       FIREFOX_EXTENSION_NAME = 'pdf.js.xpi';
 
-  target.locale();
-  execGulp('bundle-firefox');
-  cd(ROOT_DIR);
-
-  // Clear out everything in the firefox extension build directory
-  rm('-rf', FIREFOX_BUILD_DIR);
-  mkdir('-p', FIREFOX_BUILD_CONTENT_DIR);
-  mkdir('-p', FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR);
-  mkdir('-p', FIREFOX_BUILD_CONTENT_DIR + '/web');
-  mkdir('-p', FIREFOX_BUILD_CONTENT_DIR + '/web/cmaps');
-
-  cp(FIREFOX_CONTENT_DIR + 'PdfJs-stub.jsm',
-     FIREFOX_BUILD_CONTENT_DIR + 'PdfJs.jsm');
-
-  cp(FIREFOX_CONTENT_DIR + 'PdfJsTelemetry-addon.jsm',
-     FIREFOX_BUILD_CONTENT_DIR + 'PdfJsTelemetry.jsm');
-
-  // Copy extension files
-  cd(FIREFOX_EXTENSION_DIR);
-  cp('-R', FIREFOX_EXTENSION_FILES_TO_COPY, ROOT_DIR + FIREFOX_BUILD_DIR);
-  cd(ROOT_DIR);
-
-  var setup = {
-    defines: defines,
-    copy: [
-      [BUILD_TARGETS, FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR],
-      [BUILD_DIR + 'viewer.js', FIREFOX_BUILD_CONTENT_DIR + '/web'],
-      [COMMON_WEB_FILES, FIREFOX_BUILD_CONTENT_DIR + '/web'],
-      ['external/bcmaps/*', FIREFOX_BUILD_CONTENT_DIR + '/web/cmaps'],
-      [FIREFOX_EXTENSION_DIR + 'tools/l10n.js',
-       FIREFOX_BUILD_CONTENT_DIR + '/web']
-    ],
-    preprocess: [
-      [COMMON_WEB_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR + '/web'],
-      [COMMON_FIREFOX_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR],
-      [FIREFOX_EXTENSION_DIR + 'bootstrap.js', FIREFOX_BUILD_DIR]
-    ],
-    preprocessCSS: [
-      ['firefox', 'web/viewer.css',
-       FIREFOX_BUILD_CONTENT_DIR + '/web/viewer.css']
-    ]
-  };
-  builder.build(setup);
-
-  cleanupJSSource(FIREFOX_BUILD_CONTENT_DIR + '/web/viewer.js');
-  cleanupJSSource(FIREFOX_BUILD_DIR + 'bootstrap.js');
-  cleanupJSSource(FIREFOX_BUILD_CONTENT_DIR + 'PdfjsChromeUtils.jsm');
-  cleanupCSSSource(FIREFOX_BUILD_CONTENT_DIR + '/web/viewer.css');
-
   // Remove '.DS_Store' and other hidden files
   find(FIREFOX_BUILD_DIR).forEach(function(file) {
     if (file.match(/^\./)) {
@@ -667,77 +425,13 @@ target.firefox = function() {
 // make mozcentral
 //
 target.mozcentral = function() {
+  execGulp('mozcentral-pre');
+
   cd(ROOT_DIR);
-  echo();
-  echo('### Building mozilla-central extension');
-  var defines = builder.merge(DEFINES, {MOZCENTRAL: true});
 
   var MOZCENTRAL_DIR = BUILD_DIR + 'mozcentral/',
       MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + 'browser/extensions/pdfjs/',
-      MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + 'content/',
-      MOZCENTRAL_L10N_DIR = MOZCENTRAL_DIR + 'browser/locales/en-US/pdfviewer/',
-      FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/',
-      FIREFOX_EXTENSION_FILES_TO_COPY =
-        ['*.svg',
-         '*.png',
-         '*.manifest',
-         'README.mozilla',
-         '../../LICENSE'],
-      DEFAULT_LOCALE_FILES =
-        [LOCALE_SRC_DIR + 'en-US/viewer.properties',
-         LOCALE_SRC_DIR + 'en-US/chrome.properties'],
-      FIREFOX_MC_EXCLUDED_FILES =
-        ['icon.png',
-         'icon64.png'];
-
-  execGulp('bundle-mozcentral');
-  cd(ROOT_DIR);
-
-  // Clear out everything in the firefox extension build directory
-  rm('-rf', MOZCENTRAL_DIR);
-  mkdir('-p', MOZCENTRAL_CONTENT_DIR);
-  mkdir('-p', MOZCENTRAL_L10N_DIR);
-  mkdir('-p', MOZCENTRAL_CONTENT_DIR + BUILD_DIR);
-  mkdir('-p', MOZCENTRAL_CONTENT_DIR + '/web');
-  mkdir('-p', MOZCENTRAL_CONTENT_DIR + '/web/cmaps');
-
-  cp(FIREFOX_CONTENT_DIR + 'PdfJsTelemetry.jsm', MOZCENTRAL_CONTENT_DIR);
-
-  // Copy extension files
-  cd('extensions/firefox');
-  cp('-R', FIREFOX_EXTENSION_FILES_TO_COPY,
-     ROOT_DIR + MOZCENTRAL_EXTENSION_DIR);
-  mv('-f', ROOT_DIR + MOZCENTRAL_EXTENSION_DIR + '/chrome-mozcentral.manifest',
-           ROOT_DIR + MOZCENTRAL_EXTENSION_DIR + '/chrome.manifest');
-  cd(ROOT_DIR);
-
-  var setup = {
-    defines: defines,
-    copy: [
-      [BUILD_TARGETS, MOZCENTRAL_CONTENT_DIR + BUILD_DIR],
-      [BUILD_DIR + 'viewer.js', MOZCENTRAL_CONTENT_DIR + '/web'],
-      [COMMON_WEB_FILES, MOZCENTRAL_CONTENT_DIR + '/web'],
-      ['external/bcmaps/*', MOZCENTRAL_CONTENT_DIR + '/web/cmaps'],
-      ['extensions/firefox/tools/l10n.js', MOZCENTRAL_CONTENT_DIR + '/web']
-    ],
-    preprocess: [
-      [COMMON_WEB_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR + '/web'],
-      [FIREFOX_CONTENT_DIR + 'pdfjschildbootstrap.js', MOZCENTRAL_CONTENT_DIR],
-      [COMMON_FIREFOX_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR],
-      [FIREFOX_CONTENT_DIR + 'PdfJs.jsm', MOZCENTRAL_CONTENT_DIR]
-    ],
-    preprocessCSS: [
-      ['mozcentral',
-       'web/viewer.css',
-       MOZCENTRAL_CONTENT_DIR + '/web/viewer.css']
-    ]
-  };
-  builder.build(setup);
-
-  cleanupJSSource(MOZCENTRAL_CONTENT_DIR + '/web/viewer.js');
-  cleanupJSSource(MOZCENTRAL_CONTENT_DIR + '/PdfJs.jsm');
-  cleanupJSSource(MOZCENTRAL_CONTENT_DIR + '/PdfjsChromeUtils.jsm');
-  cleanupCSSSource(MOZCENTRAL_CONTENT_DIR + '/web/viewer.css');
+      MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + 'content/';
 
   // Remove '.DS_Store' and other hidden files
   find(MOZCENTRAL_DIR).forEach(function(file) {
@@ -746,18 +440,6 @@ target.mozcentral = function() {
     }
   });
 
-  // Remove excluded files
-  cd(MOZCENTRAL_EXTENSION_DIR);
-  FIREFOX_MC_EXCLUDED_FILES.forEach(function(file) {
-    if (test('-f', file)) {
-      rm('-r', file);
-    }
-  });
-  cd(ROOT_DIR);
-
-  // Copy default localization files
-  cp(DEFAULT_LOCALE_FILES, MOZCENTRAL_L10N_DIR);
-
   // Update the build version number
   var VERSION = getCurrentVersion();
   sed('-i', /PDFJSSCRIPT_VERSION/, VERSION,
@@ -779,56 +461,13 @@ target.mozcentral = function() {
 // make chrome
 //
 target.chromium = function() {
-  target.locale();
+  execGulp('chromium-pre');
 
   cd(ROOT_DIR);
-  echo();
-  echo('### Building Chromium extension');
-  var defines = builder.merge(DEFINES, {CHROME: true});
 
   var CHROME_BUILD_DIR = BUILD_DIR + '/chromium/',
       CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/';
 
-  execGulp('bundle-chromium');
-  cd(ROOT_DIR);
-
-  // Clear out everything in the chrome extension build directory
-  rm('-Rf', CHROME_BUILD_DIR);
-  mkdir('-p', CHROME_BUILD_CONTENT_DIR);
-  mkdir('-p', CHROME_BUILD_CONTENT_DIR + BUILD_DIR);
-  mkdir('-p', CHROME_BUILD_CONTENT_DIR + '/web');
-
-  var setup = {
-    defines: defines,
-    copy: [
-      [BUILD_TARGETS, CHROME_BUILD_CONTENT_DIR + BUILD_DIR],
-      [BUILD_DIR + 'viewer.js', CHROME_BUILD_CONTENT_DIR + '/web'],
-      [COMMON_WEB_FILES, CHROME_BUILD_CONTENT_DIR + '/web'],
-      [['extensions/chromium/*.json',
-        'extensions/chromium/*.html',
-        'extensions/chromium/*.js',
-        'extensions/chromium/*.css',
-        'extensions/chromium/icon*.png'],
-       CHROME_BUILD_DIR],
-      ['extensions/chromium/pageAction/*.*', CHROME_BUILD_DIR + '/pageAction'],
-      ['extensions/chromium/options/*.*', CHROME_BUILD_DIR + '/options'],
-      ['external/webL10n/l10n.js', CHROME_BUILD_CONTENT_DIR + '/web'],
-      ['external/bcmaps/*', CHROME_BUILD_CONTENT_DIR + '/web/cmaps'],
-      ['web/locale', CHROME_BUILD_CONTENT_DIR + '/web']
-    ],
-    preprocess: [
-      [COMMON_WEB_FILES_PREPROCESS, CHROME_BUILD_CONTENT_DIR + '/web']
-    ],
-    preprocessCSS: [
-      ['chrome', 'web/viewer.css',
-       CHROME_BUILD_CONTENT_DIR + '/web/viewer.css']
-    ]
-  };
-  builder.build(setup);
-
-  cleanupJSSource(CHROME_BUILD_CONTENT_DIR + '/web/viewer.js');
-  cleanupCSSSource(CHROME_BUILD_CONTENT_DIR + '/web/viewer.css');
-
   // Update the build version number
   var VERSION = getCurrentVersion();
   sed('-i', /PDFJSSCRIPT_VERSION/, VERSION,
@@ -1171,6 +810,3 @@ target.makefile = function () {
 target.importl10n = function() {
   execGulp('importl10n');
 };
-
-exports.stripCommentHeaders = stripCommentHeaders;
-exports.builder = builder;
diff --git a/package.json b/package.json
index 78e5b57f0..96caf5e48 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
     "eslint": "^3.11.1",
     "esprima": "^2.7.2",
     "gulp": "^3.9.1",
+    "gulp-rename": "^1.2.2",
     "gulp-util": "^3.0.7",
     "gulp-zip": "^3.2.0",
     "jasmine": "^2.5.2",