Skip to content

Commit

Permalink
Move more logic from react-scripts to react-dev-utils (facebook#2209)
Browse files Browse the repository at this point in the history
* Show warnings for builds

* Move WebpackDevServer helpers into react-dev-utils
  • Loading branch information
gaearon committed May 18, 2017
1 parent bacbf59 commit be2378b
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 268 deletions.
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
"react-scripts": "./bin/react-scripts.js"
},
"dependencies": {
"@timer/detect-port": "1.1.3",
"address": "1.0.1",
"autoprefixer": "7.1.0",
"babel-core": "6.24.1",
"babel-eslint": "7.2.3",
Expand Down
41 changes: 27 additions & 14 deletions scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,25 @@ measureFileSizesBeforeBuild(paths.appBuild)
return build(previousFileSizes);
})
.then(
({ stats, previousFileSizes }) => {
console.log(chalk.green('Compiled successfully.'));
console.log();
({ stats, previousFileSizes, warnings }) => {
if (warnings.length) {
console.log(chalk.yellow('Compiled with warnings.\n'));
console.log(warnings.join('\n\n'));
console.log(
'\nSearch for the ' +
chalk.underline(chalk.yellow('rule keywords')) +
' to learn more about each warning.'
);
console.log(
'To ignore, add ' +
chalk.cyan('// eslint-disable-next-line') +
' to the line before.\n'
);
} else {
console.log(chalk.green('Compiled successfully.\n'));
}

console.log('File sizes after gzip:');
console.log();
console.log('File sizes after gzip:\n');
printFileSizesAfterBuild(stats, previousFileSizes);
console.log();

Expand All @@ -78,10 +91,8 @@ measureFileSizesBeforeBuild(paths.appBuild)
);
},
err => {
console.log(chalk.red('Failed to compile.'));
console.log();
console.log(err.message || err);
console.log();
console.log(chalk.red('Failed to compile.\n'));
console.log((err.message || err) + '\n');
process.exit(1);
}
);
Expand All @@ -101,17 +112,19 @@ function build(previousFileSizes) {
return reject(new Error(messages.errors.join('\n\n')));
}
if (process.env.CI && messages.warnings.length) {
console.log();
console.log(
chalk.yellow(
'Treating warnings as errors because process.env.CI = true.\n' +
'Most CI servers set it automatically.'
'\nTreating warnings as errors because process.env.CI = true.\n' +
'Most CI servers set it automatically.\n'
)
);
console.log();
return reject(new Error(messages.warnings.join('\n\n')));
}
return resolve({ stats, previousFileSizes });
return resolve({
stats,
previousFileSizes,
warnings: messages.warnings,
});
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/eject.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ inquirer
}
}

const folders = ['config', 'config/jest', 'scripts', 'scripts/utils'];
const folders = ['config', 'config/jest', 'scripts'];

// Make shallow array of files paths
const files = folders.reduce(
Expand Down
174 changes: 43 additions & 131 deletions scripts/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,24 @@ process.env.NODE_ENV = 'development';
// Ensure environment variables are read.
require('../config/env');

const address = require('address');
const fs = require('fs');
const chalk = require('chalk');
const detect = require('@timer/detect-port');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const clearConsole = require('react-dev-utils/clearConsole');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const getProcessForPort = require('react-dev-utils/getProcessForPort');
const {
choosePort,
createCompiler,
prepareProxy,
prepareUrls,
} = require('react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser');
const inquirer = require('inquirer');
const paths = require('../config/paths');
const config = require('../config/webpack.config.dev');
const devServerConfig = require('../config/webpackDevServer.config');
const createWebpackCompiler = require('./utils/createWebpackCompiler');
const prepareProxy = require('react-dev-utils/prepareProxy');
const url = require('url');
const createDevServerConfig = require('../config/webpackDevServer.config');

const useYarn = fs.existsSync(paths.yarnLockFile);
const cli = useYarn ? 'yarn' : 'npm';
const isInteractive = process.stdout.isTTY;

// Warn and crash if required files are missing
Expand All @@ -52,130 +51,43 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';

function run(port) {
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';

const formatUrl = hostname => url.format({
protocol,
hostname,
port,
pathname: '/',
});
const prettyPrintUrl = hostname => url.format({
protocol,
hostname,
port: chalk.bold(port),
pathname: '/',
});

const isUnspecifiedAddress = HOST === '0.0.0.0' || HOST === '::';
let prettyHost, lanAddress, prettyLanUrl;
if (isUnspecifiedAddress) {
prettyHost = 'localhost';
try {
lanAddress = address.ip();
if (lanAddress) {
prettyLanUrl = prettyPrintUrl(lanAddress);
}
} catch (_e) {
// ignored
}
} else {
prettyHost = HOST;
}
const prettyLocalUrl = prettyPrintUrl(prettyHost);

// Create a webpack compiler that is configured with custom messages.
const compiler = createWebpackCompiler(
config,
function onReady(showInstructions) {
if (!showInstructions) {
return;
}
console.log();
console.log(
`You can now view ${chalk.bold(require(paths.appPackageJson).name)} in the browser.`
);
console.log();

if (prettyLanUrl) {
console.log(` ${chalk.bold('Local:')} ${prettyLocalUrl}`);
console.log(` ${chalk.bold('On Your Network:')} ${prettyLanUrl}`);
} else {
console.log(` ${prettyLocalUrl}`);
}

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();
}
);

// Load proxy config
const proxy = require(paths.appPackageJson).proxy;
// Serve webpack assets generated by the compiler over a web sever.
const devServer = new WebpackDevServer(
compiler,
devServerConfig(prepareProxy(proxy), lanAddress)
);

// Launch WebpackDevServer.
devServer.listen(port, HOST, err => {
if (err) {
return console.log(err);
}

if (isInteractive) {
clearConsole();
}
console.log(chalk.cyan('Starting the development server...'));
console.log();

openBrowser(formatUrl(prettyHost));
});
}

// 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, HOST).then(
port => {
if (port === DEFAULT_PORT) {
run(port);
choosePort(HOST, DEFAULT_PORT)
.then(port => {
if (port == null) {
// We have not found a port.
return;
}

if (isInteractive) {
clearConsole();
const existingProcess = getProcessForPort(DEFAULT_PORT);
const question = {
type: 'confirm',
name: 'shouldChangePort',
message: chalk.yellow(
`Something is already running on port ${DEFAULT_PORT}.` +
`${existingProcess ? ` Probably:\n ${existingProcess}` : ''}`
) + '\n\nWould you like to run the app on another port instead?',
default: true,
};

inquirer.prompt(question).then(answer => {
if (answer.shouldChangePort) {
run(port);
}
});
} else {
console.log(
chalk.red(`Something is already running on port ${DEFAULT_PORT}.`)
);
}
},
err => {
console.log(
chalk.red(`Could not find an open port at ${chalk.bold(HOST)}.`)
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name;
const urls = prepareUrls(protocol, HOST, port);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
// Load proxy config
const proxySetting = require(paths.appPackageJson).proxy;
const proxyConfig = prepareProxy(proxySetting);
// Serve webpack assets generated by the compiler over a web sever.
const serverConfig = createDevServerConfig(
proxyConfig,
urls.lanUrlForConfig
);
console.log('Network error message: ' + err.message || err);
console.log();
}
);
const devServer = new WebpackDevServer(compiler, serverConfig);
// Launch WebpackDevServer.
devServer.listen(port, HOST, err => {
if (err) {
return console.log(err);
}
if (isInteractive) {
clearConsole();
}
console.log(chalk.cyan('Starting the development server...\n'));
openBrowser(urls.localUrlForBrowser);
});
})
.catch(err => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});
Loading

0 comments on commit be2378b

Please sign in to comment.