From 6bd63812ce444c85b0cdb51322ba89b4a23d8e85 Mon Sep 17 00:00:00 2001 From: Daniel Grant Date: Mon, 23 Jan 2017 22:34:21 +0000 Subject: [PATCH 1/8] Refactor start script into modules --- packages/react-scripts/scripts/start.js | 266 ++---------------- .../utils/addWebpackMiddleware.js | 96 +++++++ .../utils/createWebpackCompiler.js | 100 +++++++ .../utils/createWebpackDevServer.js | 51 ++++ 4 files changed, 266 insertions(+), 247 deletions(-) create mode 100644 packages/react-scripts/utils/addWebpackMiddleware.js create mode 100644 packages/react-scripts/utils/createWebpackCompiler.js create mode 100644 packages/react-scripts/utils/createWebpackDevServer.js diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index 5d2fd8a852..a81c3a5829 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -17,21 +17,19 @@ process.env.NODE_ENV = 'development'; // https://github.com/motdotla/dotenv require('dotenv').config({silent: true}); +var fs = require('fs'); var chalk = require('chalk'); -var webpack = require('webpack'); -var WebpackDevServer = require('webpack-dev-server'); -var historyApiFallback = require('connect-history-api-fallback'); -var httpProxyMiddleware = require('http-proxy-middleware'); var detect = require('detect-port'); var clearConsole = require('react-dev-utils/clearConsole'); var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); -var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); var getProcessForPort = require('react-dev-utils/getProcessForPort'); var openBrowser = require('react-dev-utils/openBrowser'); var prompt = require('react-dev-utils/prompt'); -var fs = require('fs'); -var config = require('../config/webpack.config.dev'); var paths = require('../config/paths'); +var config = require('../config/webpack.config.dev'); +var createWebpackCompiler = require('../utils/createWebpackCompiler'); +var createWebpackDevServer = require('../utils/createWebpackDevServer'); +var addWebpackMiddleware = require('../utils/addWebpackMiddleware'); var useYarn = fs.existsSync(paths.yarnLockFile); var cli = useYarn ? 'yarn' : 'npm'; @@ -44,247 +42,28 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { // Tools like Cloud9 rely on this. var DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; -var compiler; -var handleCompile; -// You can safely remove this after ejecting. -// We only use this block for testing of Create React App itself: -var isSmokeTest = process.argv.some(arg => arg.indexOf('--smoke-test') > -1); -if (isSmokeTest) { - handleCompile = function (err, stats) { - if (err || stats.hasErrors() || stats.hasWarnings()) { - process.exit(1); - } else { - process.exit(0); - } - }; -} +function run(port) { + var protocol = process.env.HTTPS === 'true' ? "https" : "http"; + var host = process.env.HOST || 'localhost'; -function setupCompiler(host, port, protocol) { - // "Compiler" is a low-level interface to Webpack. - // It lets us listen to some events and provide our own custom messages. - try { - compiler = webpack(config, handleCompile); - } catch (err) { - console.log(chalk.red('Failed to compile.')); + // Create a webpack compiler that is configured with custom messages. + var compiler = createWebpackCompiler(config, function onReady() { console.log(); - console.log(err.message || err); + console.log('The app is running at:'); console.log(); - process.exit(1); - } - - // "invalid" event fires when you have changed a file, and Webpack is - // recompiling a bundle. WebpackDevServer takes care to pause serving the - // bundle, so if you refresh, it'll wait instead of serving the old one. - // "invalid" is short for "bundle invalidated", it doesn't imply any errors. - compiler.plugin('invalid', function() { - if (isInteractive) { - clearConsole(); - } - console.log('Compiling...'); - }); - - var isFirstCompile = true; - - // "done" event fires when Webpack has finished recompiling the bundle. - // Whether or not you have warnings or errors, you will get this event. - compiler.plugin('done', function(stats) { - if (isInteractive) { - clearConsole(); - } - - // We have switched off the default Webpack output in WebpackDevServer - // options so we are going to "massage" the warnings and errors and present - // them in a readable focused way. - var messages = formatWebpackMessages(stats.toJson({}, true)); - var isSuccessful = !messages.errors.length && !messages.warnings.length; - var showInstructions = isSuccessful && (isInteractive || isFirstCompile); - - if (isSuccessful) { - console.log(chalk.green('Compiled successfully!')); - } - - if (showInstructions) { - console.log(); - console.log('The app is running at:'); - console.log(); - console.log(' ' + chalk.cyan(protocol + '://' + host + ':' + port + '/')); - console.log(); - console.log('Note that the development build is not optimized.'); - console.log('To create a production build, use ' + chalk.cyan(cli + ' run build') + '.'); - console.log(); - isFirstCompile = false; - } - - // If errors exist, only show errors. - if (messages.errors.length) { - console.log(chalk.red('Failed to compile.')); - console.log(); - messages.errors.forEach(message => { - console.log(message); - console.log(); - }); - return; - } - - // Show warnings if no errors were found. - if (messages.warnings.length) { - console.log(chalk.yellow('Compiled with warnings.')); - console.log(); - messages.warnings.forEach(message => { - console.log(message); - console.log(); - }); - // Teach some ESLint tricks. - console.log('You may use special comments to disable some warnings.'); - console.log('Use ' + chalk.yellow('// eslint-disable-next-line') + ' to ignore the next line.'); - console.log('Use ' + chalk.yellow('/* eslint-disable */') + ' to ignore all warnings in a file.'); - } - }); -} - -// We need to provide a custom onError function for httpProxyMiddleware. -// It allows us to log custom error messages on the console. -function onProxyError(proxy) { - return function(err, req, res){ - var host = req.headers && req.headers.host; - console.log( - chalk.red('Proxy error:') + ' Could not proxy request ' + chalk.cyan(req.url) + - ' from ' + chalk.cyan(host) + ' to ' + chalk.cyan(proxy) + '.' - ); - console.log( - 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' + - chalk.cyan(err.code) + ').' - ); + console.log(' ' + chalk.cyan(protocol + '://' + host + ':' + port + '/')); + console.log(); + console.log('Note that the development build is not optimized.'); + console.log('To create a production build, use ' + chalk.cyan(cli + ' run build') + '.'); console.log(); - - // And immediately send the proper error response to the client. - // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side. - if (res.writeHead && !res.headersSent) { - res.writeHead(500); - } - res.end('Proxy error: Could not proxy request ' + req.url + ' from ' + - host + ' to ' + proxy + ' (' + err.code + ').' - ); - } -} - -function addMiddleware(devServer) { - // `proxy` lets you to specify a fallback server during development. - // Every unrecognized request will be forwarded to it. - var proxy = require(paths.appPackageJson).proxy; - devServer.use(historyApiFallback({ - // Paths with dots should still use the history fallback. - // See https://github.com/facebookincubator/create-react-app/issues/387. - disableDotRule: true, - // For single page apps, we generally want to fallback to /index.html. - // However we also want to respect `proxy` for API calls. - // So if `proxy` is specified, we need to decide which fallback to use. - // We use a heuristic: if request `accept`s text/html, we pick /index.html. - // Modern browsers include text/html into `accept` header when navigating. - // However API calls like `fetch()` won’t generally accept text/html. - // If this heuristic doesn’t work well for you, don’t use `proxy`. - htmlAcceptHeaders: proxy ? - ['text/html'] : - ['text/html', '*/*'] - })); - if (proxy) { - if (typeof proxy !== 'string') { - console.log(chalk.red('When specified, "proxy" in package.json must be a string.')); - console.log(chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".')); - console.log(chalk.red('Either remove "proxy" from package.json, or make it a string.')); - process.exit(1); - } - - // Otherwise, if proxy is specified, we will let it handle any request. - // There are a few exceptions which we won't send to the proxy: - // - /index.html (served as HTML5 history API fallback) - // - /*.hot-update.json (WebpackDevServer uses this too for hot reloading) - // - /sockjs-node/* (WebpackDevServer uses this for hot reloading) - // Tip: use https://jex.im/regulex/ to visualize the regex - var mayProxy = /^(?!\/(index\.html$|.*\.hot-update\.json$|sockjs-node\/)).*$/; - - // Pass the scope regex both to Express and to the middleware for proxying - // of both HTTP and WebSockets to work without false positives. - var hpm = httpProxyMiddleware(pathname => mayProxy.test(pathname), { - target: proxy, - logLevel: 'silent', - onProxyReq: function(proxyReq, req, res) { - // Browers may send Origin headers even with same-origin - // requests. To prevent CORS issues, we have to change - // the Origin to match the target URL. - if (proxyReq.getHeader('origin')) { - proxyReq.setHeader('origin', proxy); - } - }, - onError: onProxyError(proxy), - secure: false, - changeOrigin: true, - ws: true, - xfwd: true - }); - devServer.use(mayProxy, hpm); - - // Listen for the websocket 'upgrade' event and upgrade the connection. - // If this is not done, httpProxyMiddleware will not try to upgrade until - // an initial plain HTTP request is made. - devServer.listeningApp.on('upgrade', hpm.upgrade); - } - - // Finally, by now we have certainly resolved the URL. - // It may be /index.html, so let the dev server try serving it again. - devServer.use(devServer.middleware); -} - -function runDevServer(host, port, protocol) { - var devServer = new WebpackDevServer(compiler, { - // Enable gzip compression of generated files. - compress: true, - // Silence WebpackDevServer's own logs since they're generally not useful. - // It will still show compile warnings and errors with this setting. - clientLogLevel: 'none', - // By default WebpackDevServer serves physical files from current directory - // in addition to all the virtual build products that it serves from memory. - // This is confusing because those files won’t automatically be available in - // production build folder unless we copy them. However, copying the whole - // project directory is dangerous because we may expose sensitive files. - // Instead, we establish a convention that only files in `public` directory - // get served. Our build script will copy `public` into the `build` folder. - // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%: - // - // In JavaScript code, you can access it with `process.env.PUBLIC_URL`. - // Note that we only recommend to use `public` folder as an escape hatch - // for files like `favicon.ico`, `manifest.json`, and libraries that are - // for some reason broken when imported through Webpack. If you just want to - // use an image, put it in `src` and `import` it from JavaScript instead. - contentBase: paths.appPublic, - // By default files from `contentBase` will not trigger a page reload. - watchContentBase: true, - // Enable hot reloading server. It will provide /sockjs-node/ endpoint - // for the WebpackDevServer client so it can learn when the files were - // updated. The WebpackDevServer client is included as an entry point - // in the Webpack development configuration. Note that only changes - // to CSS are currently hot reloaded. JS changes will refresh the browser. - hot: true, - // It is important to tell WebpackDevServer to use the same "root" path - // as we specified in the config. In development, we always serve from /. - publicPath: config.output.publicPath, - // WebpackDevServer is noisy by default so we emit custom message instead - // by listening to the compiler events with `compiler.plugin` calls above. - quiet: true, - // Reportedly, this avoids CPU overload on some systems. - // https://github.com/facebookincubator/create-react-app/issues/293 - watchOptions: { - ignored: /node_modules/ - }, - // Enable HTTPS if the HTTPS environment variable is set to 'true' - https: protocol === "https", - host: host, - overlay: false, }); + // Serve webpack assets generated by the compiler over http. + var devServer = createWebpackDevServer(compiler, protocol, host); + // Our custom middleware proxies requests to /index.html or a remote API. - addMiddleware(devServer); + addWebpackMiddleware(devServer); // Launch WebpackDevServer. devServer.listen(port, (err, result) => { @@ -302,13 +81,6 @@ function runDevServer(host, port, protocol) { }); } -function run(port) { - var protocol = process.env.HTTPS === 'true' ? "https" : "http"; - var host = process.env.HOST || 'localhost'; - setupCompiler(host, port, protocol); - runDevServer(host, port, protocol); -} - // We attempt to use the default port but if it is busy, we offer the user to // run on a different port. `detect()` Promise resolves to the next free port. detect(DEFAULT_PORT).then(port => { diff --git a/packages/react-scripts/utils/addWebpackMiddleware.js b/packages/react-scripts/utils/addWebpackMiddleware.js new file mode 100644 index 0000000000..4987853985 --- /dev/null +++ b/packages/react-scripts/utils/addWebpackMiddleware.js @@ -0,0 +1,96 @@ +var historyApiFallback = require('connect-history-api-fallback'); +var httpProxyMiddleware = require('http-proxy-middleware'); +var paths = require('../config/paths'); +var chalk = require('chalk'); + +module.exports = function addMiddleware(devServer) { + // `proxy` lets you to specify a fallback server during development. + // Every unrecognized request will be forwarded to it. + var proxy = require(paths.appPackageJson).proxy; + devServer.use(historyApiFallback({ + // Paths with dots should still use the history fallback. + // See https://github.com/facebookincubator/create-react-app/issues/387. + disableDotRule: true, + // For single page apps, we generally want to fallback to /index.html. + // However we also want to respect `proxy` for API calls. + // So if `proxy` is specified, we need to decide which fallback to use. + // We use a heuristic: if request `accept`s text/html, we pick /index.html. + // Modern browsers include text/html into `accept` header when navigating. + // However API calls like `fetch()` won’t generally accept text/html. + // If this heuristic doesn’t work well for you, don’t use `proxy`. + htmlAcceptHeaders: proxy ? + ['text/html'] : + ['text/html', '*/*'] + })); + if (proxy) { + if (typeof proxy !== 'string') { + console.log(chalk.red('When specified, "proxy" in package.json must be a string.')); + console.log(chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".')); + console.log(chalk.red('Either remove "proxy" from package.json, or make it a string.')); + process.exit(1); + } + + // Otherwise, if proxy is specified, we will let it handle any request. + // There are a few exceptions which we won't send to the proxy: + // - /index.html (served as HTML5 history API fallback) + // - /*.hot-update.json (WebpackDevServer uses this too for hot reloading) + // - /sockjs-node/* (WebpackDevServer uses this for hot reloading) + // Tip: use https://jex.im/regulex/ to visualize the regex + var mayProxy = /^(?!\/(index\.html$|.*\.hot-update\.json$|sockjs-node\/)).*$/; + + // Pass the scope regex both to Express and to the middleware for proxying + // of both HTTP and WebSockets to work without false positives. + var hpm = httpProxyMiddleware(pathname => mayProxy.test(pathname), { + target: proxy, + logLevel: 'silent', + onProxyReq: function(proxyReq, req, res) { + // Browers may send Origin headers even with same-origin + // requests. To prevent CORS issues, we have to change + // the Origin to match the target URL. + if (proxyReq.getHeader('origin')) { + proxyReq.setHeader('origin', proxy); + } + }, + onError: onProxyError(proxy), + secure: false, + changeOrigin: true, + ws: true + }); + devServer.use(mayProxy, hpm); + + // Listen for the websocket 'upgrade' event and upgrade the connection. + // If this is not done, httpProxyMiddleware will not try to upgrade until + // an initial plain HTTP request is made. + devServer.listeningApp.on('upgrade', hpm.upgrade); + } + + // Finally, by now we have certainly resolved the URL. + // It may be /index.html, so let the dev server try serving it again. + devServer.use(devServer.middleware); +}; + +// We need to provide a custom onError function for httpProxyMiddleware. +// It allows us to log custom error messages on the console. +function onProxyError(proxy) { + return function(err, req, res){ + var host = req.headers && req.headers.host; + console.log( + chalk.red('Proxy error:') + ' Could not proxy request ' + chalk.cyan(req.url) + + ' from ' + chalk.cyan(host) + ' to ' + chalk.cyan(proxy) + '.' + ); + console.log( + 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' + + chalk.cyan(err.code) + ').' + ); + console.log(); + + // And immediately send the proper error response to the client. + // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side. + if (res.writeHead && !res.headersSent) { + res.writeHead(500); + } + res.end('Proxy error: Could not proxy request ' + req.url + ' from ' + + host + ' to ' + proxy + ' (' + err.code + ').' + ); + } +} diff --git a/packages/react-scripts/utils/createWebpackCompiler.js b/packages/react-scripts/utils/createWebpackCompiler.js new file mode 100644 index 0000000000..516755b761 --- /dev/null +++ b/packages/react-scripts/utils/createWebpackCompiler.js @@ -0,0 +1,100 @@ +var chalk = require('chalk'); +var webpack = require('webpack'); +var clearConsole = require('react-dev-utils/clearConsole'); +var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); + +var isInteractive = process.stdout.isTTY; +var handleCompile; + +// You can safely remove this after ejecting. +// We only use this block for testing of Create React App itself: +var isSmokeTest = process.argv.some(arg => arg.indexOf('--smoke-test') > -1); +if (isSmokeTest) { + handleCompile = function (err, stats) { + if (err || stats.hasErrors() || stats.hasWarnings()) { + process.exit(1); + } else { + process.exit(0); + } + }; +} + +module.exports = function createCompiler(config, onReadyCallack) { + // "Compiler" is a low-level interface to Webpack. + // It lets us listen to some events and provide our own custom messages. + try { + var compiler = webpack(config, handleCompile); + } catch (err) { + console.log(chalk.red('Failed to compile.')); + console.log(); + console.log(err.message || err); + console.log(); + process.exit(1); + } + + // "invalid" event fires when you have changed a file, and Webpack is + // recompiling a bundle. WebpackDevServer takes care to pause serving the + // bundle, so if you refresh, it'll wait instead of serving the old one. + // "invalid" is short for "bundle invalidated", it doesn't imply any errors. + compiler.plugin('invalid', function() { + if (isInteractive) { + clearConsole(); + } + console.log('Compiling...'); + }); + + var isFirstCompile = true; + + // "done" event fires when Webpack has finished recompiling the bundle. + // Whether or not you have warnings or errors, you will get this event. + compiler.plugin('done', function(stats) { + if (isInteractive) { + clearConsole(); + } + + // We have switched off the default Webpack output in WebpackDevServer + // options so we are going to "massage" the warnings and errors and present + // them in a readable focused way. + var messages = formatWebpackMessages(stats.toJson({}, true)); + var isSuccessful = !messages.errors.length && !messages.warnings.length; + var showInstructions = isSuccessful && (isInteractive || isFirstCompile); + + if (isSuccessful) { + console.log(chalk.green('Compiled successfully!')); + } + + if (showInstructions) { + if (typeof onReadyCallack === 'function') { + onReadyCallack(); + } + isFirstCompile = false; + } + + // If errors exist, only show errors. + if (messages.errors.length) { + console.log(chalk.red('Failed to compile.')); + console.log(); + messages.errors.forEach(message => { + console.log(message); + console.log(); + }); + return; + } + + // Show warnings if no errors were found. + if (messages.warnings.length) { + console.log(chalk.yellow('Compiled with warnings.')); + console.log(); + messages.warnings.forEach(message => { + console.log(message); + console.log(); + }); + // Teach some ESLint tricks. + console.log('You may use special comments to disable some warnings.'); + console.log('Use ' + chalk.yellow('// eslint-disable-next-line') + ' to ignore the next line.'); + console.log('Use ' + chalk.yellow('/* eslint-disable */') + ' to ignore all warnings in a file.'); + } + }); + + return compiler; +} diff --git a/packages/react-scripts/utils/createWebpackDevServer.js b/packages/react-scripts/utils/createWebpackDevServer.js new file mode 100644 index 0000000000..b5b1334492 --- /dev/null +++ b/packages/react-scripts/utils/createWebpackDevServer.js @@ -0,0 +1,51 @@ +var WebpackDevServer = require('webpack-dev-server'); +var config = require('../config/webpack.config.dev'); +var paths = require('../config/paths'); + +module.exports = function createWebpackDevServer(compiler, protocol, host) { + return new WebpackDevServer(compiler, { + // Enable gzip compression of generated files. + compress: true, + // Silence WebpackDevServer's own logs since they're generally not useful. + // It will still show compile warnings and errors with this setting. + clientLogLevel: 'none', + // By default WebpackDevServer serves physical files from current directory + // in addition to all the virtual build products that it serves from memory. + // This is confusing because those files won’t automatically be available in + // production build folder unless we copy them. However, copying the whole + // project directory is dangerous because we may expose sensitive files. + // Instead, we establish a convention that only files in `public` directory + // get served. Our build script will copy `public` into the `build` folder. + // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%: + // + // In JavaScript code, you can access it with `process.env.PUBLIC_URL`. + // Note that we only recommend to use `public` folder as an escape hatch + // for files like `favicon.ico`, `manifest.json`, and libraries that are + // for some reason broken when imported through Webpack. If you just want to + // use an image, put it in `src` and `import` it from JavaScript instead. + contentBase: paths.appPublic, + // By default files from `contentBase` will not trigger a page reload. + watchContentBase: true, + // Enable hot reloading server. It will provide /sockjs-node/ endpoint + // for the WebpackDevServer client so it can learn when the files were + // updated. The WebpackDevServer client is included as an entry point + // in the Webpack development configuration. Note that only changes + // to CSS are currently hot reloaded. JS changes will refresh the browser. + hot: true, + // It is important to tell WebpackDevServer to use the same "root" path + // as we specified in the config. In development, we always serve from /. + publicPath: config.output.publicPath, + // WebpackDevServer is noisy by default so we emit custom message instead + // by listening to the compiler events with `compiler.plugin` calls above. + quiet: true, + // Reportedly, this avoids CPU overload on some systems. + // https://github.com/facebookincubator/create-react-app/issues/293 + watchOptions: { + ignored: /node_modules/ + }, + // Enable HTTPS if the HTTPS environment variable is set to 'true' + https: protocol === "https", + host: host, + overlay: false + }); +} From 073cb55f59ce487103af86079ade7b8ef1d51d6f Mon Sep 17 00:00:00 2001 From: Daniel Grant Date: Wed, 25 Jan 2017 22:10:59 +0000 Subject: [PATCH 2/8] Move dev server config into config file --- .../config/webpackDevServer.config.js | 48 +++++++++++++++++ packages/react-scripts/scripts/start.js | 7 +-- .../utils/createWebpackDevServer.js | 51 ------------------- 3 files changed, 52 insertions(+), 54 deletions(-) create mode 100644 packages/react-scripts/config/webpackDevServer.config.js delete mode 100644 packages/react-scripts/utils/createWebpackDevServer.js diff --git a/packages/react-scripts/config/webpackDevServer.config.js b/packages/react-scripts/config/webpackDevServer.config.js new file mode 100644 index 0000000000..06ac14c467 --- /dev/null +++ b/packages/react-scripts/config/webpackDevServer.config.js @@ -0,0 +1,48 @@ +var config = require('./webpack.config.dev'); +var paths = require('./paths'); + +var protocol = process.env.HTTPS === 'true' ? "https" : "http"; +var host = process.env.HOST || 'localhost'; + +module.exports = { + // Enable gzip compression of generated files. + compress: true, + // Silence WebpackDevServer's own logs since they're generally not useful. + // It will still show compile warnings and errors with this setting. + clientLogLevel: 'none', + // By default WebpackDevServer serves physical files from current directory + // in addition to all the virtual build products that it serves from memory. + // This is confusing because those files won’t automatically be available in + // production build folder unless we copy them. However, copying the whole + // project directory is dangerous because we may expose sensitive files. + // Instead, we establish a convention that only files in `public` directory + // get served. Our build script will copy `public` into the `build` folder. + // In `index.html`, you can get URL of `public` folder with %PUBLIC_PATH%: + // + // In JavaScript code, you can access it with `process.env.PUBLIC_URL`. + // Note that we only recommend to use `public` folder as an escape hatch + // for files like `favicon.ico`, `manifest.json`, and libraries that are + // for some reason broken when imported through Webpack. If you just want to + // use an image, put it in `src` and `import` it from JavaScript instead. + contentBase: paths.appPublic, + // Enable hot reloading server. It will provide /sockjs-node/ endpoint + // for the WebpackDevServer client so it can learn when the files were + // updated. The WebpackDevServer client is included as an entry point + // in the Webpack development configuration. Note that only changes + // to CSS are currently hot reloaded. JS changes will refresh the browser. + hot: true, + // It is important to tell WebpackDevServer to use the same "root" path + // as we specified in the config. In development, we always serve from /. + publicPath: config.output.publicPath, + // WebpackDevServer is noisy by default so we emit custom message instead + // by listening to the compiler events with `compiler.plugin` calls above. + quiet: true, + // Reportedly, this avoids CPU overload on some systems. + // https://github.com/facebookincubator/create-react-app/issues/293 + watchOptions: { + ignored: /node_modules/ + }, + // Enable HTTPS if the HTTPS environment variable is set to 'true' + https: protocol === "https", + host: host +}; diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index a81c3a5829..d5d4c7880a 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -20,6 +20,7 @@ require('dotenv').config({silent: true}); var fs = require('fs'); var chalk = require('chalk'); var detect = require('detect-port'); +var WebpackDevServer = require('webpack-dev-server'); var clearConsole = require('react-dev-utils/clearConsole'); var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); var getProcessForPort = require('react-dev-utils/getProcessForPort'); @@ -27,8 +28,8 @@ var openBrowser = require('react-dev-utils/openBrowser'); var prompt = require('react-dev-utils/prompt'); var paths = require('../config/paths'); var config = require('../config/webpack.config.dev'); +var devServerConfig = require('../config/webpackDevServer.config'); var createWebpackCompiler = require('../utils/createWebpackCompiler'); -var createWebpackDevServer = require('../utils/createWebpackDevServer'); var addWebpackMiddleware = require('../utils/addWebpackMiddleware'); var useYarn = fs.existsSync(paths.yarnLockFile); @@ -59,8 +60,8 @@ function run(port) { console.log(); }); - // Serve webpack assets generated by the compiler over http. - var devServer = createWebpackDevServer(compiler, protocol, host); + // Serve webpack assets generated by the compiler over a web sever. + var devServer = new WebpackDevServer(compiler, devServerConfig); // Our custom middleware proxies requests to /index.html or a remote API. addWebpackMiddleware(devServer); diff --git a/packages/react-scripts/utils/createWebpackDevServer.js b/packages/react-scripts/utils/createWebpackDevServer.js deleted file mode 100644 index b5b1334492..0000000000 --- a/packages/react-scripts/utils/createWebpackDevServer.js +++ /dev/null @@ -1,51 +0,0 @@ -var WebpackDevServer = require('webpack-dev-server'); -var config = require('../config/webpack.config.dev'); -var paths = require('../config/paths'); - -module.exports = function createWebpackDevServer(compiler, protocol, host) { - return new WebpackDevServer(compiler, { - // Enable gzip compression of generated files. - compress: true, - // Silence WebpackDevServer's own logs since they're generally not useful. - // It will still show compile warnings and errors with this setting. - clientLogLevel: 'none', - // By default WebpackDevServer serves physical files from current directory - // in addition to all the virtual build products that it serves from memory. - // This is confusing because those files won’t automatically be available in - // production build folder unless we copy them. However, copying the whole - // project directory is dangerous because we may expose sensitive files. - // Instead, we establish a convention that only files in `public` directory - // get served. Our build script will copy `public` into the `build` folder. - // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%: - // - // In JavaScript code, you can access it with `process.env.PUBLIC_URL`. - // Note that we only recommend to use `public` folder as an escape hatch - // for files like `favicon.ico`, `manifest.json`, and libraries that are - // for some reason broken when imported through Webpack. If you just want to - // use an image, put it in `src` and `import` it from JavaScript instead. - contentBase: paths.appPublic, - // By default files from `contentBase` will not trigger a page reload. - watchContentBase: true, - // Enable hot reloading server. It will provide /sockjs-node/ endpoint - // for the WebpackDevServer client so it can learn when the files were - // updated. The WebpackDevServer client is included as an entry point - // in the Webpack development configuration. Note that only changes - // to CSS are currently hot reloaded. JS changes will refresh the browser. - hot: true, - // It is important to tell WebpackDevServer to use the same "root" path - // as we specified in the config. In development, we always serve from /. - publicPath: config.output.publicPath, - // WebpackDevServer is noisy by default so we emit custom message instead - // by listening to the compiler events with `compiler.plugin` calls above. - quiet: true, - // Reportedly, this avoids CPU overload on some systems. - // https://github.com/facebookincubator/create-react-app/issues/293 - watchOptions: { - ignored: /node_modules/ - }, - // Enable HTTPS if the HTTPS environment variable is set to 'true' - https: protocol === "https", - host: host, - overlay: false - }); -} From d606bcc51b406dd9675e64f303d5eb79c2c889dc Mon Sep 17 00:00:00 2001 From: Daniel Grant Date: Thu, 26 Jan 2017 02:08:53 +0000 Subject: [PATCH 3/8] Replace eject file whitelist with a "remove-file-on-eject" flag --- packages/react-scripts/scripts/eject.js | 54 +++++++++++-------- packages/react-scripts/scripts/init.js | 1 + .../react-scripts/utils/createJestConfig.js | 3 +- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js index 701907fa43..57158cbada 100644 --- a/packages/react-scripts/scripts/eject.js +++ b/packages/react-scripts/scripts/eject.js @@ -1,3 +1,4 @@ +// @remove-file-on-eject /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -7,13 +8,14 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -var createJestConfig = require('../utils/createJestConfig'); var fs = require('fs-extra'); var path = require('path'); -var paths = require('../config/paths'); -var prompt = require('react-dev-utils/prompt'); var spawnSync = require('cross-spawn').sync; var chalk = require('chalk'); +var prompt = require('react-dev-utils/prompt'); +var paths = require('../config/paths'); +var createJestConfig = require('../utils/createJestConfig'); + var green = chalk.green; var cyan = chalk.cyan; @@ -45,45 +47,51 @@ prompt( var folders = [ 'config', - path.join('config', 'jest'), + 'config/jest', 'scripts' ]; - var files = [ - path.join('config', 'env.js'), - path.join('config', 'paths.js'), - path.join('config', 'polyfills.js'), - path.join('config', 'webpack.config.dev.js'), - path.join('config', 'webpack.config.prod.js'), - path.join('config', 'jest', 'cssTransform.js'), - path.join('config', 'jest', 'fileTransform.js'), - path.join('scripts', 'build.js'), - path.join('scripts', 'start.js'), - path.join('scripts', 'test.js') - ]; + // Make shallow array of files paths + var files = folders.reduce(function (files, folder) { + return files.concat( + fs.readdirSync(path.join(ownPath, folder)) + // set full path + .map(file => path.join(ownPath, folder, file)) + // omit dirs from file list + .filter(file => fs.lstatSync(file).isFile()) + ); + }, []); // Ensure that the app folder is clean and we won't override any files folders.forEach(verifyAbsent); files.forEach(verifyAbsent); - // Copy the files over + console.log(); + console.log(cyan('Copying files into ' + appPath)); + folders.forEach(function(folder) { fs.mkdirSync(path.join(appPath, folder)) }); - console.log(); - console.log(cyan('Copying files into ' + appPath)); files.forEach(function(file) { - console.log(' Adding ' + cyan(file) + ' to the project'); - var content = fs - .readFileSync(path.join(ownPath, file), 'utf8') + var content = fs.readFileSync(file, 'utf8') + + // Skip flagged files + if (content.match(/\/\/ @remove-file-on-eject/)) { + return; + } + + content = content // Remove dead code from .js files on eject .replace(/\/\/ @remove-on-eject-begin([\s\S]*?)\/\/ @remove-on-eject-end/mg, '') // Remove dead code from .applescript files on eject .replace(/-- @remove-on-eject-begin([\s\S]*?)-- @remove-on-eject-end/mg, '') .trim() + '\n'; - fs.writeFileSync(path.join(appPath, file), content); + + console.log(' Adding ' + cyan(file.replace(ownPath, '')) + ' to the project'); + fs.writeFileSync(file.replace(ownPath, appPath), content); }); + console.log(); var ownPackage = require(path.join(ownPath, 'package.json')); diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index aa62265ccc..33c0777ef4 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -1,3 +1,4 @@ +// @remove-file-on-eject /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. diff --git a/packages/react-scripts/utils/createJestConfig.js b/packages/react-scripts/utils/createJestConfig.js index f1c67c018f..406b818846 100644 --- a/packages/react-scripts/utils/createJestConfig.js +++ b/packages/react-scripts/utils/createJestConfig.js @@ -1,3 +1,4 @@ +// @remove-file-on-eject /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -7,8 +8,6 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -// Note: this file does not exist after ejecting. - const fs = require('fs'); const paths = require('../config/paths'); From 1a3fa312cdb22fe1c8a90305e9cc0b8123a75c2d Mon Sep 17 00:00:00 2001 From: Daniel Grant Date: Thu, 26 Jan 2017 02:22:48 +0000 Subject: [PATCH 4/8] Move utils into scripts folder (for inclusion in ejection) --- packages/react-scripts/scripts/eject.js | 5 +++-- packages/react-scripts/scripts/start.js | 4 ++-- packages/react-scripts/scripts/test.js | 2 +- .../{ => scripts}/utils/addWebpackMiddleware.js | 4 ++-- .../react-scripts/{ => scripts}/utils/createJestConfig.js | 2 +- .../{ => scripts}/utils/createWebpackCompiler.js | 0 6 files changed, 9 insertions(+), 8 deletions(-) rename packages/react-scripts/{ => scripts}/utils/addWebpackMiddleware.js (98%) rename packages/react-scripts/{ => scripts}/utils/createJestConfig.js (97%) rename packages/react-scripts/{ => scripts}/utils/createWebpackCompiler.js (100%) diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js index 57158cbada..13f6a65070 100644 --- a/packages/react-scripts/scripts/eject.js +++ b/packages/react-scripts/scripts/eject.js @@ -14,7 +14,7 @@ var spawnSync = require('cross-spawn').sync; var chalk = require('chalk'); var prompt = require('react-dev-utils/prompt'); var paths = require('../config/paths'); -var createJestConfig = require('../utils/createJestConfig'); +var createJestConfig = require('./utils/createJestConfig'); var green = chalk.green; var cyan = chalk.cyan; @@ -48,7 +48,8 @@ prompt( var folders = [ 'config', 'config/jest', - 'scripts' + 'scripts', + 'scripts/utils' ]; // Make shallow array of files paths diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index d5d4c7880a..652e3e339a 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -29,8 +29,8 @@ var prompt = require('react-dev-utils/prompt'); var paths = require('../config/paths'); var config = require('../config/webpack.config.dev'); var devServerConfig = require('../config/webpackDevServer.config'); -var createWebpackCompiler = require('../utils/createWebpackCompiler'); -var addWebpackMiddleware = require('../utils/addWebpackMiddleware'); +var createWebpackCompiler = require('./utils/createWebpackCompiler'); +var addWebpackMiddleware = require('./utils/addWebpackMiddleware'); var useYarn = fs.existsSync(paths.yarnLockFile); var cli = useYarn ? 'yarn' : 'npm'; diff --git a/packages/react-scripts/scripts/test.js b/packages/react-scripts/scripts/test.js index 9de5181d73..dfd2c75c72 100644 --- a/packages/react-scripts/scripts/test.js +++ b/packages/react-scripts/scripts/test.js @@ -28,7 +28,7 @@ if (!process.env.CI && argv.indexOf('--coverage') < 0) { // @remove-on-eject-begin // This is not necessary after eject because we embed config into package.json. -const createJestConfig = require('../utils/createJestConfig'); +const createJestConfig = require('./utils/createJestConfig'); const path = require('path'); const paths = require('../config/paths'); argv.push('--config', JSON.stringify(createJestConfig( diff --git a/packages/react-scripts/utils/addWebpackMiddleware.js b/packages/react-scripts/scripts/utils/addWebpackMiddleware.js similarity index 98% rename from packages/react-scripts/utils/addWebpackMiddleware.js rename to packages/react-scripts/scripts/utils/addWebpackMiddleware.js index 4987853985..1eccc95ef8 100644 --- a/packages/react-scripts/utils/addWebpackMiddleware.js +++ b/packages/react-scripts/scripts/utils/addWebpackMiddleware.js @@ -1,7 +1,7 @@ +var chalk = require('chalk'); var historyApiFallback = require('connect-history-api-fallback'); var httpProxyMiddleware = require('http-proxy-middleware'); -var paths = require('../config/paths'); -var chalk = require('chalk'); +var paths = require('../../config/paths'); module.exports = function addMiddleware(devServer) { // `proxy` lets you to specify a fallback server during development. diff --git a/packages/react-scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js similarity index 97% rename from packages/react-scripts/utils/createJestConfig.js rename to packages/react-scripts/scripts/utils/createJestConfig.js index 406b818846..c99345b858 100644 --- a/packages/react-scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -9,7 +9,7 @@ */ const fs = require('fs'); -const paths = require('../config/paths'); +const paths = require('../../config/paths'); module.exports = (resolve, rootDir, isEjecting) => { // Use this instead of `paths.testsSetup` to avoid putting diff --git a/packages/react-scripts/utils/createWebpackCompiler.js b/packages/react-scripts/scripts/utils/createWebpackCompiler.js similarity index 100% rename from packages/react-scripts/utils/createWebpackCompiler.js rename to packages/react-scripts/scripts/utils/createWebpackCompiler.js From 38bc01c077fb6ac9cce45bb6ef2c201664f53c35 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Fri, 3 Mar 2017 16:39:21 -0500 Subject: [PATCH 5/8] Add missed changes --- .../config/webpackDevServer.config.js | 11 ++-- packages/react-scripts/scripts/eject.js | 11 ++-- packages/react-scripts/scripts/start.js | 2 +- .../scripts/utils/addWebpackMiddleware.js | 57 ++++++++++--------- .../scripts/utils/createWebpackCompiler.js | 8 +-- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/packages/react-scripts/config/webpackDevServer.config.js b/packages/react-scripts/config/webpackDevServer.config.js index 06ac14c467..4d65567bd7 100644 --- a/packages/react-scripts/config/webpackDevServer.config.js +++ b/packages/react-scripts/config/webpackDevServer.config.js @@ -1,7 +1,7 @@ var config = require('./webpack.config.dev'); var paths = require('./paths'); -var protocol = process.env.HTTPS === 'true' ? "https" : "http"; +var protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; var host = process.env.HOST || 'localhost'; module.exports = { @@ -17,7 +17,7 @@ module.exports = { // project directory is dangerous because we may expose sensitive files. // Instead, we establish a convention that only files in `public` directory // get served. Our build script will copy `public` into the `build` folder. - // In `index.html`, you can get URL of `public` folder with %PUBLIC_PATH%: + // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%: // // In JavaScript code, you can access it with `process.env.PUBLIC_URL`. // Note that we only recommend to use `public` folder as an escape hatch @@ -25,6 +25,8 @@ module.exports = { // for some reason broken when imported through Webpack. If you just want to // use an image, put it in `src` and `import` it from JavaScript instead. contentBase: paths.appPublic, + // By default files from `contentBase` will not trigger a page reload. + watchContentBase: true, // Enable hot reloading server. It will provide /sockjs-node/ endpoint // for the WebpackDevServer client so it can learn when the files were // updated. The WebpackDevServer client is included as an entry point @@ -43,6 +45,7 @@ module.exports = { ignored: /node_modules/ }, // Enable HTTPS if the HTTPS environment variable is set to 'true' - https: protocol === "https", - host: host + https: protocol === 'https', + host: host, + overlay: false, }; diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js index 13f6a65070..5d2b7af0df 100644 --- a/packages/react-scripts/scripts/eject.js +++ b/packages/react-scripts/scripts/eject.js @@ -49,7 +49,7 @@ prompt( 'config', 'config/jest', 'scripts', - 'scripts/utils' + 'scripts/utils', ]; // Make shallow array of files paths @@ -75,24 +75,21 @@ prompt( }); files.forEach(function(file) { - var content = fs.readFileSync(file, 'utf8') + var content = fs.readFileSync(file, 'utf8'); // Skip flagged files if (content.match(/\/\/ @remove-file-on-eject/)) { return; } - content = content // Remove dead code from .js files on eject .replace(/\/\/ @remove-on-eject-begin([\s\S]*?)\/\/ @remove-on-eject-end/mg, '') // Remove dead code from .applescript files on eject .replace(/-- @remove-on-eject-begin([\s\S]*?)-- @remove-on-eject-end/mg, '') .trim() + '\n'; - - console.log(' Adding ' + cyan(file.replace(ownPath, '')) + ' to the project'); - fs.writeFileSync(file.replace(ownPath, appPath), content); + console.log(' Adding ' + cyan(file) + ' to the project'); + fs.writeFileSync(path.join(appPath, file), content); }); - console.log(); var ownPackage = require(path.join(ownPath, 'package.json')); diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index 652e3e339a..1488fcce25 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -45,7 +45,7 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { var DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; function run(port) { - var protocol = process.env.HTTPS === 'true' ? "https" : "http"; + var protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; var host = process.env.HOST || 'localhost'; // Create a webpack compiler that is configured with custom messages. diff --git a/packages/react-scripts/scripts/utils/addWebpackMiddleware.js b/packages/react-scripts/scripts/utils/addWebpackMiddleware.js index 1eccc95ef8..16bf40c370 100644 --- a/packages/react-scripts/scripts/utils/addWebpackMiddleware.js +++ b/packages/react-scripts/scripts/utils/addWebpackMiddleware.js @@ -3,7 +3,33 @@ var historyApiFallback = require('connect-history-api-fallback'); var httpProxyMiddleware = require('http-proxy-middleware'); var paths = require('../../config/paths'); -module.exports = function addMiddleware(devServer) { +// We need to provide a custom onError function for httpProxyMiddleware. +// It allows us to log custom error messages on the console. +function onProxyError(proxy) { + return function(err, req, res){ + var host = req.headers && req.headers.host; + console.log( + chalk.red('Proxy error:') + ' Could not proxy request ' + chalk.cyan(req.url) + + ' from ' + chalk.cyan(host) + ' to ' + chalk.cyan(proxy) + '.' + ); + console.log( + 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' + + chalk.cyan(err.code) + ').' + ); + console.log(); + + // And immediately send the proper error response to the client. + // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side. + if (res.writeHead && !res.headersSent) { + res.writeHead(500); + } + res.end('Proxy error: Could not proxy request ' + req.url + ' from ' + + host + ' to ' + proxy + ' (' + err.code + ').' + ); + } +} + +module.exports = function addWebpackMiddleware(devServer) { // `proxy` lets you to specify a fallback server during development. // Every unrecognized request will be forwarded to it. var proxy = require(paths.appPackageJson).proxy; @@ -54,7 +80,8 @@ module.exports = function addMiddleware(devServer) { onError: onProxyError(proxy), secure: false, changeOrigin: true, - ws: true + ws: true, + xfwd: true }); devServer.use(mayProxy, hpm); @@ -68,29 +95,3 @@ module.exports = function addMiddleware(devServer) { // It may be /index.html, so let the dev server try serving it again. devServer.use(devServer.middleware); }; - -// We need to provide a custom onError function for httpProxyMiddleware. -// It allows us to log custom error messages on the console. -function onProxyError(proxy) { - return function(err, req, res){ - var host = req.headers && req.headers.host; - console.log( - chalk.red('Proxy error:') + ' Could not proxy request ' + chalk.cyan(req.url) + - ' from ' + chalk.cyan(host) + ' to ' + chalk.cyan(proxy) + '.' - ); - console.log( - 'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' + - chalk.cyan(err.code) + ').' - ); - console.log(); - - // And immediately send the proper error response to the client. - // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side. - if (res.writeHead && !res.headersSent) { - res.writeHead(500); - } - res.end('Proxy error: Could not proxy request ' + req.url + ' from ' + - host + ' to ' + proxy + ' (' + err.code + ').' - ); - } -} diff --git a/packages/react-scripts/scripts/utils/createWebpackCompiler.js b/packages/react-scripts/scripts/utils/createWebpackCompiler.js index 516755b761..155e6f1708 100644 --- a/packages/react-scripts/scripts/utils/createWebpackCompiler.js +++ b/packages/react-scripts/scripts/utils/createWebpackCompiler.js @@ -19,7 +19,7 @@ if (isSmokeTest) { }; } -module.exports = function createCompiler(config, onReadyCallack) { +module.exports = function createCompiler(config, onReadyCallback) { // "Compiler" is a low-level interface to Webpack. // It lets us listen to some events and provide our own custom messages. try { @@ -64,8 +64,8 @@ module.exports = function createCompiler(config, onReadyCallack) { } if (showInstructions) { - if (typeof onReadyCallack === 'function') { - onReadyCallack(); + if (typeof onReadyCallback === 'function') { + onReadyCallback(); } isFirstCompile = false; } @@ -97,4 +97,4 @@ module.exports = function createCompiler(config, onReadyCallack) { }); return compiler; -} +}; From 0f9b5df7b75b7a79162db26457b4cb01ee762a94 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Fri, 3 Mar 2017 20:44:22 -0500 Subject: [PATCH 6/8] Pass showInstructions as an argument --- packages/react-scripts/scripts/start.js | 5 ++++- .../scripts/utils/createWebpackCompiler.js | 10 ++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index 1488fcce25..9f6f645af1 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -49,7 +49,10 @@ function run(port) { var host = process.env.HOST || 'localhost'; // Create a webpack compiler that is configured with custom messages. - var compiler = createWebpackCompiler(config, function onReady() { + var compiler = createWebpackCompiler(config, function onReady(showInstructions) { + if (!showInstructions) { + return; + } console.log(); console.log('The app is running at:'); console.log(); diff --git a/packages/react-scripts/scripts/utils/createWebpackCompiler.js b/packages/react-scripts/scripts/utils/createWebpackCompiler.js index 155e6f1708..932bfd5403 100644 --- a/packages/react-scripts/scripts/utils/createWebpackCompiler.js +++ b/packages/react-scripts/scripts/utils/createWebpackCompiler.js @@ -19,7 +19,7 @@ if (isSmokeTest) { }; } -module.exports = function createCompiler(config, onReadyCallback) { +module.exports = function createWebpackCompiler(config, onReadyCallback) { // "Compiler" is a low-level interface to Webpack. // It lets us listen to some events and provide our own custom messages. try { @@ -63,12 +63,10 @@ module.exports = function createCompiler(config, onReadyCallback) { console.log(chalk.green('Compiled successfully!')); } - if (showInstructions) { - if (typeof onReadyCallback === 'function') { - onReadyCallback(); - } - isFirstCompile = false; + if (typeof onReadyCallback === 'function') { + onReadyCallback(showInstructions); } + isFirstCompile = false; // If errors exist, only show errors. if (messages.errors.length) { From 3ba6dfe811467d032d8f08e91206fd744cad0445 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Fri, 3 Mar 2017 20:55:16 -0500 Subject: [PATCH 7/8] Fix eject bug --- packages/react-scripts/scripts/eject.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js index 5d2b7af0df..0358d4256f 100644 --- a/packages/react-scripts/scripts/eject.js +++ b/packages/react-scripts/scripts/eject.js @@ -87,8 +87,8 @@ prompt( // Remove dead code from .applescript files on eject .replace(/-- @remove-on-eject-begin([\s\S]*?)-- @remove-on-eject-end/mg, '') .trim() + '\n'; - console.log(' Adding ' + cyan(file) + ' to the project'); - fs.writeFileSync(path.join(appPath, file), content); + console.log(' Adding ' + cyan(file.replace(ownPath, '')) + ' to the project'); + fs.writeFileSync(file.replace(ownPath, appPath), content); }); console.log(); From 61e99ee2342b117e287f5a4d6ae917ebcefeea36 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Fri, 3 Mar 2017 20:59:56 -0500 Subject: [PATCH 8/8] Don't eject babelTransform --- packages/react-scripts/config/jest/babelTransform.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-scripts/config/jest/babelTransform.js b/packages/react-scripts/config/jest/babelTransform.js index 145bd86cc9..064fbf1029 100644 --- a/packages/react-scripts/config/jest/babelTransform.js +++ b/packages/react-scripts/config/jest/babelTransform.js @@ -1,3 +1,4 @@ +// @remove-file-on-eject /** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. *