diff --git a/package.json b/package.json
index 4b42bb5ebdf26..d8d77c57ee4a6 100644
--- a/package.json
+++ b/package.json
@@ -83,13 +83,12 @@
     "rollup-plugin-commonjs": "^8.2.6",
     "rollup-plugin-inject": "^2.0.0",
     "rollup-plugin-node-resolve": "^2.0.0",
+    "rollup-plugin-prettier": "^0.3.0",
     "rollup-plugin-replace": "^1.1.1",
-    "rollup-plugin-uglify": "^1.0.1",
     "run-sequence": "^1.1.4",
     "through2": "^2.0.0",
     "tmp": "~0.0.28",
     "typescript": "~1.8.10",
-    "uglify-js": "^2.5.0",
     "yargs": "^6.3.0"
   },
   "devEngines": {
diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js
index e1756d717b165..e5f5328a1b34b 100644
--- a/scripts/rollup/build.js
+++ b/scripts/rollup/build.js
@@ -2,9 +2,10 @@
 
 const rollup = require('rollup').rollup;
 const babel = require('rollup-plugin-babel');
+const closure = require('rollup-plugin-closure-compiler-js');
 const commonjs = require('rollup-plugin-commonjs');
 const alias = require('rollup-plugin-alias');
-const uglify = require('rollup-plugin-uglify');
+const prettier = require('rollup-plugin-prettier');
 const replace = require('rollup-plugin-replace');
 const chalk = require('chalk');
 const join = require('path').join;
@@ -24,7 +25,6 @@ const syncReactNativeRT = require('./sync').syncReactNativeRT;
 const syncReactNativeCS = require('./sync').syncReactNativeCS;
 const Packaging = require('./packaging');
 const Header = require('./header');
-const closure = require('rollup-plugin-closure-compiler-js');
 
 const UMD_DEV = Bundles.bundleTypes.UMD_DEV;
 const UMD_PROD = Bundles.bundleTypes.UMD_PROD;
@@ -51,31 +51,16 @@ const errorCodeOpts = {
   errorMapFilePath: 'scripts/error-codes/codes.json',
 };
 
-function getHeaderSanityCheck(bundleType, globalName) {
-  switch (bundleType) {
-    case FB_DEV:
-    case FB_PROD:
-    case RN_DEV:
-    case RN_PROD:
-      let hasteFinalName = globalName;
-      switch (bundleType) {
-        case FB_DEV:
-        case RN_DEV:
-          hasteFinalName += '-dev';
-          break;
-        case FB_PROD:
-        case RN_PROD:
-          hasteFinalName += '-prod';
-          break;
-      }
-      return hasteFinalName;
-    case UMD_DEV:
-    case UMD_PROD:
-      return reactVersion;
-    default:
-      return null;
-  }
-}
+const closureOptions = {
+  compilationLevel: 'SIMPLE',
+  languageIn: 'ECMASCRIPT5_STRICT',
+  languageOut: 'ECMASCRIPT5_STRICT',
+  env: 'CUSTOM',
+  warningLevel: 'QUIET',
+  applyInputSourceMaps: false,
+  useTypesForOptimization: false,
+  processCommonJsModules: false,
+};
 
 function getBanner(bundleType, globalName, filename, moduleType) {
   if (moduleType === RECONCILER) {
@@ -261,7 +246,6 @@ function getRollupOutputOptions(
   return Object.assign(
     {},
     {
-      banner: getBanner(bundleType, globalName, filename, moduleType),
       destDir: 'build/',
       file:
         'build/' +
@@ -270,7 +254,6 @@ function getRollupOutputOptions(
           filename,
           globalName
         ),
-      footer: getFooter(bundleType, filename, moduleType),
       format,
       globals,
       interop: false,
@@ -323,55 +306,6 @@ function getFilename(name, globalName, bundleType) {
   }
 }
 
-function getUglifyConfig(configs) {
-  var mangle = configs.mangle;
-  var preserveVersionHeader = configs.preserveVersionHeader;
-  var removeComments = configs.removeComments;
-  var headerSanityCheck = configs.headerSanityCheck;
-  return {
-    warnings: false,
-    compress: {
-      screw_ie8: true,
-      dead_code: true,
-      unused: true,
-      drop_debugger: true,
-      // we have a string literal <script> that we don't want to evaluate
-      // for FB prod bundles (where we disable mangling)
-      evaluate: mangle,
-      booleans: true,
-      // Our www inline transform combined with Jest resetModules is confused
-      // in some rare cases unless we keep all requires at the top:
-      hoist_funs: mangle,
-    },
-    output: {
-      beautify: !mangle,
-      comments(node, comment) {
-        if (preserveVersionHeader && comment.pos === 0 && comment.col === 0) {
-          // Keep the very first comment (the bundle header) in prod bundles.
-          if (
-            headerSanityCheck &&
-            comment.value.indexOf(headerSanityCheck) === -1
-          ) {
-            // Sanity check: this doesn't look like the bundle header!
-            throw new Error(
-              'Expected the first comment to be the file header but got: ' +
-                comment.value
-            );
-          }
-          return true;
-        }
-        return !removeComments;
-      },
-    },
-    mangle: mangle
-      ? {
-          toplevel: true,
-          screw_ie8: true,
-        }
-      : false,
-  };
-}
-
 // FB uses require('React') instead of require('react').
 // We can't set up a forwarding module due to case sensitivity issues.
 function rewriteFBReactImport() {
@@ -405,6 +339,19 @@ function writeErrorCodes() {
   };
 }
 
+// Add custom intro and outro. This is intentionally a custom plugin
+// rather than expressed via Rollup output options because we want them
+// to be applied *after* the build.
+function wrapBundle(bundleType, globalName, filename, moduleType) {
+  return {
+    transformBundle(source) {
+      const banner = getBanner(bundleType, globalName, filename, moduleType);
+      const footer = getFooter(bundleType, filename, moduleType);
+      return banner + '\n' + source + '\n' + footer;
+    },
+  };
+}
+
 function getPlugins(
   entry,
   externals,
@@ -431,7 +378,6 @@ function getPlugins(
     stripUseStrict(),
   ].filter(Boolean);
 
-  const headerSanityCheck = getHeaderSanityCheck(bundleType, globalName);
   switch (bundleType) {
     case UMD_DEV:
     case NODE_DEV:
@@ -442,43 +388,40 @@ function getPlugins(
       plugins.push(
         replace(stripEnvVariables(true)),
         commonjs(),
-        closure({
-          compilationLevel: 'SIMPLE',
-          languageIn: 'ECMASCRIPT5_STRICT',
-          languageOut: 'ECMASCRIPT5_STRICT',
-          env: 'CUSTOM',
-          warningLevel: 'QUIET',
-          // Don't let it create global variables in the browser.
-          // https://github.com/facebook/react/issues/10909
-          assumeFunctionWrapper: bundleType !== UMD_PROD,
-          applyInputSourceMaps: false,
-          useTypesForOptimization: false,
-          processCommonJsModules: false,
-        })
+        closure(
+          Object.assign({}, closureOptions, {
+            // Don't let it create global variables in the browser.
+            // https://github.com/facebook/react/issues/10909
+            assumeFunctionWrapper: bundleType !== UMD_PROD,
+          })
+        )
       );
       break;
     case FB_DEV:
       plugins.push(
         replace(stripEnvVariables(false)),
         commonjs(),
-        rewriteFBReactImport()
+        rewriteFBReactImport(),
+        prettier()
       );
       break;
     case FB_PROD:
       plugins.push(
         replace(stripEnvVariables(true)),
         commonjs(),
-        uglify(
-          getUglifyConfig({
-            mangle: bundleType !== FB_PROD,
-            preserveVersionHeader: bundleType === UMD_PROD,
-            // leave comments in for source map debugging purposes
-            // they will be stripped as part of FB's build process
-            removeComments: bundleType !== FB_PROD,
-            headerSanityCheck,
+        closure(
+          Object.assign({}, closureOptions, {
+            assumeFunctionWrapper: true,
+            // Disable renaming so we have readable FB bundles.
+            // Works because `google-closure-compiler-js` is forked in the Yarn lockfile.
+            // We can remove this if GCC merges my PR:
+            // https://github.com/google/closure-compiler/pull/2707
+            // and then the compiled version is released via `google-closure-compiler-js`.
+            renaming: false,
           })
         ),
-        rewriteFBReactImport()
+        rewriteFBReactImport(),
+        prettier()
       );
       break;
     case RN_DEV:
@@ -486,17 +429,24 @@ function getPlugins(
       plugins.push(
         replace(stripEnvVariables(bundleType === RN_PROD)),
         commonjs(),
-        uglify(
-          getUglifyConfig({
-            mangle: false,
-            preserveVersionHeader: true,
-            removeComments: true,
-            headerSanityCheck,
+        closure(
+          Object.assign({}, closureOptions, {
+            assumeFunctionWrapper: true,
+            // <hack>
+            // Disable renaming so we have readable FB bundles.
+            // Works because `google-closure-compiler-js` is forked in the Yarn lockfile.
+            // We can remove this if GCC merges my PR:
+            // https://github.com/google/closure-compiler/pull/2707
+            // and then the compiled version is released via `google-closure-compiler-js`.
+            renaming: false,
+            // </hack>
           })
-        )
+        ),
+        prettier()
       );
       break;
   }
+  plugins.push(wrapBundle(bundleType, globalName, filename, moduleType));
   plugins.push(
     sizes({
       getSize: (size, gzip) => {
diff --git a/yarn.lock b/yarn.lock
index 8b42751657a85..af68ffad9dc7e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1437,7 +1437,7 @@ detective@^4.3.1:
     acorn "^4.0.3"
     defined "^1.0.0"
 
-diff@^3.2.0:
+diff@3.3.0, diff@^3.2.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9"
 
@@ -2150,8 +2150,8 @@ glogg@^1.0.0:
     sparkles "^1.0.0"
 
 google-closure-compiler-js@>20170000:
-  version "20170626.0.0"
-  resolved "https://registry.yarnpkg.com/google-closure-compiler-js/-/google-closure-compiler-js-20170626.0.0.tgz#5df265b277d1ec6fdea12eed131d1491cd8a8d71"
+  version "20170910.0.1"
+  resolved "https://registry.yarnpkg.com/@gaearon/google-closure-compiler-js/-/google-closure-compiler-js-20170910.0.1.tgz#b0cf7ef408219a19c390375a76bf0a82ccf65eea"
   dependencies:
     minimist "^1.2.0"
     vinyl "^2.0.1"
@@ -3208,6 +3208,12 @@ lru-cache@^4.0.1:
     pseudomap "^1.0.2"
     yallist "^2.1.2"
 
+magic-string@0.22.4, magic-string@^0.22.4:
+  version "0.22.4"
+  resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.4.tgz#31039b4e40366395618c1d6cf8193c53917475ff"
+  dependencies:
+    vlq "^0.2.1"
+
 magic-string@^0.15.2:
   version "0.15.2"
   resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.15.2.tgz#0681d7388741bbc3addaa65060992624c6c09e9c"
@@ -3220,12 +3226,6 @@ magic-string@^0.16.0:
   dependencies:
     vlq "^0.2.1"
 
-magic-string@^0.22.4:
-  version "0.22.4"
-  resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.4.tgz#31039b4e40366395618c1d6cf8193c53917475ff"
-  dependencies:
-    vlq "^0.2.1"
-
 makeerror@1.0.x:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
@@ -3671,7 +3671,7 @@ preserve@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
 
-prettier@1.8.1:
+prettier@1.8.1, prettier@^1.0.0:
   version "1.8.1"
   resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.1.tgz#91064d778c08c85ac1cbe6b23195c34310d039f9"
 
@@ -4104,6 +4104,14 @@ rollup-plugin-node-resolve@^2.0.0:
     builtin-modules "^1.1.0"
     resolve "^1.1.6"
 
+rollup-plugin-prettier@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/rollup-plugin-prettier/-/rollup-plugin-prettier-0.3.0.tgz#1000df8a2914d367b79507c1caa582fdbed8b0f3"
+  dependencies:
+    diff "3.3.0"
+    magic-string "0.22.4"
+    prettier "^1.0.0"
+
 rollup-plugin-replace@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/rollup-plugin-replace/-/rollup-plugin-replace-1.1.1.tgz#396315ded050a6ce43b9518a886a3f60efb1ea33"
@@ -4112,12 +4120,6 @@ rollup-plugin-replace@^1.1.1:
     minimatch "^3.0.2"
     rollup-pluginutils "^1.5.0"
 
-rollup-plugin-uglify@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-1.0.2.tgz#d4aa6f5df13522eae1ba17780c7c4c7096038359"
-  dependencies:
-    uglify-js "^2.6.1"
-
 rollup-pluginutils@^1.2.0, rollup-pluginutils@^1.5.0:
   version "1.5.2"
   resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408"
@@ -4600,7 +4602,7 @@ ua-parser-js@^0.7.9:
   version "0.7.17"
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
 
-uglify-js@^2.5.0, uglify-js@^2.6, uglify-js@^2.6.1:
+uglify-js@^2.6:
   version "2.8.22"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
   dependencies: