From 13ad859236b2bd33ac9a132b3125681826cb0feb Mon Sep 17 00:00:00 2001 From: James Blight Date: Thu, 8 Sep 2016 01:16:25 +0930 Subject: [PATCH 1/6] Create .babelrc file on eject. --- config/babel.dev.js | 92 +++++++++++++++++++++------------ config/babel.prod.js | 96 ++++++++++++++++++++++------------- config/webpack.config.dev.js | 2 +- config/webpack.config.prod.js | 2 +- scripts/eject.js | 26 ++++++++++ 5 files changed, 149 insertions(+), 69 deletions(-) diff --git a/config/babel.dev.js b/config/babel.dev.js index d122f108150..5a56c03a32d 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -9,38 +9,66 @@ */ // @remove-on-eject-end + +// After eject +module.exports = function () { + return { + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in OS temporary directory for faster rebuilds. + cacheDirectory: true + }; +} + +// @remove-on-eject-begin var path = require('path'); +// Before eject +module.exports = function (resolvePaths) { + return { + // Don't try to find .babelrc because we want to force this configuration. + babelrc: false, + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in OS temporary directory for faster rebuilds. + cacheDirectory: true, + presets: [ + // Latest stable ECMAScript features + 'babel-preset-latest', + // JSX, Flow + 'babel-preset-react' + ].map(function (preset) { + if (resolvePaths) { + return require.resolve(preset); + } -module.exports = { - // Don't try to find .babelrc because we want to force this configuration. - babelrc: false, - // This is a feature of `babel-loader` for webpack (not Babel itself). - // It enables caching results in OS temporary directory for faster rebuilds. - cacheDirectory: true, - presets: [ - // Latest stable ECMAScript features - require.resolve('babel-preset-latest'), - // JSX, Flow - require.resolve('babel-preset-react') - ], - plugins: [ - // class { handleClick = () => { } } - require.resolve('babel-plugin-transform-class-properties'), - // { ...todo, completed: true } - require.resolve('babel-plugin-transform-object-rest-spread'), - // function* () { yield 42; yield 43; } - [require.resolve('babel-plugin-transform-regenerator'), { - // Async functions are converted to generators by babel-preset-latest - async: false - }], - // Polyfills the runtime needed for async/await and generators - [require.resolve('babel-plugin-transform-runtime'), { - helpers: false, - polyfill: false, - regenerator: true, - // Resolve the Babel runtime relative to the config. - // You can safely remove this after ejecting: - moduleName: path.dirname(require.resolve('babel-runtime/package')) - }] - ] + return preset; + }), + plugins: [ + // class { handleClick = () => { } } + 'babel-plugin-transform-class-properties', + // { ...todo, completed: true } + 'babel-plugin-transform-object-rest-spread', + // function* () { yield 42; yield 43; } + ['babel-plugin-transform-regenerator', { + // Async functions are converted to generators by babel-preset-latest + async: false + }], + // Polyfills the runtime needed for async/await and generators + ['babel-plugin-transform-runtime', { + helpers: false, + polyfill: false, + regenerator: true, + // Resolve the Babel runtime relative to the config. + // You can safely remove this after ejecting: + moduleName: path.dirname(require.resolve('babel-runtime/package')) + }] + ].map(function (plugin) { + if (resolvePaths) { + return Array.isArray(plugin) ? + [require.resolve(plugin[0]), plugin[1]] : + require.resolve(plugin); + } + + return plugin; + }) + } }; +// @remove-on-eject-end diff --git a/config/babel.prod.js b/config/babel.prod.js index f53094ababd..8dcdfa526f6 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -9,41 +9,67 @@ */ // @remove-on-eject-end + +// After eject +// Config is empty as .babelrc now exists. +// Export an empty object as webpack.config.prod.js expects to find one. +module.exports = function () { + return {}; +}; + +// @remove-on-eject-begin var path = require('path'); +// Before eject +module.exports = function (resolvePaths) { + return { + // Don't try to find .babelrc because we want to force this configuration. + babelrc: false, + presets: [ + // Latest stable ECMAScript features + 'babel-preset-latest', + // JSX, Flow + 'babel-preset-react' + ].map(function (preset) { + if (resolvePaths) { + return require.resolve(preset); + } + + return preset; + }), + plugins: [ + // class { handleClick = () => { } } + 'babel-plugin-transform-class-properties', + // { ...todo, completed: true } + 'babel-plugin-transform-object-rest-spread', + // function* () { yield 42; yield 43; } + ['babel-plugin-transform-regenerator', { + // Async functions are converted to generators by babel-preset-latest + async: false + }], + // Polyfills the runtime needed for async/await and generators + ['babel-plugin-transform-runtime', { + helpers: false, + polyfill: false, + regenerator: true, + // Resolve the Babel runtime relative to the config. + // You can safely remove this after ejecting: + moduleName: path.dirname(require.resolve('babel-runtime/package')) + }], + // 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/ + // TODO: Enable again when these issues are resolved. + // require.resolve('babel-plugin-transform-react-constant-elements') + ].map(function (plugin) { + if (resolvePaths) { + return Array.isArray(plugin) ? + [require.resolve(plugin[0]), plugin[1]] : + require.resolve(plugin); + } -module.exports = { - // Don't try to find .babelrc because we want to force this configuration. - babelrc: false, - presets: [ - // Latest stable ECMAScript features - require.resolve('babel-preset-latest'), - // JSX, Flow - require.resolve('babel-preset-react') - ], - plugins: [ - // class { handleClick = () => { } } - require.resolve('babel-plugin-transform-class-properties'), - // { ...todo, completed: true } - require.resolve('babel-plugin-transform-object-rest-spread'), - // function* () { yield 42; yield 43; } - [require.resolve('babel-plugin-transform-regenerator'), { - // Async functions are converted to generators by babel-preset-latest - async: false - }], - // Polyfills the runtime needed for async/await and generators - [require.resolve('babel-plugin-transform-runtime'), { - helpers: false, - polyfill: false, - regenerator: true, - // Resolve the Babel runtime relative to the config. - // You can safely remove this after ejecting: - moduleName: path.dirname(require.resolve('babel-runtime/package')) - }], - // 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/ - // TODO: Enable again when these issues are resolved. - // require.resolve('babel-plugin-transform-react-constant-elements') - ] + return plugin; + }) + }; }; +// @remove-on-eject-end diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index e9d5a1f4946..898c14c522d 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -107,7 +107,7 @@ module.exports = { test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel', - query: require('./babel.dev') + query: require('./babel.dev')(true) }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index be27a29e4bf..16c63b6709f 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -102,7 +102,7 @@ module.exports = { test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel', - query: require('./babel.prod') + query: require('./babel.prod')(true) }, // The notation here is somewhat confusing. // "postcss" loader applies autoprefixer to our CSS. diff --git a/scripts/eject.js b/scripts/eject.js index 3e5e18af387..50172c25d27 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -13,6 +13,8 @@ var path = require('path'); var prompt = require('./utils/prompt'); var rimrafSync = require('rimraf').sync; var spawnSync = require('cross-spawn').sync; +var babelDevConfig = require('../config/babel.dev.js')(false); +var babelProdConfig = require('../config/babel.prod.js')(false); prompt( 'Are you sure you want to eject? This action is permanent.', @@ -69,6 +71,25 @@ prompt( fs.mkdirSync(path.join(appPath, 'scripts')); fs.mkdirSync(path.join(appPath, 'scripts', 'utils')); + // Create .babelrc from dev and prod configs before dead code is removed + var babelrc = { + env: { + development: { + presets: babelDevConfig.presets, + plugins: babelDevConfig.plugins + }, + production: { + presets: babelProdConfig.presets, + plugins: babelProdConfig.plugins + } + } + }; + + fs.writeFileSync( + path.join(appPath, 'config', '.babelrc'), + JSON.stringify(babelrc, null, 2) + ); + files.forEach(function(file) { console.log('Copying ' + file + ' to ' + appPath); var content = fs @@ -115,6 +136,11 @@ prompt( extends: './config/eslint.js', }; + // Explicitly specify .babelrc config path + appPackage.babel = { + extends: './config/.babelrc' + }; + console.log('Writing package.json'); fs.writeFileSync( path.join(appPath, 'package.json'), From 5cf70d35bf646743fd8f9e95e90450550c277f56 Mon Sep 17 00:00:00 2001 From: James Blight Date: Sat, 10 Sep 2016 09:43:47 +0930 Subject: [PATCH 2/6] Fix babel config import for jest. --- config/jest/transform.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/jest/transform.js b/config/jest/transform.js index 3a085e93e65..b38c50acdaa 100644 --- a/config/jest/transform.js +++ b/config/jest/transform.js @@ -8,7 +8,7 @@ */ // @remove-on-eject-end -const babelDev = require('../babel.dev'); +const babelDev = require('../babel.dev')(true); const babelJest = require('babel-jest'); module.exports = babelJest.createTransformer(babelDev); From 4337f8c4f0be68684f1f4f2e4618094ad9b85bcd Mon Sep 17 00:00:00 2001 From: James Blight Date: Tue, 13 Sep 2016 00:11:29 +0930 Subject: [PATCH 3/6] Make e2e test pass. --- scripts/eject.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/eject.js b/scripts/eject.js index 50172c25d27..8e6f4b08cb8 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -74,6 +74,10 @@ prompt( // Create .babelrc from dev and prod configs before dead code is removed var babelrc = { env: { + test: { + presets: babelDevConfig.presets, + plugins: babelDevConfig.plugins + }, development: { presets: babelDevConfig.presets, plugins: babelDevConfig.plugins @@ -84,7 +88,7 @@ prompt( } } }; - + fs.writeFileSync( path.join(appPath, 'config', '.babelrc'), JSON.stringify(babelrc, null, 2) From 680bb7d66c6637df91d62a1d26d5c955816558d2 Mon Sep 17 00:00:00 2001 From: James Blight Date: Tue, 13 Sep 2016 01:13:13 +0930 Subject: [PATCH 4/6] Remove babel configs from eject. --- config/babel.dev.js | 18 +----------------- config/babel.prod.js | 13 +------------ config/jest/transform.js | 8 +++++++- config/webpack.config.dev.js | 11 ++++++++++- config/webpack.config.prod.js | 2 ++ scripts/eject.js | 2 -- 6 files changed, 21 insertions(+), 33 deletions(-) diff --git a/config/babel.dev.js b/config/babel.dev.js index 5a56c03a32d..59b12fa490e 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -8,27 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ // @remove-on-eject-end - - -// After eject -module.exports = function () { - return { - // This is a feature of `babel-loader` for webpack (not Babel itself). - // It enables caching results in OS temporary directory for faster rebuilds. - cacheDirectory: true - }; -} - -// @remove-on-eject-begin var path = require('path'); -// Before eject + module.exports = function (resolvePaths) { return { // Don't try to find .babelrc because we want to force this configuration. babelrc: false, - // This is a feature of `babel-loader` for webpack (not Babel itself). - // It enables caching results in OS temporary directory for faster rebuilds. - cacheDirectory: true, presets: [ // Latest stable ECMAScript features 'babel-preset-latest', @@ -71,4 +56,3 @@ module.exports = function (resolvePaths) { }) } }; -// @remove-on-eject-end diff --git a/config/babel.prod.js b/config/babel.prod.js index 8dcdfa526f6..1bdfdad8f05 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -8,18 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ // @remove-on-eject-end - - -// After eject -// Config is empty as .babelrc now exists. -// Export an empty object as webpack.config.prod.js expects to find one. -module.exports = function () { - return {}; -}; - -// @remove-on-eject-begin var path = require('path'); -// Before eject + module.exports = function (resolvePaths) { return { // Don't try to find .babelrc because we want to force this configuration. @@ -72,4 +62,3 @@ module.exports = function (resolvePaths) { }) }; }; -// @remove-on-eject-end diff --git a/config/jest/transform.js b/config/jest/transform.js index b38c50acdaa..9380abb4344 100644 --- a/config/jest/transform.js +++ b/config/jest/transform.js @@ -8,7 +8,13 @@ */ // @remove-on-eject-end -const babelDev = require('../babel.dev')(true); const babelJest = require('babel-jest'); +// After Eject +module.exports = babelJest.createTransformer(); + +// @remove-on-eject-begin +// Before Eject +const babelDev = require('../babel.dev')(true); module.exports = babelJest.createTransformer(babelDev); +// @remove-on-eject-end diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 898c14c522d..43e33ea609c 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -107,7 +107,16 @@ module.exports = { test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel', - query: require('./babel.dev')(true) + query: Object.assign({}, + // @remove-on-eject-begin + require('./babel.dev')(true), + // @remove-on-eject-end + { + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in OS temporary directory for faster rebuilds. + cacheDirectory: true + } + ) }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 16c63b6709f..4d7df409f84 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -102,7 +102,9 @@ module.exports = { test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel', + // @remove-on-eject-begin query: require('./babel.prod')(true) + // @remove-on-eject-end }, // The notation here is somewhat confusing. // "postcss" loader applies autoprefixer to our CSS. diff --git a/scripts/eject.js b/scripts/eject.js index 8e6f4b08cb8..13a9fb9253b 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -31,8 +31,6 @@ prompt( var ownPath = path.join(__dirname, '..'); var appPath = path.join(ownPath, '..', '..'); var files = [ - path.join('config', 'babel.dev.js'), - path.join('config', 'babel.prod.js'), path.join('config', 'flow', 'css.js.flow'), path.join('config', 'flow', 'file.js.flow'), path.join('config', 'eslint.js'), From 8a4f1854883b6f1f71a3607be45af24249ca9704 Mon Sep 17 00:00:00 2001 From: James Blight Date: Tue, 13 Sep 2016 01:26:45 +0930 Subject: [PATCH 5/6] Ensure ejected .babelrc doesn't overwrite an existing file. --- scripts/eject.js | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/scripts/eject.js b/scripts/eject.js index 13a9fb9253b..f77e4c4960e 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -33,6 +33,8 @@ prompt( var files = [ path.join('config', 'flow', 'css.js.flow'), path.join('config', 'flow', 'file.js.flow'), + // .babelrc is generated from the dev and prod configs + path.join('config', '.babelrc'), path.join('config', 'eslint.js'), path.join('config', 'paths.js'), path.join('config', 'env.js'), @@ -49,27 +51,7 @@ prompt( path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js') ]; - // Ensure that the app folder is clean and we won't override any files - files.forEach(function(file) { - if (fs.existsSync(path.join(appPath, file))) { - console.error( - '`' + file + '` already exists in your app folder. We cannot ' + - 'continue as you would lose all the changes in that file or directory. ' + - 'Please delete it (maybe make a copy for backup) and run this ' + - 'command again.' - ); - process.exit(1); - } - }); - - // Copy the files over - fs.mkdirSync(path.join(appPath, 'config')); - fs.mkdirSync(path.join(appPath, 'config', 'flow')); - fs.mkdirSync(path.join(appPath, 'config', 'jest')); - fs.mkdirSync(path.join(appPath, 'scripts')); - fs.mkdirSync(path.join(appPath, 'scripts', 'utils')); - - // Create .babelrc from dev and prod configs before dead code is removed + // Create .babelrc from dev and prod configs before copying var babelrc = { env: { test: { @@ -88,10 +70,31 @@ prompt( }; fs.writeFileSync( - path.join(appPath, 'config', '.babelrc'), + path.join(ownPath, 'config', '.babelrc'), JSON.stringify(babelrc, null, 2) ); + // Ensure that the app folder is clean and we won't override any files + files.forEach(function(file) { + if (fs.existsSync(path.join(appPath, file))) { + console.error( + '`' + file + '` already exists in your app folder. We cannot ' + + 'continue as you would lose all the changes in that file or directory. ' + + 'Please delete it (maybe make a copy for backup) and run this ' + + 'command again.' + ); + process.exit(1); + } + }); + + // Copy the files over + fs.mkdirSync(path.join(appPath, 'config')); + fs.mkdirSync(path.join(appPath, 'config', 'flow')); + fs.mkdirSync(path.join(appPath, 'config', 'jest')); + fs.mkdirSync(path.join(appPath, 'scripts')); + fs.mkdirSync(path.join(appPath, 'scripts', 'utils')); + + files.forEach(function(file) { console.log('Copying ' + file + ' to ' + appPath); var content = fs From 736c2f41058d241c0f2da4224466742397d84c42 Mon Sep 17 00:00:00 2001 From: James Blight Date: Wed, 14 Sep 2016 08:52:01 +0930 Subject: [PATCH 6/6] Only create a .babelrc file if one doesn't already exist in the app config folder. --- scripts/eject.js | 61 ++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/scripts/eject.js b/scripts/eject.js index f77e4c4960e..9d21be36771 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -33,8 +33,6 @@ prompt( var files = [ path.join('config', 'flow', 'css.js.flow'), path.join('config', 'flow', 'file.js.flow'), - // .babelrc is generated from the dev and prod configs - path.join('config', '.babelrc'), path.join('config', 'eslint.js'), path.join('config', 'paths.js'), path.join('config', 'env.js'), @@ -51,29 +49,6 @@ prompt( path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js') ]; - // Create .babelrc from dev and prod configs before copying - var babelrc = { - env: { - test: { - presets: babelDevConfig.presets, - plugins: babelDevConfig.plugins - }, - development: { - presets: babelDevConfig.presets, - plugins: babelDevConfig.plugins - }, - production: { - presets: babelProdConfig.presets, - plugins: babelProdConfig.plugins - } - } - }; - - fs.writeFileSync( - path.join(ownPath, 'config', '.babelrc'), - JSON.stringify(babelrc, null, 2) - ); - // Ensure that the app folder is clean and we won't override any files files.forEach(function(file) { if (fs.existsSync(path.join(appPath, file))) { @@ -87,6 +62,17 @@ prompt( } }); + // Ensure a .babelrc file doesn't exist in the app config folder + if (fs.existsSync(path.join(appPath, 'config', '.babelrc'))) { + console.error( + 'config/.babelrc already exists in your app folder. We cannot ' + + 'continue as you would lose all the changes in that file ' + + 'Please delete it (maybe make a copy for backup) and run this ' + + 'command again. You might have to manually merge your configs.' + ); + process.exit(1); + } + // Copy the files over fs.mkdirSync(path.join(appPath, 'config')); fs.mkdirSync(path.join(appPath, 'config', 'flow')); @@ -108,6 +94,31 @@ prompt( }); console.log(); + // Create .babelrc from dev and prod configs + var babelrc = { + env: { + test: { + presets: babelDevConfig.presets, + plugins: babelDevConfig.plugins + }, + development: { + presets: babelDevConfig.presets, + plugins: babelDevConfig.plugins + }, + production: { + presets: babelProdConfig.presets, + plugins: babelProdConfig.plugins + } + } + }; + + console.log('Writing config/.babelrc to ' + appPath ); + fs.writeFileSync( + path.join(appPath, 'config', '.babelrc'), + JSON.stringify(babelrc, null, 2) + ); + console.log(); + var ownPackage = require(path.join(ownPath, 'package.json')); var appPackage = require(path.join(appPath, 'package.json'));