diff --git a/packages/babel-preset-react-app/index.js b/packages/babel-preset-react-app/index.js index a028babc06c..74592d0ece7 100644 --- a/packages/babel-preset-react-app/index.js +++ b/packages/babel-preset-react-app/index.js @@ -30,7 +30,11 @@ const plugins = [ regenerator: true, // Resolve the Babel runtime relative to the config. moduleName: path.dirname(require.resolve('babel-runtime/package')) - }] + }], + // We always include this plugin regardless of environment + // because of a Babel bug that breaks object rest/spread without it: + // https://github.com/babel/babel/issues/4851 + require.resolve('babel-plugin-transform-es2015-parameters'), ]; // This is similar to how `env` works in Babel: @@ -63,53 +67,46 @@ if (env === 'development' || env === 'test') { ]); } -if (env === 'test') { - plugins.push.apply(plugins, [ - // We always include this plugin regardless of environment - // because of a Babel bug that breaks object rest/spread without it: - // https://github.com/babel/babel/issues/4851 - require.resolve('babel-plugin-transform-es2015-parameters') - ]); +if (env === 'production') { + // Optimization: hoist JSX that never changes out of render() + // Disabled because of issues: + // * https://github.com/facebookincubator/create-react-app/issues/525 + // * https://phabricator.babeljs.io/search/query/pCNlnC2xzwzx/ + // * https://github.com/babel/babel/issues/4516 + // TODO: Enable again when these issues are resolved. + // plugins.push.apply(plugins, [ + // require.resolve('babel-plugin-transform-react-constant-elements') + // ]); +} - module.exports = { +module.exports = function buildPreset(context, opts) { + if (env !== 'test') { + if (!opts.browsers) { + throw new Error('The "browsers" option is required outside "test" environment.'); + } + if (!Array.isArray(opts.browsers.development)) { + throw new Error('The "browsers" option must contain a "development" array.'); + } + if (!Array.isArray(opts.browsers.production)) { + throw new Error('The "browsers" option must contain a "production" array.'); + } + } + + return { presets: [ // ES features necessary for user's Node version [require('babel-preset-env').default, { - targets: { + targets: env === 'test' ? { node: 'current', - }, + } : { + browsers: env === 'development' ? + opts.browsers.development : + opts.browsers.production + } }], // JSX, Flow require.resolve('babel-preset-react') ], plugins: plugins }; -} else { - module.exports = { - presets: [ - // Latest stable ECMAScript features - require.resolve('babel-preset-latest'), - // JSX, Flow - require.resolve('babel-preset-react') - ], - plugins: plugins.concat([ - // function* () { yield 42; yield 43; } - [require.resolve('babel-plugin-transform-regenerator'), { - // Async functions are converted to generators by babel-preset-latest - async: false - }], - ]) - }; - - if (env === 'production') { - // Optimization: hoist JSX that never changes out of render() - // Disabled because of issues: - // * https://github.com/facebookincubator/create-react-app/issues/525 - // * https://phabricator.babeljs.io/search/query/pCNlnC2xzwzx/ - // * https://github.com/babel/babel/issues/4516 - // TODO: Enable again when these issues are resolved. - // plugins.push.apply(plugins, [ - // require.resolve('babel-plugin-transform-react-constant-elements') - // ]); - } -} +} \ No newline at end of file diff --git a/packages/babel-preset-react-app/package.json b/packages/babel-preset-react-app/package.json index c9513ae340a..92f603efa24 100644 --- a/packages/babel-preset-react-app/package.json +++ b/packages/babel-preset-react-app/package.json @@ -20,8 +20,7 @@ "babel-plugin-transform-react-jsx-source": "6.9.0", "babel-plugin-transform-regenerator": "6.16.1", "babel-plugin-transform-runtime": "6.15.0", - "babel-preset-env": "0.0.8", - "babel-preset-latest": "6.16.0", + "babel-preset-env": "1.0.2", "babel-preset-react": "6.16.0", "babel-runtime": "6.11.6" } diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index 2f10ea2fb8a..b4d9f56a0a1 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -83,7 +83,7 @@ if (__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1) appPublic: resolveOwn('../template/public'), appHtml: resolveOwn('../template/public/index.html'), appIndexJs: resolveOwn('../template/src/index.js'), - appPackageJson: resolveOwn('../package.json'), + appPackageJson: resolveOwn('../example.package.json'), appSrc: resolveOwn('../template/src'), yarnLockFile: resolveOwn('../template/yarn.lock'), testsSetup: resolveOwn('../template/src/setupTests.js'), diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 96fd632b795..a58d1edaa78 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -10,6 +10,7 @@ // @remove-on-eject-end var autoprefixer = require('autoprefixer'); +var chalk = require('chalk'); var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); @@ -33,6 +34,21 @@ var publicUrl = ''; // Get environment variables to inject into our app. var env = getClientEnvironment(publicUrl); +// TODO: better messages (or make it optional) +var supportedBrowsers = require(paths.appPackageJson).browsers; +if (!supportedBrowsers) { + console.error( + chalk.red('Please specify supported browsers in the "browsers" field in "package.json".') + ); + process.exit(1); +} +if (!Array.isArray(supportedBrowsers.development)) { + console.error( + chalk.red('Please specify the "development" browser array in the "browsers" field in "package.json".') + ); + process.exit(1); +} + // This is the development configuration. // It is focused on developer experience and fast rebuilds. // The production configuration is different and lives in a separate file. @@ -148,7 +164,11 @@ module.exports = { query: { // @remove-on-eject-begin babelrc: false, - presets: [require.resolve('babel-preset-react-app')], + presets: [ + [require.resolve('babel-preset-react-app'), { + browsers: supportedBrowsers + }] + ], // @remove-on-eject-end // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ @@ -192,12 +212,7 @@ module.exports = { postcss: function() { return [ autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ] + browsers: supportedBrowsers.development }), ]; }, diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 058db0d7921..db1a8f87600 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -10,6 +10,7 @@ // @remove-on-eject-end var autoprefixer = require('autoprefixer'); +var chalk = require('chalk'); var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); @@ -52,6 +53,21 @@ var publicUrl = ensureSlash(homepagePathname, false); // Get environment variables to inject into our app. var env = getClientEnvironment(publicUrl); +// TODO: better messages (or make it optional) +var supportedBrowsers = require(paths.appPackageJson).browsers; +if (!supportedBrowsers) { + console.error( + chalk.red('Please specify supported browsers in the "browsers" field in "package.json".') + ); + process.exit(1); +} +if (!Array.isArray(supportedBrowsers.production)) { + console.error( + chalk.red('Please specify the "production" browser array in the "browsers" field in "package.json".') + ); + process.exit(1); +} + // Assert this just to be safe. // Development builds of React are slow and not intended for production. if (env['process.env'].NODE_ENV !== '"production"') { @@ -154,7 +170,11 @@ module.exports = { // @remove-on-eject-begin query: { babelrc: false, - presets: [require.resolve('babel-preset-react-app')], + presets: [ + [require.resolve('babel-preset-react-app'), { + browsers: supportedBrowsers + }] + ], }, // @remove-on-eject-end }, @@ -204,12 +224,7 @@ module.exports = { postcss: function() { return [ autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ] + browsers: supportedBrowsers.production }), ]; }, diff --git a/packages/react-scripts/example.package.json b/packages/react-scripts/example.package.json new file mode 100644 index 00000000000..f1b6b2edfae --- /dev/null +++ b/packages/react-scripts/example.package.json @@ -0,0 +1,26 @@ +{ + "name": "sample-project", + "dependencies": { + "react": "^15.4.1", + "react-dom": "^15.4.1" + }, + "devDependencies": { + "react-scripts": "^0.9.0" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test" + }, + "browsers": { + "development": [ + "last 1 chrome version" + ], + "production": [ + ">1%", + "last 4 versions", + "Firefox ESR", + "not ie < 9" + ] + } +} \ No newline at end of file