diff --git a/examples/acroforms/forms.js b/examples/acroforms/forms.js
index eda306625..d7c40c8cc 100644
--- a/examples/acroforms/forms.js
+++ b/examples/acroforms/forms.js
@@ -5,6 +5,9 @@
 
 'use strict';
 
+// Specify the PDF with AcroForm here
+var pdfWithFormsPath = '../../test/pdfs/f1040.pdf';
+
 var formFields = {};
 
 function setupForm(div, content, viewport) {
@@ -135,16 +138,23 @@ function renderPage(div, pdf, pageNumber, callback) {
   });
 }
 
-// Fetch the PDF document from the URL using promices
-PDFJS.getDocument(pdfWithFormsPath).then(function getPdfForm(pdf) {
-  // Rendering all pages starting from first
-  var viewer = document.getElementById('viewer');
-  var pageNumber = 1;
-  renderPage(viewer, pdf, pageNumber++, function pageRenderingComplete() {
-    if (pageNumber > pdf.numPages) {
-      return; // All pages rendered
-    }
-    // Continue rendering of the next page
-    renderPage(viewer, pdf, pageNumber++, pageRenderingComplete);
+// In production, the bundled pdf.js shall be used instead of RequireJS.
+require.config({paths: {'pdfjs': '../../src'}});
+require(['pdfjs/display/api'], function (api) {
+  // In production, change this to point to the built `pdf.worker.js` file.
+  PDFJS.workerSrc = '../../src/worker_loader.js';
+
+  // Fetch the PDF document from the URL using promises.
+  api.getDocument(pdfWithFormsPath).then(function getPdfForm(pdf) {
+    // Rendering all pages starting from first
+    var viewer = document.getElementById('viewer');
+    var pageNumber = 1;
+    renderPage(viewer, pdf, pageNumber++, function pageRenderingComplete() {
+      if (pageNumber > pdf.numPages) {
+        return; // All pages rendered
+      }
+      // Continue rendering of the next page
+      renderPage(viewer, pdf, pageNumber++, pageRenderingComplete);
+    });
   });
 });
diff --git a/examples/acroforms/index.html b/examples/acroforms/index.html
index 15b9fde64..6a217edd0 100644
--- a/examples/acroforms/index.html
+++ b/examples/acroforms/index.html
@@ -2,27 +2,7 @@
 <html>
 
 <head>
-  <!-- In production, only one script (pdf.js) is necessary -->
-  <!-- In production, change the content of PDFJS.workerSrc below -->
-  <script src="../../src/shared/global.js"></script>
-  <script src="../../src/display/dom_utils.js"></script>
-  <script src="../../src/shared/util.js"></script>
-  <script src="../../src/display/annotation_layer.js"></script>
-  <script src="../../src/display/font_loader.js"></script>
-  <script src="../../src/display/metadata.js"></script>
-  <script src="../../src/display/text_layer.js"></script>
-  <script src="../../src/display/webgl.js"></script>
-  <script src="../../src/display/pattern_helper.js"></script>
-  <script src="../../src/display/canvas.js"></script>
-  <script src="../../src/display/api.js"></script>
-  <script>
-    // Specify the main script used to create a new PDF.JS web worker.
-    // In production, change this to point to the combined `pdf.js` file.
-    PDFJS.workerSrc = '../../src/worker_loader.js';
-
-    // Specify the PDF with AcroForm here
-    var pdfWithFormsPath = '../../test/pdfs/f1040.pdf';
-  </script>
+  <script src="../../node_modules/requirejs/require.js"></script>
 
   <style>
   .pdfpage { position:relative; top: 0; left: 0; border: solid 1px black; margin: 10px; }
diff --git a/examples/helloworld/hello.js b/examples/helloworld/hello.js
index 9cd8295f8..00aac8f61 100644
--- a/examples/helloworld/hello.js
+++ b/examples/helloworld/hello.js
@@ -1,34 +1,30 @@
-
-//
-// See README for overview
-//
-
 'use strict';
 
-//
-// Fetch the PDF document from the URL using promises
-//
-PDFJS.getDocument('helloworld.pdf').then(function(pdf) {
-  // Using promise to fetch the page
-  pdf.getPage(1).then(function(page) {
-    var scale = 1.5;
-    var viewport = page.getViewport(scale);
+// In production, the bundled pdf.js shall be used instead of RequireJS.
+require.config({paths: {'pdfjs': '../../src'}});
+require(['pdfjs/display/api'], function (api) {
+  // In production, change this to point to the built `pdf.worker.js` file.
+  PDFJS.workerSrc = '../../src/worker_loader.js';
+
+  // Fetch the PDF document from the URL using promises.
+  api.getDocument('helloworld.pdf').then(function (pdf) {
+    // Fetch the page.
+    pdf.getPage(1).then(function (page) {
+      var scale = 1.5;
+      var viewport = page.getViewport(scale);
 
-    //
-    // Prepare canvas using PDF page dimensions
-    //
-    var canvas = document.getElementById('the-canvas');
-    var context = canvas.getContext('2d');
-    canvas.height = viewport.height;
-    canvas.width = viewport.width;
+      // Prepare canvas using PDF page dimensions.
+      var canvas = document.getElementById('the-canvas');
+      var context = canvas.getContext('2d');
+      canvas.height = viewport.height;
+      canvas.width = viewport.width;
 
-    //
-    // Render PDF page into canvas context
-    //
-    var renderContext = {
-      canvasContext: context,
-      viewport: viewport
-    };
-    page.render(renderContext);
+      // Render PDF page into canvas context.
+      var renderContext = {
+        canvasContext: context,
+        viewport: viewport
+      };
+      page.render(renderContext);
+    });
   });
 });
diff --git a/examples/helloworld/index.html b/examples/helloworld/index.html
index 817212292..4b44fd21c 100644
--- a/examples/helloworld/index.html
+++ b/examples/helloworld/index.html
@@ -2,26 +2,7 @@
 <html>
 
 <head>
-  <!-- In production, only one script (pdf.js) is necessary -->
-  <!-- In production, change the content of PDFJS.workerSrc below -->
-  <script src="../../src/shared/global.js"></script>
-  <script src="../../src/display/dom_utils.js"></script>
-  <script src="../../src/shared/util.js"></script>
-  <script src="../../src/display/annotation_layer.js"></script>
-  <script src="../../src/display/font_loader.js"></script>
-  <script src="../../src/display/metadata.js"></script>
-  <script src="../../src/display/text_layer.js"></script>
-  <script src="../../src/display/webgl.js"></script>
-  <script src="../../src/display/pattern_helper.js"></script>
-  <script src="../../src/display/canvas.js"></script>
-  <script src="../../src/display/api.js"></script>
-
-  <script>
-    // Specify the main script used to create a new PDF.JS web worker.
-    // In production, leave this undefined or change it to point to the
-    // combined `pdf.worker.js` file.
-    PDFJS.workerSrc = '../../src/worker_loader.js';
-  </script>
+  <script src="../../node_modules/requirejs/require.js"></script>
   <script src="hello.js"></script>
 </head>
 
diff --git a/examples/svgviewer/index.html b/examples/svgviewer/index.html
index b51937591..931b595a3 100644
--- a/examples/svgviewer/index.html
+++ b/examples/svgviewer/index.html
@@ -2,24 +2,7 @@
 <html>
 
 <head>
-  <!-- In production, only one script (pdf.js) is necessary -->
-  <!-- In production, change the content of PDFJS.workerSrc below -->
-  <script src="../../src/shared/global.js"></script>
-  <script src="../../src/shared/util.js"></script>
-  <script src="../../src/display/font_loader.js"></script>
-  <script src="../../src/display/metadata.js"></script>
-  <script src="../../src/display/svg.js"></script>
-  <script src="../../src/display/webgl.js"></script>
-  <script src="../../src/display/pattern_helper.js"></script>
-  <script src="../../src/display/canvas.js"></script>
-  <script src="../../src/display/api.js"></script>
-
-  <script>
-    // Specify the main script used to create a new PDF.JS web worker.
-    // In production, leave this undefined or change it to point to the
-    // combined `pdf.worker.js` file.
-    PDFJS.workerSrc = '../../src/worker_loader.js';
-  </script>
+  <script src="../../node_modules/requirejs/require.js"></script>
   <script src="viewer.js"></script>
   <style>
     body {
diff --git a/examples/svgviewer/viewer.js b/examples/svgviewer/viewer.js
index 344315e79..a9ae5c8c0 100644
--- a/examples/svgviewer/viewer.js
+++ b/examples/svgviewer/viewer.js
@@ -1,8 +1,3 @@
-
-//
-// See README for overview
-//
-
 'use strict';
 
 // Parse query string to extract some parameters (it can fail for some input)
@@ -14,10 +9,7 @@ var queryParams = query ? JSON.parse('{' + query.split('&').map(function (a) {
 var url = queryParams.file || '../../test/pdfs/liveprogramming.pdf';
 var scale = +queryParams.scale || 1.5;
 
-//
-// Fetch the PDF document from the URL using promises
-//
-PDFJS.getDocument(url).then(function(pdf) {
+function renderDocument(pdf) {
   var numPages = pdf.numPages;
   // Using promise to fetch the page
 
@@ -53,4 +45,14 @@ PDFJS.getDocument(url).then(function(pdf) {
       });
     }.bind(null, i, anchor));
   }
+}
+
+// In production, the bundled pdf.js shall be used instead of RequireJS.
+require.config({paths: {'pdfjs': '../../src'}});
+require(['pdfjs/display/api', 'pdfjs/display/svg'], function (api, svg) {
+  // In production, change this to point to the built `pdf.worker.js` file.
+  PDFJS.workerSrc = '../../src/worker_loader.js';
+
+  // Fetch the PDF document from the URL using promises.
+  api.getDocument(url).then(renderDocument);
 });
diff --git a/external/builder/builder.js b/external/builder/builder.js
index 7552ad048..e1d2cf03d 100644
--- a/external/builder/builder.js
+++ b/external/builder/builder.js
@@ -303,36 +303,6 @@ function build(setup) {
 }
 exports.build = build;
 
-function getWorkerSrcFiles(filePath) {
-  var src = fs.readFileSync(filePath).toString();
-  var reSrcFiles = /var\s+otherFiles\s*=\s*(\[[^\]]*\])/;
-  var match = reSrcFiles.exec(src);
-  if (!match) {
-    throw new Error('Cannot find otherFiles array in ' + filePath);
-  }
-
-  var files = match[1].replace(/'/g, '"').replace(/^\s*\/\/.*/gm, '')
-    .replace(/,\s*]$/, ']');
-  try {
-    files = JSON.parse(files);
-  } catch (e) {
-    throw new Error('Failed to parse otherFiles in ' + filePath + ' as JSON, ' +
-                    e);
-  }
-
-  var srcFiles = files.filter(function(name) {
-    return name.indexOf('external') === -1;
-  });
-  var externalSrcFiles = files.filter(function(name) {
-    return name.indexOf('external') > -1;
-  });
-  return {
-    srcFiles: srcFiles,
-    externalSrcFiles: externalSrcFiles
-  };
-}
-exports.getWorkerSrcFiles = getWorkerSrcFiles;
-
 /**
  * Merge two defines arrays. Values in the second param will override values in
  * the first.
diff --git a/external/umdutils/genhtml.js b/external/umdutils/genhtml.js
deleted file mode 100644
index 46b3ee0ff..000000000
--- a/external/umdutils/genhtml.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright 2015 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* jshint node:true */
-
-'use strict';
-
-// Simple util to re-generate HTML module references in right load order.
-
-var fs = require('fs');
-var path = require('path');
-var umd = require('./verifier.js');
-
-var filePath = process.argv[2];
-if (!filePath) {
-  console.log('USAGE: node ./external/umdutils/genhtml.js <html-file-path>');
-  process.exit(0);
-}
-
-var content = fs.readFileSync(filePath).toString();
-var m, re = /<script\s+src=['"]([^'"]+)/g;
-var filesFound = [];
-while ((m = re.exec(content))) {
-  var jsPath = m[1];
-  if (!/\bsrc\/.*?\.js$/.test(jsPath)) {
-    continue;
-  }
-  filesFound.push(jsPath);
-}
-
-var srcPrefix = filesFound[0].substring(0, filesFound[0].indexOf('src/') + 4);
-
-var dependencies = umd.readDependencies(filesFound.map(function (p) {
-  return path.join(path.dirname(filePath), p);
-}));
-
-dependencies.loadOrder.forEach(function (i) {
-  console.log('<script src="' + i.replace('pdfjs/', srcPrefix) + '.js">'+
-    '</script>');
-});
diff --git a/external/umdutils/verifier.js b/external/umdutils/verifier.js
index fc9f17436..864739091 100644
--- a/external/umdutils/verifier.js
+++ b/external/umdutils/verifier.js
@@ -59,7 +59,7 @@ function parseUmd(filePath) {
   var umdStart = '\\(function\\s\\(root,\\sfactory\\)\\s\\{';
   var umdImports = '\\}\\(this,\\sfunction\\s\\(exports\\b';
   var umdBody = '\\)\\s\\{';
-  var umdEnd = '\\}\\)\\);\\s*$';
+  var umdEnd = '\\}\\)\\);\\s*(//#endif\\s*)?$';
   var m, re;
   m = new RegExp(umdStart + '([\\s\\S]*?)' + umdImports + '([\\s\\S]*?)' +
     umdBody + '([\\s\\S]*?)' + umdEnd).exec(jscode);
diff --git a/make.js b/make.js
index b46026ed7..c544ccadf 100644
--- a/make.js
+++ b/make.js
@@ -477,7 +477,6 @@ target.cmaps = function () {
 target.bundle = function(args) {
   args = args || {};
   var defines = args.defines || DEFINES;
-  var excludes = args.excludes || [];
 
   target.buildnumber();
 
@@ -485,21 +484,13 @@ target.bundle = function(args) {
   echo();
   echo('### Bundling files into ' + BUILD_TARGET);
 
-  function bundle(filename, outfilename, SRC_FILES, EXT_SRC_FILES) {
-    for (var i = 0, length = excludes.length; i < length; ++i) {
-      var exclude = excludes[i];
-      var index = SRC_FILES.indexOf(exclude);
-      if (index >= 0) {
-        SRC_FILES.splice(index, 1);
-      }
-    }
-
-    var bundleContent = cat(SRC_FILES),
+  function bundle(filename, outfilename, files) {
+    var bundleContent = cat(files),
         bundleVersion = VERSION,
         bundleBuild = exec('git log --format="%h" -n 1',
           {silent: true}).output.replace('\n', '');
 
-    crlfchecker.checkIfCrlfIsPresent(SRC_FILES);
+    crlfchecker.checkIfCrlfIsPresent(files);
 
     // Prepend a newline because stripCommentHeaders only strips comments that
     // follow a line feed. The file where bundleContent is inserted already
@@ -509,9 +500,6 @@ target.bundle = function(args) {
     // Removes AMD and CommonJS branches from UMD headers.
     bundleContent = stripUMDHeaders(bundleContent);
 
-    // Append external files last since we don't want to modify them.
-    bundleContent += cat(EXT_SRC_FILES);
-
     // This just preprocesses the empty pdf.js file, we don't actually want to
     // preprocess everything yet since other build targets use this file.
     builder.preprocess(filename, outfilename, builder.merge(defines,
@@ -524,47 +512,51 @@ target.bundle = function(args) {
     mkdir(BUILD_DIR);
   }
 
-  var SHARED_SRC_FILES = [
-    'shared/global.js',
-    'shared/util.js'
+  var umd = require('./external/umdutils/verifier.js');
+  var MAIN_SRC_FILES = [
+    SRC_DIR + 'display/annotation_layer.js',
+    SRC_DIR + 'display/metadata.js',
+    SRC_DIR + 'display/text_layer.js',
+    SRC_DIR + 'display/api.js'
   ];
 
-  var MAIN_SRC_FILES = SHARED_SRC_FILES.concat([
-    'display/dom_utils.js',
-    'display/annotation_layer.js',
-    'display/font_loader.js',
-    'display/metadata.js',
-    'display/text_layer.js',
-    'display/webgl.js',
-    'display/pattern_helper.js',
-    'display/canvas.js',
-    'display/api.js',
-    'display/svg.js'
-  ]);
-
-  var srcFiles = builder.getWorkerSrcFiles('src/worker_loader.js');
-  var WORKER_SRC_FILES = srcFiles.srcFiles;
-
-  if (!defines.SINGLE_FILE) {
-    // We want shared_src_files in both pdf.js and pdf.worker.js
-    // unless it's being built in singlefile mode.
-    WORKER_SRC_FILES = SHARED_SRC_FILES.concat(WORKER_SRC_FILES);
-  } else {
+  var WORKER_SRC_FILES = [
+    SRC_DIR + 'core/worker.js'
+  ];
+
+  // Extension does not need svg.js and network.js files.
+  if (!defines.FIREFOX && !defines.MOZCENTRAL) {
+    MAIN_SRC_FILES.push(SRC_DIR + 'display/svg.js');
+    WORKER_SRC_FILES.push(SRC_DIR + 'core/network.js');
+  }
+
+  if (defines.SINGLE_FILE) {
     // In singlefile mode, all of the src files will be bundled into
-    // the main pdf.js outuput.
+    // the main pdf.js output.
     MAIN_SRC_FILES = MAIN_SRC_FILES.concat(WORKER_SRC_FILES);
+    WORKER_SRC_FILES = null; // no need for worker file
   }
 
-  var EXT_SRC_FILES = srcFiles.externalSrcFiles;
+  // Reading UMD headers and building loading orders of modules. The
+  // readDependencies returns AMD module names: removing 'pdfjs' prefix and
+  // adding '.js' extensions to the name.
+  var mainFiles = umd.readDependencies(MAIN_SRC_FILES).loadOrder.map(
+    function (name) { return name.replace('pdfjs/', '') + '.js'; });
+
+  var workerFiles = WORKER_SRC_FILES &&
+                    umd.readDependencies(WORKER_SRC_FILES).loadOrder.map(
+    function (name) { return name.replace('pdfjs/', '') + '.js'; });
 
   cd(SRC_DIR);
 
-  bundle('pdf.js', ROOT_DIR + BUILD_TARGET, MAIN_SRC_FILES, []);
-  var srcCopy = ROOT_DIR + BUILD_DIR + 'pdf.worker.js.temp';
-  cp('pdf.js', srcCopy);
-  bundle(srcCopy, ROOT_DIR + BUILD_WORKER_TARGET, WORKER_SRC_FILES,
-         EXT_SRC_FILES);
-  rm(srcCopy);
+  bundle('pdf.js', ROOT_DIR + BUILD_TARGET, mainFiles);
+
+  if (workerFiles) {
+    var srcCopy = ROOT_DIR + BUILD_DIR + 'pdf.worker.js.temp';
+    cp('pdf.js', srcCopy);
+    bundle(srcCopy, ROOT_DIR + BUILD_WORKER_TARGET, workerFiles);
+    rm(srcCopy);
+  }
 };
 
 //
@@ -796,7 +788,7 @@ target.firefox = function() {
       FIREFOX_AMO_EXTENSION_NAME = 'pdf.js.amo.xpi';
 
   target.locale();
-  target.bundle({ excludes: ['core/network.js'], defines: defines });
+  target.bundle({ defines: defines });
   cd(ROOT_DIR);
 
   // Clear out everything in the firefox extension build directory
@@ -923,7 +915,7 @@ target.mozcentral = function() {
         ['icon.png',
          'icon64.png'];
 
-  target.bundle({ excludes: ['core/network.js'], defines: defines });
+  target.bundle({ defines: defines });
   cd(ROOT_DIR);
 
   // Clear out everything in the firefox extension build directory
diff --git a/package.json b/package.json
index 97a39d9ac..17d60766e 100644
--- a/package.json
+++ b/package.json
@@ -4,11 +4,12 @@
   "devDependencies": {
     "jsdoc": "^3.3.0-alpha9",
     "jshint": "~2.8.0",
-    "wintersmith": "^2.0.0",
     "node-ensure": "^0.0.0",
+    "requirejs": "^2.1.22",
     "rimraf": "^2.4.1",
     "shelljs": "~0.4.0",
     "typogr": "~0.6.5",
+    "wintersmith": "^2.0.0",
     "yargs": "^3.14.0"
   },
   "scripts": {
diff --git a/src/core/network.js b/src/core/network.js
index fa0974996..c36066eac 100644
--- a/src/core/network.js
+++ b/src/core/network.js
@@ -291,3 +291,17 @@ var NetworkManager = (function NetworkManagerClosure() {
 
   return NetworkManager;
 })();
+
+//#if !(FIREFOX || MOZCENTRAL)
+(function (root, factory) {
+  if (typeof define === 'function' && define.amd) {
+    define('pdfjs/core/network', ['exports'], factory);
+  } else if (typeof exports !== 'undefined') {
+    factory(exports);
+  } else {
+    factory((root.pdfjsCoreNetwork = {}));
+  }
+}(this, function (exports) {
+  exports.NetworkManager = NetworkManager;
+}));
+//#endif
diff --git a/src/core/worker.js b/src/core/worker.js
index 2a157c62b..37f2fc756 100644
--- a/src/core/worker.js
+++ b/src/core/worker.js
@@ -84,7 +84,13 @@ var WorkerTask = (function WorkerTaskClosure() {
 
 var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
   setup: function wphSetup(handler, port) {
+    var testMessageProcessed = false;
     handler.on('test', function wphSetupTest(data) {
+      if (testMessageProcessed) {
+        return; // we already processed 'test' message once
+      }
+      testMessageProcessed = true;
+
       // check if Uint8Array can be sent to worker
       if (!(data instanceof Uint8Array)) {
         handler.send('test', 'main', false);
@@ -611,51 +617,57 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
   }
 };
 
-var consoleTimer = {};
-
-var workerConsole = {
-  log: function log() {
-    var args = Array.prototype.slice.call(arguments);
-    globalScope.postMessage({
-      targetName: 'main',
-      action: 'console_log',
-      data: args
-    });
-  },
-
-  error: function error() {
-    var args = Array.prototype.slice.call(arguments);
-    globalScope.postMessage({
-      targetName: 'main',
-      action: 'console_error',
-      data: args
-    });
-    throw 'pdf.js execution error';
-  },
-
-  time: function time(name) {
-    consoleTimer[name] = Date.now();
-  },
+function initializeWorker() {
+//#if !MOZCENTRAL
+  if (!('console' in globalScope)) {
+    var consoleTimer = {};
+
+    var workerConsole = {
+      log: function log() {
+        var args = Array.prototype.slice.call(arguments);
+        globalScope.postMessage({
+          targetName: 'main',
+          action: 'console_log',
+          data: args
+        });
+      },
+
+      error: function error() {
+        var args = Array.prototype.slice.call(arguments);
+        globalScope.postMessage({
+          targetName: 'main',
+          action: 'console_error',
+          data: args
+        });
+        throw 'pdf.js execution error';
+      },
 
-  timeEnd: function timeEnd(name) {
-    var time = consoleTimer[name];
-    if (!time) {
-      error('Unknown timer name ' + name);
-    }
-    this.log('Timer:', name, Date.now() - time);
-  }
-};
+      time: function time(name) {
+        consoleTimer[name] = Date.now();
+      },
 
+      timeEnd: function timeEnd(name) {
+        var time = consoleTimer[name];
+        if (!time) {
+          error('Unknown timer name ' + name);
+        }
+        this.log('Timer:', name, Date.now() - time);
+      }
+    };
 
-// Worker thread?
-if (typeof window === 'undefined' &&
-    !(typeof module !== 'undefined' && module.require)) {
-  if (!('console' in globalScope)) {
     globalScope.console = workerConsole;
   }
+//#endif
 
   var handler = new MessageHandler('worker', 'main', self);
   WorkerMessageHandler.setup(handler, self);
+  handler.send('ready', null);
+}
+
+// Worker thread (and not node.js)?
+if (typeof window === 'undefined' &&
+    !(typeof module !== 'undefined' && module.require)) {
+  initializeWorker();
 }
 
 exports.WorkerTask = WorkerTask;
diff --git a/src/display/api.js b/src/display/api.js
index 2167757de..bfa7b4040 100644
--- a/src/display/api.js
+++ b/src/display/api.js
@@ -414,7 +414,7 @@ PDFJS.getDocument = function getDocument(src,
       var transport = new WorkerTransport(messageHandler, task, rangeTransport);
       task._transport = transport;
     });
-  }, task._capability.reject);
+  }).catch(task._capability.reject);
 
   return task;
 };
@@ -1186,14 +1186,14 @@ var PDFWorker = (function PDFWorkerClosure() {
       // pdf.worker.js file is needed.
 //#if !PRODUCTION
       if (typeof amdRequire === 'function') {
-        amdRequire(['pdfjs/core/worker'], function () {
+        amdRequire(['pdfjs/core/network', 'pdfjs/core/worker'], function () {
           PDFJS.fakeWorkerFilesLoadedCapability.resolve();
         });
       } else if (typeof require === 'function') {
         require('../core/worker.js');
         PDFJS.fakeWorkerFilesLoadedCapability.resolve();
       } else {
-        Util.loadScript(PDFJS.workerSrc);
+        throw new Error('AMD or CommonJS must be used to load fake worker.');
       }
 //#endif
 //#if PRODUCTION && SINGLE_FILE
@@ -1253,8 +1253,16 @@ var PDFWorker = (function PDFWorkerClosure() {
           // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
           var worker = new Worker(workerSrc);
           var messageHandler = new MessageHandler('main', 'worker', worker);
-
+//#if !PRODUCTION
+          // Don't allow worker to be destroyed by Chrome, see:
+          // https://code.google.com/p/chromium/issues/detail?id=572225
+          var jsWorkerId = '_workerKungfuGrip_' + Math.random();
+          window[jsWorkerId] = worker;
+//#endif
           messageHandler.on('test', function PDFWorker_test(data) {
+//#if !PRODUCTION
+            delete window[jsWorkerId];
+//#endif
             if (this.destroyed) {
               this._readyCapability.reject(new Error('Worker was destroyed'));
               messageHandler.destroy();
@@ -1284,16 +1292,40 @@ var PDFWorker = (function PDFWorkerClosure() {
             console.error.apply(console, data);
           });
 
-          var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
-          // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
-          // typed array. Also, checking if we can use transfers.
-          try {
-            messageHandler.send('test', testObj, [testObj.buffer]);
-          } catch (ex) {
-            info('Cannot use postMessage transfers');
-            testObj[0] = 0;
-            messageHandler.send('test', testObj);
-          }
+          messageHandler.on('ready', function (data) {
+            if (this.destroyed) {
+              this._readyCapability.reject(new Error('Worker was destroyed'));
+              messageHandler.destroy();
+              worker.terminate();
+              return; // worker was destroyed
+            }
+            try {
+              sendTest();
+            } catch (e)  {
+              // We need fallback to a faked worker.
+              this._setupFakeWorker();
+            }
+          }.bind(this));
+
+          var sendTest = function () {
+            var testObj = new Uint8Array(
+              [PDFJS.postMessageTransfers ? 255 : 0]);
+            // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
+            // typed array. Also, checking if we can use transfers.
+            try {
+              messageHandler.send('test', testObj, [testObj.buffer]);
+            } catch (ex) {
+              info('Cannot use postMessage transfers');
+              testObj[0] = 0;
+              messageHandler.send('test', testObj);
+            }
+          };
+
+          // It might take time for worker to initialize (especially when AMD
+          // loader is used). We will try to send test immediately, and then
+          // when 'ready' message will arrive. The worker shall process only
+          // first received 'test'.
+          sendTest();
           return;
         } catch (e) {
           info('The worker has been disabled.');
diff --git a/src/display/svg.js b/src/display/svg.js
index 472287e4f..15048b451 100644
--- a/src/display/svg.js
+++ b/src/display/svg.js
@@ -16,6 +16,7 @@
 
 'use strict';
 
+//#if (GENERIC || SINGLE_FILE)
 (function (root, factory) {
   if (typeof define === 'function' && define.amd) {
     define('pdfjs/display/svg', ['exports', 'pdfjs/shared/util'], factory);
@@ -25,7 +26,6 @@
     factory((root.pdfjsDisplaySVG = {}), root.pdfjsSharedUtil);
   }
 }(this, function (exports, sharedUtil) {
-//#if (GENERIC || SINGLE_FILE)
 
 var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
 var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
@@ -1209,5 +1209,5 @@ var SVGGraphics = (function SVGGraphicsClosure() {
 PDFJS.SVGGraphics = SVGGraphics;
 
 exports.SVGGraphics = SVGGraphics;
-//#endif
 }));
+//#endif
diff --git a/src/display/text_layer.js b/src/display/text_layer.js
index 7b00f07d6..29f197ea5 100644
--- a/src/display/text_layer.js
+++ b/src/display/text_layer.js
@@ -12,22 +12,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/* globals PDFJS */
 
 'use strict';
 
 (function (root, factory) {
   if (typeof define === 'function' && define.amd) {
-    define('pdfjs/display/text_layer', ['exports', 'pdfjs/shared/util'],
-      factory);
+    define('pdfjs/display/text_layer', ['exports', 'pdfjs/shared/util',
+      'pdfjs/display/dom_utils', 'pdfjs/shared/global'], factory);
   } else if (typeof exports !== 'undefined') {
-    factory(exports, require('../shared/util.js'));
+    factory(exports, require('../shared/util.js'), require('./dom_utils.js'),
+      require('../shared/global.js'));
   } else {
-    factory((root.pdfjsDisplayTextLayer = {}), root.pdfjsSharedUtil);
+    factory((root.pdfjsDisplayTextLayer = {}), root.pdfjsSharedUtil,
+      root.pdfjsDisplayDOMUtils, root.pdfjsSharedGlobal);
   }
-}(this, function (exports, sharedUtil) {
+}(this, function (exports, sharedUtil, displayDOMUtils, sharedGlobal) {
 
+var Util = sharedUtil.Util;
 var createPromiseCapability = sharedUtil.createPromiseCapability;
+var CustomStyle = displayDOMUtils.CustomStyle;
+var PDFJS = sharedGlobal.PDFJS;
 
 /**
  * Text layer render parameters.
@@ -61,7 +65,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
       textDiv.dataset.isWhitespace = true;
       return;
     }
-    var tx = PDFJS.Util.transform(viewport.transform, geom.transform);
+    var tx = Util.transform(viewport.transform, geom.transform);
     var angle = Math.atan2(tx[1], tx[0]);
     if (style.vertical) {
       angle += Math.PI / 2;
@@ -167,7 +171,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
           transform = 'rotate(' + rotation + 'deg) ' + transform;
         }
         if (transform) {
-          PDFJS.CustomStyle.setProp('transform' , textDiv, transform);
+          CustomStyle.setProp('transform' , textDiv, transform);
         }
       }
     }
diff --git a/src/expose_to_global.js b/src/expose_to_global.js
deleted file mode 100644
index 36b4d50f3..000000000
--- a/src/expose_to_global.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright 2015 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- NOTE: This file is created as a helper to expose all loaded internal exported
- members to global scope.
- */
-
-'use strict';
-
-(function (root) {
-  for (var i in root) {
-    if (/^pdfjs(Shared|Core|Display)/.test(i)) {
-      var obj = root[i];
-      for (var j in obj) {
-        if (Object.getOwnPropertyDescriptor(root, j)) {
-          continue; // ignoring if already set
-        }
-        root[j] =  obj[j];
-      }
-    }
-  }
-})(window);
diff --git a/src/worker_loader.js b/src/worker_loader.js
index dc11706b8..ea480c741 100644
--- a/src/worker_loader.js
+++ b/src/worker_loader.js
@@ -12,70 +12,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- /* globals PDFJS, Util */
 
 'use strict';
 
-// List of shared files to include;
-var sharedFiles = [
-  'shared/global.js',
-  'shared/util.js'
-];
+importScripts('../node_modules/requirejs/require.js');
 
-// List of other files to include;
-var otherFiles = [
-  'core/network.js',
-  'core/arithmetic_decoder.js',
-  'core/charsets.js',
-  'core/glyphlist.js',
-  'core/jpg.js',
-  'core/metrics.js',
-  'core/bidi.js',
-  'core/chunked_stream.js',
-  'core/jbig2.js',
-  'core/jpx.js',
-  'core/murmurhash3.js',
-  'core/primitives.js',
-  'core/stream.js',
-  'core/crypto.js',
-  'core/font_renderer.js',
-  'core/parser.js',
-  'core/cmap.js',
-  'core/obj.js',
-  'core/ps_parser.js',
-  'core/fonts.js',
-  'core/function.js',
-  'core/colorspace.js',
-  'core/image.js',
-  'core/pattern.js',
-  'core/evaluator.js',
-  'core/annotation.js',
-  'core/document.js',
-  'core/pdf_manager.js',
-  'core/worker.js'
-];
-
-function loadInOrder(index, path, files) {
-  if (index >= files.length) {
-    PDFJS.fakeWorkerFilesLoadedCapability.resolve();
-    return;
-  }
-  PDFJS.Util.loadScript(path + files[index],
-                  loadInOrder.bind(null, ++index, path, files));
-}
-
-// Load all the files.
-if (typeof PDFJS === 'undefined' || !PDFJS.fakeWorkerFilesLoadedCapability) {
-  var files = sharedFiles.concat(otherFiles);
-  for (var i = 0; i < files.length; i++) {
-    importScripts(files[i]);
-  }
-} else {
-  var src = PDFJS.workerSrc;
-  var path = src.substr(0, src.indexOf('worker_loader.js'));
-  // If Util is available, we assume that shared files are already loaded. Can
-  // happen that they are not if PDF.js is bundled inside a special namespace.
-  var skipShared = typeof Util !== 'undefined';
-  var files = skipShared ? otherFiles : sharedFiles.concat(otherFiles);
-  loadInOrder(0, path, files);
-}
+require.config({paths: {'pdfjs': '.'}});
+require(['pdfjs/core/network', 'pdfjs/core/worker'],
+    function (network, worker) {
+  // Worker is loaded at this point.
+});
diff --git a/test/font/font_test.html b/test/font/font_test.html
index 44a3fbcae..feba02753 100644
--- a/test/font/font_test.html
+++ b/test/font/font_test.html
@@ -6,55 +6,12 @@
   <link rel="shortcut icon" type="image/png" href="../../external/jasmine/jasmine_favicon.png">
   <link rel="stylesheet" type="text/css" href="../../external/jasmine/jasmine.css">
 
+  <script src="../../node_modules/requirejs/require.js"></script>
   <script src="../../external/jasmine/jasmine.js"></script>
   <script src="../../external/jasmine/jasmine-html.js"></script>
   <script src="../unit/testreporter.js"></script>
   <script src="fontutils.js"></script>
 
-  <!-- include source files here... -->
-  <script src="../../src/core/network.js"></script>
-  <script src="../../src/core/arithmetic_decoder.js"></script>
-  <script src="../../src/core/charsets.js"></script>
-  <script src="../../src/core/glyphlist.js"></script>
-  <script src="../../src/core/jpg.js"></script>
-  <script src="../../src/core/metrics.js"></script>
-  <script src="../../src/shared/global.js"></script>
-  <script src="../../src/core/bidi.js"></script>
-  <script src="../../src/display/dom_utils.js"></script>
-  <script src="../../src/shared/util.js"></script>
-  <script src="../../src/core/chunked_stream.js"></script>
-  <script src="../../src/core/jbig2.js"></script>
-  <script src="../../src/core/jpx.js"></script>
-  <script src="../../src/core/murmurhash3.js"></script>
-  <script src="../../src/core/primitives.js"></script>
-  <script src="../../src/display/annotation_layer.js"></script>
-  <script src="../../src/display/font_loader.js"></script>
-  <script src="../../src/display/metadata.js"></script>
-  <script src="../../src/display/text_layer.js"></script>
-  <script src="../../src/display/webgl.js"></script>
-  <script src="../../src/core/stream.js"></script>
-  <script src="../../src/display/pattern_helper.js"></script>
-  <script src="../../src/core/crypto.js"></script>
-  <script src="../../src/core/font_renderer.js"></script>
-  <script src="../../src/core/parser.js"></script>
-  <script src="../../src/display/canvas.js"></script>
-  <script src="../../src/core/cmap.js"></script>
-  <script src="../../src/core/obj.js"></script>
-  <script src="../../src/core/ps_parser.js"></script>
-  <script src="../../src/display/api.js"></script>
-  <script src="../../src/core/fonts.js"></script>
-  <script src="../../src/core/function.js"></script>
-  <script src="../../src/core/colorspace.js"></script>
-  <script src="../../src/core/image.js"></script>
-  <script src="../../src/core/pattern.js"></script>
-  <script src="../../src/core/evaluator.js"></script>
-  <script src="../../src/core/annotation.js"></script>
-  <script src="../../src/core/document.js"></script>
-  <script src="../../src/core/pdf_manager.js"></script>
-  <script src="../../src/core/worker.js"></script>
-  <script src="../../src/expose_to_global.js"></script>
-  <script>PDFJS.workerSrc = '../../src/worker_loader.js';</script>
-
   <!-- include spec files here... -->
   <script src="font_core_spec.js"></script>
   <script src="font_os2_spec.js"></script>
@@ -64,6 +21,20 @@
   <script>
     'use strict';
 
+    function initializePDFJS(callback) {
+      require.config({paths: {'pdfjs': '../../src'}});
+      require(['pdfjs/core/fonts', 'pdfjs/core/stream', 'pdfjs/core/primitives',
+          'pdfjs/core/cmap'], function (fonts, stream, primitives, cmap) {
+        // Expose some of the PDFJS members to global scope for tests.
+        window.Font = fonts.Font;
+        window.Stream = stream.Stream;
+        window.Name = primitives.Name;
+        window.CMapFactory = cmap.CMapFactory;
+
+        callback();
+      });
+    }
+
     (function pdfJsUnitTest() {
       function queryParams() {
         var qs = window.location.search.substring(1);
@@ -99,7 +70,7 @@
         if (currentWindowOnload) {
           currentWindowOnload();
         }
-        execJasmine();
+        initializePDFJS(execJasmine);
       };
 
       function execJasmine() {
diff --git a/test/test_slave.html b/test/test_slave.html
index 50f0ce1c8..de7fda3f5 100644
--- a/test/test_slave.html
+++ b/test/test_slave.html
@@ -18,17 +18,7 @@ limitations under the License.
   <head>
     <title>PDF.js test slave</title>
     <meta charset="utf-8">
-    <script src="../src/shared/global.js"></script>
-    <script src="../src/display/dom_utils.js"></script>
-    <script src="../src/shared/util.js"></script>
-    <script src="../src/display/annotation_layer.js"></script>
-    <script src="../src/display/font_loader.js"></script>
-    <script src="../src/display/metadata.js"></script>
-    <script src="../src/display/text_layer.js"></script>
-    <script src="../src/display/webgl.js"></script>
-    <script src="../src/display/pattern_helper.js"></script>
-    <script src="../src/display/canvas.js"></script>
-    <script src="../src/display/api.js"></script>
+    <script src="../node_modules/requirejs/require.js"></script>
     <script src="driver.js"></script>
   </head>
   <body>
@@ -41,12 +31,19 @@ limitations under the License.
     <div id="end"></div>
   </body>
   <script>
-    var driver = new Driver({
-      disableScrolling: document.getElementById('disableScrolling'),
-      inflight: document.getElementById('inflight'),
-      output: document.getElementById('output'),
-      end: document.getElementById('end')
+    require.config({paths: {'pdfjs': '../src'}});
+    require(['pdfjs/display/api', 'pdfjs/display/text_layer',
+             'pdfjs/display/annotation_layer', 'pdfjs/shared/util'],
+        function (api, textLayer, annotationLayer, pdfjsSharedUtil) {
+      window.pdfjsSharedUtil = pdfjsSharedUtil;
+
+      var driver = new Driver({
+        disableScrolling: document.getElementById('disableScrolling'),
+        inflight: document.getElementById('inflight'),
+        output: document.getElementById('output'),
+        end: document.getElementById('end')
+      });
+      driver.run();
     });
-    driver.run();
   </script>
 </html>
diff --git a/test/unit/font_spec.js b/test/unit/font_spec.js
index 1eff8a22d..5b05f90cd 100644
--- a/test/unit/font_spec.js
+++ b/test/unit/font_spec.js
@@ -1,5 +1,6 @@
 /* globals expect, it, describe, CFFCompiler, CFFParser, CFFIndex, CFFStrings,
-           SEAC_ANALYSIS_ENABLED:true, Type1Parser, StringStream */
+           SEAC_ANALYSIS_ENABLED, Type1Parser, StringStream,
+           _enableSeacAnalysis */
 
 'use strict';
 
@@ -109,7 +110,7 @@ describe('font', function() {
     it('parses a CharString endchar with 4 args w/seac enabled', function() {
       var seacAnalysisState = SEAC_ANALYSIS_ENABLED;
       try {
-        window.pdfjsCoreFonts._enableSeacAnalysis(true);
+        _enableSeacAnalysis(true);
         var bytes = new Uint8Array([0, 1, // count
                                     1,  // offsetSize
                                     0,  // offset[0]
@@ -125,14 +126,14 @@ describe('font', function() {
         expect(result.seacs[0][2]).toEqual(65);
         expect(result.seacs[0][3]).toEqual(194);
       } finally {
-        window.pdfjsCoreFonts._enableSeacAnalysis(seacAnalysisState);
+        _enableSeacAnalysis(seacAnalysisState);
       }
     });
 
     it('parses a CharString endchar with 4 args w/seac disabled', function() {
       var seacAnalysisState = SEAC_ANALYSIS_ENABLED;
       try {
-        window.pdfjsCoreFonts._enableSeacAnalysis(false);
+        _enableSeacAnalysis(false);
         var bytes = new Uint8Array([0, 1, // count
                                     1,  // offsetSize
                                     0,  // offset[0]
@@ -143,7 +144,7 @@ describe('font', function() {
         expect(result.charStrings.get(0).length).toEqual(9);
         expect(result.seacs.length).toEqual(0);
       } finally {
-        window.pdfjsCoreFonts._enableSeacAnalysis(seacAnalysisState);
+        _enableSeacAnalysis(seacAnalysisState);
       }
     });
 
diff --git a/test/unit/unit_test.html b/test/unit/unit_test.html
index 6b6bff892..6ff77d3e6 100644
--- a/test/unit/unit_test.html
+++ b/test/unit/unit_test.html
@@ -6,54 +6,21 @@
   <link rel="shortcut icon" type="image/png" href="../../external/jasmine/jasmine_favicon.png">
   <link rel="stylesheet" type="text/css" href="../../external/jasmine/jasmine.css">
 
+  <script src="../../node_modules/requirejs/require.js"></script>
   <script src="../../external/jasmine/jasmine.js"></script>
   <script src="../../external/jasmine/jasmine-html.js"></script>
   <script src="testreporter.js"></script>
 
-  <!-- include source files here... -->
-  <script src="../../src/core/network.js"></script>
-  <script src="../../src/core/arithmetic_decoder.js"></script>
-  <script src="../../src/core/charsets.js"></script>
-  <script src="../../src/core/glyphlist.js"></script>
-  <script src="../../src/core/jpg.js"></script>
-  <script src="../../src/core/metrics.js"></script>
-  <script src="../../src/shared/global.js"></script>
-  <script src="../../src/core/bidi.js"></script>
-  <script src="../../src/display/dom_utils.js"></script>
-  <script src="../../src/shared/util.js"></script>
-  <script src="../../src/core/chunked_stream.js"></script>
-  <script src="../../src/core/jbig2.js"></script>
-  <script src="../../src/core/jpx.js"></script>
-  <script src="../../src/core/murmurhash3.js"></script>
-  <script src="../../src/core/primitives.js"></script>
-  <script src="../../src/display/annotation_layer.js"></script>
-  <script src="../../src/display/font_loader.js"></script>
-  <script src="../../src/display/metadata.js"></script>
-  <script src="../../src/display/text_layer.js"></script>
-  <script src="../../src/display/webgl.js"></script>
-  <script src="../../src/core/stream.js"></script>
-  <script src="../../src/display/pattern_helper.js"></script>
-  <script src="../../src/core/crypto.js"></script>
-  <script src="../../src/core/font_renderer.js"></script>
-  <script src="../../src/core/parser.js"></script>
-  <script src="../../src/display/canvas.js"></script>
-  <script src="../../src/core/cmap.js"></script>
-  <script src="../../src/core/obj.js"></script>
-  <script src="../../src/core/ps_parser.js"></script>
-  <script src="../../src/display/api.js"></script>
-  <script src="../../src/core/fonts.js"></script>
-  <script src="../../src/core/function.js"></script>
-  <script src="../../src/core/colorspace.js"></script>
-  <script src="../../src/core/image.js"></script>
-  <script src="../../src/core/pattern.js"></script>
-  <script src="../../src/core/evaluator.js"></script>
-  <script src="../../src/core/annotation.js"></script>
-  <script src="../../src/core/document.js"></script>
-  <script src="../../src/core/pdf_manager.js"></script>
-  <script src="../../src/core/worker.js"></script>
-  <script src="../../src/expose_to_global.js"></script>
   <script src="../../web/ui_utils.js"></script>
-  <script>PDFJS.workerSrc = '../../src/worker_loader.js';</script>
+
+  <script>
+    // Hacking describe() to wait for PDFJS to be loaded, since Jasmine executes
+    // it without waiting for libs to be loaded and fails to use PDFJS members.
+    var oldDescribe = window.describe, describeQueue = [];
+    window.describe = function () {
+      describeQueue.push(Array.prototype.slice.call(arguments, 0));
+    };
+  </script>
 
   <!-- include spec files here... -->
   <script src="primitives_spec.js"></script>
@@ -69,9 +36,66 @@
   <script src="util_spec.js"></script>
   <script src="cmap_spec.js"></script>
   <script src="annotation_layer_spec.js"></script>
+
   <script>
     'use strict';
 
+    var pdfjsLibs;
+
+    function initializePDFJS(callback) {
+      require.config({paths: {'pdfjs': '../../src'}});
+      require(['pdfjs/shared/util', 'pdfjs/shared/global', 'pdfjs/core/primitives',
+          'pdfjs/core/annotation', 'pdfjs/core/crypto', 'pdfjs/core/stream',
+          'pdfjs/core/fonts', 'pdfjs/core/ps_parser', 'pdfjs/core/function',
+          'pdfjs/core/parser', 'pdfjs/core/evaluator', 'pdfjs/core/cmap',
+          'pdfjs/core/worker', 'pdfjs/display/api', 'pdfjs/display/metadata'],
+          function (sharedUtil, sharedGlobal, corePrimitives, coreAnnotation,
+                    coreCrypto, coreStream, coreFonts, corePsParser, coreFunction,
+                    coreParser, coreEvaluator, coreCMap, coreWorker, displayAPI,
+                    displayMetadata) {
+
+        pdfjsLibs = {
+          sharedUtil: sharedUtil,
+          sharedGlobal: sharedGlobal,
+          corePrimitives: corePrimitives,
+          coreAnnotation: coreAnnotation,
+          coreCrypto: coreCrypto,
+          coreStream: coreStream,
+          coreFonts: coreFonts,
+          corePsParser: corePsParser,
+          coreFunction: coreFunction,
+          coreParser: coreParser,
+          coreEvaluator: coreEvaluator,
+          coreCMap: coreCMap,
+          coreWorker: coreWorker,
+          displayAPI: displayAPI,
+          displayMetadata: displayMetadata
+        };
+
+        // Expose all loaded internal exported members to global scope.
+        Object.keys(pdfjsLibs).forEach(function (libName) {
+          var lib = pdfjsLibs[libName];
+          Object.keys(lib).forEach(function (name) {
+            if (Object.getOwnPropertyDescriptor(window, name)) {
+              return; // ignoring if already set
+            }
+            window[name] = lib[name];
+          });
+        });
+
+        // Configure the worker.
+        PDFJS.workerSrc = '../../src/worker_loader.js';
+
+        // Release describe() calls.
+        window.describe = oldDescribe;
+        describeQueue.forEach(function (args) {
+          oldDescribe.apply(window, args);
+        });
+
+        callback();
+      });
+    }
+
     (function pdfJsUnitTest() {
       function queryParams() {
         var qs = window.location.search.substring(1);
@@ -107,7 +131,7 @@
         if (currentWindowOnload) {
           currentWindowOnload();
         }
-        execJasmine();
+        initializePDFJS(execJasmine);
       };
 
       function execJasmine() {
diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js
index 46afd5c8b..539113a40 100644
--- a/web/pdf_page_view.js
+++ b/web/pdf_page_view.js
@@ -36,8 +36,6 @@ var TEXT_LAYER_RENDER_DELAY = 200; // ms
  * @implements {IRenderableView}
  */
 var PDFPageView = (function PDFPageViewClosure() {
-  var CustomStyle = PDFJS.CustomStyle;
-
   /**
    * @constructs PDFPageView
    * @param {PDFPageViewOptions} options
@@ -211,6 +209,8 @@ var PDFPageView = (function PDFPageViewClosure() {
     },
 
     cssTransform: function PDFPageView_transform(canvas, redrawAnnotations) {
+      var CustomStyle = PDFJS.CustomStyle;
+
       // Scale canvas, canvas wrapper, and page container.
       var width = this.viewport.width;
       var height = this.viewport.height;
@@ -518,6 +518,7 @@ var PDFPageView = (function PDFPageViewClosure() {
     },
 
     beforePrint: function PDFPageView_beforePrint() {
+      var CustomStyle = PDFJS.CustomStyle;
       var pdfPage = this.pdfPage;
 
       var viewport = pdfPage.getViewport(1);
diff --git a/web/viewer.html b/web/viewer.html
index 2e64efa09..e5fb76293 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -53,18 +53,7 @@ See https://github.com/adobe-type-tools/cmap-resources
 <!--#endif-->
 
 <!--#if !PRODUCTION-->
-    <script src="../src/shared/global.js"></script>
-    <script src="../src/display/dom_utils.js"></script>
-    <script src="../src/shared/util.js"></script>
-    <script src="../src/display/annotation_layer.js"></script>
-    <script src="../src/display/font_loader.js"></script>
-    <script src="../src/display/metadata.js"></script>
-    <script src="../src/display/text_layer.js"></script>
-    <script src="../src/display/webgl.js"></script>
-    <script src="../src/display/pattern_helper.js"></script>
-    <script src="../src/display/canvas.js"></script>
-    <script src="../src/display/api.js"></script>
-    <script>PDFJS.workerSrc = '../src/worker_loader.js';</script>
+    <script src="../node_modules/requirejs/require.js"></script>
 <!--#endif-->
 
 <!--#if (GENERIC && !MINIFIED) -->
diff --git a/web/viewer.js b/web/viewer.js
index 6151a9037..f3684348d 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -34,17 +34,20 @@ var SCALE_SELECT_PADDING = 22;
 var PAGE_NUMBER_LOADING_INDICATOR = 'visiblePageIsLoading';
 var DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000;
 
-PDFJS.imageResourcesPath = './images/';
+function configure(PDFJS) {
+  PDFJS.imageResourcesPath = './images/';
 //#if (FIREFOX || MOZCENTRAL || GENERIC || CHROME)
 //PDFJS.workerSrc = '../build/pdf.worker.js';
 //#endif
 //#if !PRODUCTION
-PDFJS.cMapUrl = '../external/bcmaps/';
-PDFJS.cMapPacked = true;
+  PDFJS.cMapUrl = '../external/bcmaps/';
+  PDFJS.cMapPacked = true;
+  PDFJS.workerSrc = '../src/worker_loader.js';
 //#else
 //PDFJS.cMapUrl = '../web/cmaps/';
 //PDFJS.cMapPacked = true;
 //#endif
+}
 
 var mozL10n = document.mozL10n || document.webL10n;
 
@@ -1330,7 +1333,20 @@ window.PDFView = PDFViewerApplication; // obsolete name, using it as an alias
 //#endif
 
 function webViewerLoad(evt) {
-  PDFViewerApplication.initialize().then(webViewerInitialized);
+//#if !PRODUCTION
+  require.config({paths: {'pdfjs': '../src'}});
+  require(['pdfjs/display/api',
+           'pdfjs/display/annotation_layer',
+           'pdfjs/display/text_layer',
+           'pdfjs/display/metadata'],
+    function (api, annotationLayer, textLayer, metadata) {
+      configure(PDFJS);
+      PDFViewerApplication.initialize().then(webViewerInitialized);
+    });
+//#else
+//  configure(PDFJS);
+//  PDFViewerApplication.initialize().then(webViewerInitialized);
+//#endif
 }
 
 function webViewerInitialized() {