diff --git a/package.json b/package.json index 4b42bb5ebdf2..6ad64860566c 100644 --- a/package.json +++ b/package.json @@ -83,13 +83,13 @@ "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", + "rollup-plugin-strip-banner": "^0.2.0", "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/circleci/check_modules.sh b/scripts/circleci/check_modules.sh index b71b4cd616d2..8ecd67dfbbee 100755 --- a/scripts/circleci/check_modules.sh +++ b/scripts/circleci/check_modules.sh @@ -5,7 +5,7 @@ set -e # Make sure we don't introduce accidental @providesModule annotations. EXPECTED='packages/react-cs-renderer/src/ReactNativeCSTypes.js packages/react-native-renderer/src/ReactNativeTypes.js -scripts/rollup/header.js' +scripts/rollup/wrappers.js' ACTUAL=$(git grep -l @providesModule -- './*.js' ':!scripts/rollup/shims/*.js') if [ "$EXPECTED" != "$ACTUAL" ]; then diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js index e1756d717b16..a842086209de 100644 --- a/scripts/rollup/build.js +++ b/scripts/rollup/build.js @@ -2,10 +2,12 @@ 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 stripBanner = require('rollup-plugin-strip-banner'); const chalk = require('chalk'); const join = require('path').join; const resolve = require('path').resolve; @@ -23,8 +25,7 @@ const syncReactNative = require('./sync').syncReactNative; 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 Wrappers = require('./wrappers'); const UMD_DEV = Bundles.bundleTypes.UMD_DEV; const UMD_PROD = Bundles.bundleTypes.UMD_PROD; @@ -35,9 +36,6 @@ const FB_PROD = Bundles.bundleTypes.FB_PROD; const RN_DEV = Bundles.bundleTypes.RN_DEV; const RN_PROD = Bundles.bundleTypes.RN_PROD; -const RECONCILER = Bundles.moduleTypes.RECONCILER; - -const reactVersion = require('../../package.json').version; const requestedBundleTypes = (argv.type || '') .split(',') .map(type => type.toUpperCase()); @@ -51,134 +49,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; - } -} - -function getBanner(bundleType, globalName, filename, moduleType) { - if (moduleType === RECONCILER) { - // Standalone reconciler is only used by third-party renderers. - // It is handled separately. - return getReconcilerBanner(bundleType, filename); - } - - switch (bundleType) { - // UMDs are not wrapped in conditions. - case UMD_DEV: - case UMD_PROD: - return Header.getHeader(filename, reactVersion); - // CommonJS DEV bundle is guarded to help weak dead code elimination. - case NODE_DEV: - let banner = Header.getHeader(filename, reactVersion); - // Wrap the contents of the if-DEV check with an IIFE. - // Block-level function definitions can cause problems for strict mode. - banner += `'use strict';\n\n\nif (process.env.NODE_ENV !== "production") {\n(function() {\n`; - return banner; - case NODE_PROD: - return Header.getHeader(filename, reactVersion); - // All FB and RN bundles need Haste headers. - // DEV bundle is guarded to help weak dead code elimination. - case FB_DEV: - case FB_PROD: - case RN_DEV: - case RN_PROD: - const isDev = bundleType === FB_DEV || bundleType === RN_DEV; - const hasteFinalName = globalName + (isDev ? '-dev' : '-prod'); - // Wrap the contents of the if-DEV check with an IIFE. - // Block-level function definitions can cause problems for strict mode. - return ( - Header.getProvidesHeader(hasteFinalName) + - (isDev ? `\n\n'use strict';\n\n\nif (__DEV__) {\n(function() {\n` : '') - ); - default: - throw new Error('Unknown type.'); - } -} - -function getFooter(bundleType, filename, moduleType) { - if (moduleType === RECONCILER) { - // Standalone reconciler is only used by third-party renderers. - // It is handled separately. - return getReconcilerFooter(bundleType); - } - - // Only need a footer if getBanner() has an opening brace. - switch (bundleType) { - // Non-UMD DEV bundles need conditions to help weak dead code elimination. - case NODE_DEV: - case FB_DEV: - case RN_DEV: - return '\n})();\n}\n'; - default: - return ''; - } -} - -// TODO: this is extremely gross. -// But it only affects the "experimental" standalone reconciler build. -// The goal is to avoid having any shared state between renderers sharing it on npm. -// Ideally we should just remove shared state in all Fiber modules and then lint against it. -// But for now, we store the exported function in a variable, and then put the rest of the code -// into a closure that makes all module-level state private to each call. -const RECONCILER_WRAPPER_INTRO = `var $$$reconciler;\nmodule.exports = function(config) {\n`; -const RECONCILER_WRAPPER_OUTRO = `return ($$$reconciler || ($$$reconciler = module.exports))(config);\n};\n`; - -function getReconcilerBanner(bundleType, filename) { - let banner = `${Header.getHeader( - filename, - reactVersion - )}\n\n'use strict';\n\n\n`; - switch (bundleType) { - case NODE_DEV: - banner += `if (process.env.NODE_ENV !== "production") {\n${ - RECONCILER_WRAPPER_INTRO - }`; - break; - case NODE_PROD: - banner += RECONCILER_WRAPPER_INTRO; - break; - default: - throw new Error( - 'Standalone reconciler does not support ' + bundleType + ' builds.' - ); - } - return banner; -} - -function getReconcilerFooter(bundleType) { - switch (bundleType) { - case NODE_DEV: - return `\n${RECONCILER_WRAPPER_OUTRO}\n}`; - case NODE_PROD: - return `\n${RECONCILER_WRAPPER_OUTRO}`; - default: - throw new Error( - 'Standalone reconciler does not support ' + bundleType + ' builds.' - ); - } -} +const closureOptions = { + compilationLevel: 'SIMPLE', + languageIn: 'ECMASCRIPT5_STRICT', + languageOut: 'ECMASCRIPT5_STRICT', + env: 'CUSTOM', + warningLevel: 'QUIET', + applyInputSourceMaps: false, + useTypesForOptimization: false, + processCommonJsModules: false, +}; function getBabelConfig(updateBabelOptions, bundleType, filename) { let options = { @@ -261,7 +141,6 @@ function getRollupOutputOptions( return Object.assign( {}, { - banner: getBanner(bundleType, globalName, filename, moduleType), destDir: 'build/', file: 'build/' + @@ -270,7 +149,6 @@ function getRollupOutputOptions( filename, globalName ), - footer: getFooter(bundleType, filename, moduleType), format, globals, interop: false, @@ -280,13 +158,6 @@ function getRollupOutputOptions( ); } -function stripEnvVariables(production) { - return { - __DEV__: production ? 'false' : 'true', - 'process.env.NODE_ENV': production ? "'production'" : "'development'", - }; -} - function getFormat(bundleType) { switch (bundleType) { case UMD_DEV: @@ -323,86 +194,21 @@ 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