diff --git a/packages/react-scripts/config/jest/babelTransform.js b/packages/react-scripts/config/jest/babelTransform.js
index 145bd86cc9a..064fbf10290 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.
*
diff --git a/packages/react-scripts/config/webpackDevServer.config.js b/packages/react-scripts/config/webpackDevServer.config.js
new file mode 100644
index 00000000000..4d65567bd7d
--- /dev/null
+++ b/packages/react-scripts/config/webpackDevServer.config.js
@@ -0,0 +1,51 @@
+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_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,
+};
diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js
index 701907fa436..0358d4256f4 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,44 +47,48 @@ prompt(
var folders = [
'config',
- path.join('config', 'jest'),
- 'scripts'
+ 'config/jest',
+ 'scripts',
+ 'scripts/utils',
];
- 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();
diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js
index aa62265ccc5..33c0777ef41 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/scripts/start.js b/packages/react-scripts/scripts/start.js
index 5d2fd8a8523..9f6f645af10 100644
--- a/packages/react-scripts/scripts/start.js
+++ b/packages/react-scripts/scripts/start.js
@@ -17,21 +17,20 @@ 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 WebpackDevServer = require('webpack-dev-server');
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 devServerConfig = require('../config/webpackDevServer.config');
+var createWebpackCompiler = require('./utils/createWebpackCompiler');
+var addWebpackMiddleware = require('./utils/addWebpackMiddleware');
var useYarn = fs.existsSync(paths.yarnLockFile);
var cli = useYarn ? 'yarn' : 'npm';
@@ -44,247 +43,31 @@ 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 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.'));
- 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) {
- 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;
- }
+function run(port) {
+ var protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
+ var host = process.env.HOST || 'localhost';
- // 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();
- });
+ // Create a webpack compiler that is configured with custom messages.
+ var compiler = createWebpackCompiler(config, function onReady(showInstructions) {
+ if (!showInstructions) {
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();
-
- // 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,
+ 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();
});
+ // 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.
- addMiddleware(devServer);
+ addWebpackMiddleware(devServer);
// Launch WebpackDevServer.
devServer.listen(port, (err, result) => {
@@ -302,13 +85,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/scripts/test.js b/packages/react-scripts/scripts/test.js
index 9de5181d739..dfd2c75c728 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/scripts/utils/addWebpackMiddleware.js b/packages/react-scripts/scripts/utils/addWebpackMiddleware.js
new file mode 100644
index 00000000000..16bf40c3709
--- /dev/null
+++ b/packages/react-scripts/scripts/utils/addWebpackMiddleware.js
@@ -0,0 +1,97 @@
+var chalk = require('chalk');
+var historyApiFallback = require('connect-history-api-fallback');
+var httpProxyMiddleware = require('http-proxy-middleware');
+var paths = require('../../config/paths');
+
+// 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;
+ 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);
+};
diff --git a/packages/react-scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js
similarity index 94%
rename from packages/react-scripts/utils/createJestConfig.js
rename to packages/react-scripts/scripts/utils/createJestConfig.js
index f1c67c018f1..c99345b858a 100644
--- a/packages/react-scripts/utils/createJestConfig.js
+++ b/packages/react-scripts/scripts/utils/createJestConfig.js
@@ -1,3 +1,4 @@
+// @remove-file-on-eject
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
@@ -7,10 +8,8 @@
* 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');
+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/scripts/utils/createWebpackCompiler.js b/packages/react-scripts/scripts/utils/createWebpackCompiler.js
new file mode 100644
index 00000000000..932bfd54034
--- /dev/null
+++ b/packages/react-scripts/scripts/utils/createWebpackCompiler.js
@@ -0,0 +1,98 @@
+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 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 {
+ 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 (typeof onReadyCallback === 'function') {
+ onReadyCallback(showInstructions);
+ }
+ 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;
+};