Skip to content

Commit 89d78d3

Browse files
committed
# Conflicts: # README.md # packages/react-scripts/package.json # packages/react-scripts/scripts/start.js # packages/react-scripts/utils/createJestConfig.js
2 parents 27ca91d + 5a273b2 commit 89d78d3

File tree

16 files changed

+406
-94
lines changed

16 files changed

+406
-94
lines changed

README.md

Lines changed: 207 additions & 43 deletions
Large diffs are not rendered by default.

packages/babel-preset-react-app/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ Then create a file named `.babelrc` with following contents in the root folder o
2323
"presets": ["react-app"]
2424
}
2525
```
26+
27+
This preset uses the `useBuiltIns` option with [transform-object-rest-spread](http://babeljs.io/docs/plugins/transform-object-rest-spread/) and [transform-react-jsx](http://babeljs.io/docs/plugins/transform-react-jsx/), which assumes that `Object.assign` is available or polyfilled.

packages/babel-preset-react-app/index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,16 @@ var path = require('path');
1313
const plugins = [
1414
// class { handleClick = () => { } }
1515
require.resolve('babel-plugin-transform-class-properties'),
16+
// The following two plugins use Object.assign directly, instead of Babel's
17+
// extends helper. Note that this assumes `Object.assign` is available.
1618
// { ...todo, completed: true }
17-
require.resolve('babel-plugin-transform-object-rest-spread'),
19+
[require.resolve('babel-plugin-transform-object-rest-spread'), {
20+
useBuiltIns: true
21+
}],
22+
// Transforms JSX
23+
[require.resolve('babel-plugin-transform-react-jsx'), {
24+
useBuiltIns: true
25+
}],
1826
// function* () { yield 42; yield 43; }
1927
[require.resolve('babel-plugin-transform-regenerator'), {
2028
// Async functions are converted to generators by babel-preset-latest

packages/babel-preset-react-app/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"babel-plugin-transform-class-properties": "6.16.0",
1616
"babel-plugin-transform-object-rest-spread": "6.19.0",
1717
"babel-plugin-transform-react-constant-elements": "6.9.1",
18+
"babel-plugin-transform-react-jsx": "6.8.0",
1819
"babel-plugin-transform-react-jsx-self": "6.11.0",
1920
"babel-plugin-transform-react-jsx-source": "6.9.0",
2021
"babel-plugin-transform-regenerator": "6.16.1",

packages/eslint-config-react-app/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ module.exports = {
4343

4444
settings: {
4545
'import/ignore': [
46-
'node_modules',
47-
'\\.(json|css|ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$',
46+
'node_modules'
4847
],
4948
'import/extensions': ['.js'],
5049
'import/resolver': {

packages/react-dev-utils/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,22 @@ compiler.plugin('done', function(stats) {
142142
});
143143
```
144144

145+
#### `getProcessForPort(port: number): string`
146+
147+
Finds the currently running process on `port`.
148+
Returns a string containing the name and directory, e.g.,
149+
150+
```
151+
create-react-app
152+
in /Users/developer/create-react-app
153+
```
154+
155+
```js
156+
var getProcessForPort = require('react-dev-utils/getProcessForPort');
157+
158+
getProcessForPort(3000);
159+
```
160+
145161
#### `openBrowser(url: string): boolean`
146162

147163
Attempts to open the browser with a given URL.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
var chalk = require('chalk');
2+
var execSync = require('child_process').execSync;
3+
var path = require('path');
4+
5+
var execOptions = {
6+
encoding: 'utf8',
7+
stdio: [
8+
'pipe', // stdin (default)
9+
'pipe', // stdout (default)
10+
'ignore' //stderr
11+
]
12+
};
13+
14+
function isProcessAReactApp(processCommand) {
15+
return /^node .*react-scripts\/scripts\/start\.js\s?$/.test(processCommand);
16+
}
17+
18+
function getProcessIdOnPort(port) {
19+
return execSync('lsof -i:' + port + ' -P -t -sTCP:LISTEN', execOptions).trim();
20+
}
21+
22+
function getPackageNameInDirectory(directory) {
23+
var packagePath = path.join(directory.trim(), 'package.json');
24+
25+
try {
26+
return require(packagePath).name;
27+
} catch(e) {
28+
return null;
29+
}
30+
31+
}
32+
33+
function getProcessCommand(processId, processDirectory) {
34+
var command = execSync('ps -o command -p ' + processId + ' | sed -n 2p', execOptions);
35+
36+
if (isProcessAReactApp(command)) {
37+
const packageName = getPackageNameInDirectory(processDirectory);
38+
return (packageName) ? packageName + '\n' : command;
39+
} else {
40+
return command;
41+
}
42+
43+
}
44+
45+
function getDirectoryOfProcessById(processId) {
46+
return execSync('lsof -p '+ processId + ' | grep cwd | awk \'{print $9}\'', execOptions).trim();
47+
}
48+
49+
function getProcessForPort(port) {
50+
try {
51+
var processId = getProcessIdOnPort(port);
52+
var directory = getDirectoryOfProcessById(processId);
53+
var command = getProcessCommand(processId, directory);
54+
return chalk.cyan(command) + chalk.blue(' in ') + chalk.cyan(directory);
55+
} catch(e) {
56+
return null;
57+
}
58+
}
59+
60+
module.exports = getProcessForPort;
61+

packages/react-dev-utils/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"clearConsole.js",
1616
"checkRequiredFiles.js",
1717
"formatWebpackMessages.js",
18+
"getProcessForPort.js",
1819
"InterpolateHtmlPlugin.js",
1920
"openChrome.applescript",
2021
"openBrowser.js",

packages/react-scripts/config/webpack.config.dev.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ module.exports = {
127127
// A missing `test` is equivalent to a match.
128128
{
129129
exclude: [
130-
/\.(html)$/,
130+
/\.html$/,
131131
/\.(js|jsx)$/,
132132
/\.css$/,
133133
/\.json$/

packages/react-scripts/config/webpack.config.prod.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,13 @@ module.exports = {
127127
// we need to add the supported extension to this loader too.
128128
// Add one new line in `exclude` for each loader.
129129
//
130-
// "file" loader makes sure those assets get served by WebpackDevServer.
131-
// When you `import` an asset, you get its (virtual) filename.
132-
// In production, they would get copied to the `build` folder.
133-
// "url" loader works like "file" loader except that it embeds assets
134-
// smaller than specified limit in bytes as data URLs to avoid requests.
135-
// A missing `test` is equivalent to a match.
130+
// "file" loader makes sure those assets end up in the `build` folder.
131+
// When you `import` an asset, you get its filename.
132+
// "url" loader works just like "file" loader but it also embeds
133+
// assets smaller than specified size as data URLs to avoid requests.
136134
{
137135
exclude: [
138-
/\.(html)$/,
136+
/\.html$/,
139137
/\.(js|jsx)$/,
140138
/\.css$/,
141139
/\.json$/

packages/react-scripts/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"name": "custom-react-scripts",
3-
"version": "0.0.19",
4-
"description": "Allow custom config for create-react-app without ejecting",
5-
"repository": "kitze/create-react-app",
2+
"name": "react-scripts",
3+
"version": "0.7.0",
4+
"description": "Configuration and scripts for Create React App.",
5+
"repository": "facebookincubator/create-react-app",
66
"license": "BSD-3-Clause",
77
"engines": {
88
"node": ">=4"
@@ -26,7 +26,7 @@
2626
"autoprefixer": "6.5.1",
2727
"babel-core": "6.17.0",
2828
"babel-eslint": "7.0.0",
29-
"babel-jest": "16.0.0",
29+
"babel-jest": "17.0.2",
3030
"babel-loader": "6.2.7",
3131
"babel-preset-react-app": "^1.0.0",
3232
"babel-preset-stage-0": "^6.5.0",
@@ -52,7 +52,7 @@
5252
"gzip-size": "3.0.0",
5353
"html-webpack-plugin": "2.24.0",
5454
"http-proxy-middleware": "0.17.2",
55-
"jest": "16.0.2",
55+
"jest": "17.0.2",
5656
"json-loader": "0.5.4",
5757
"less": "^2.7.1",
5858
"less-loader": "^2.2.3",

packages/react-scripts/scripts/build.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ var path = require('path');
2424
var pathExists = require('path-exists');
2525
var filesize = require('filesize');
2626
var gzipSize = require('gzip-size').sync;
27-
var rimrafSync = require('rimraf').sync;
2827
var webpack = require('webpack');
2928
var config = require('../config/webpack.config.prod');
3029
var paths = require('../config/paths');
@@ -78,7 +77,7 @@ recursive(paths.appBuild, (err, fileNames) => {
7877

7978
// Remove all content but keep the directory so that
8079
// if you're in it, you don't end up in Trash
81-
rimrafSync(paths.appBuild + '/*');
80+
fs.emptyDirSync(paths.appBuild);
8281

8382
// Start the webpack build
8483
build(previousSizeMap);

packages/react-scripts/scripts/eject.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
*/
99

1010
var createJestConfig = require('../utils/createJestConfig');
11-
var fs = require('fs');
11+
var fs = require('fs-extra');
1212
var path = require('path');
1313
var pathExists = require('path-exists');
1414
var paths = require('../config/paths');
1515
var prompt = require('react-dev-utils/prompt');
16-
var rimrafSync = require('rimraf').sync;
1716
var spawnSync = require('cross-spawn').sync;
1817
var chalk = require('chalk');
1918
var green = chalk.green;
@@ -149,11 +148,11 @@ prompt(
149148

150149
if (pathExists.sync(paths.yarnLockFile)) {
151150
console.log(cyan('Running yarn...'));
152-
rimrafSync(ownPath);
151+
fs.removeSync(ownPath);
153152
spawnSync('yarn', [], {stdio: 'inherit'});
154153
} else {
155154
console.log(cyan('Running npm install...'));
156-
rimrafSync(ownPath);
155+
fs.removeSync(ownPath);
157156
spawnSync('npm', ['install'], {stdio: 'inherit'});
158157
}
159158
console.log(green('Ejected successfully!'));

packages/react-scripts/scripts/start.js

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var detect = require('detect-port');
2626
var clearConsole = require('react-dev-utils/clearConsole');
2727
var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
2828
var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
29+
var getProcessForPort = require('react-dev-utils/getProcessForPort');
2930
var openBrowser = require('react-dev-utils/openBrowser');
3031
var prompt = require('react-dev-utils/prompt');
3132
var pathExists = require('path-exists');
@@ -34,6 +35,7 @@ var paths = require('../config/paths');
3435

3536
var useYarn = pathExists.sync(paths.yarnLockFile);
3637
var cli = useYarn ? 'yarn' : 'npm';
38+
var isInteractive = process.stdout.isTTY;
3739

3840
// Warn and crash if required files are missing
3941
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
@@ -68,21 +70,33 @@ function setupCompiler(host, port, protocol) {
6870
// bundle, so if you refresh, it'll wait instead of serving the old one.
6971
// "invalid" is short for "bundle invalidated", it doesn't imply any errors.
7072
compiler.plugin('invalid', function() {
71-
clearConsole();
73+
if (isInteractive) {
74+
clearConsole();
75+
}
7276
console.log('Compiling...');
7377
});
7478

79+
var isFirstCompile = true;
80+
7581
// "done" event fires when Webpack has finished recompiling the bundle.
7682
// Whether or not you have warnings or errors, you will get this event.
7783
compiler.plugin('done', function(stats) {
78-
clearConsole();
84+
if (isInteractive) {
85+
clearConsole();
86+
}
7987

8088
// We have switched off the default Webpack output in WebpackDevServer
8189
// options so we are going to "massage" the warnings and errors and present
8290
// them in a readable focused way.
8391
var messages = formatWebpackMessages(stats.toJson({}, true));
84-
if (!messages.errors.length && !messages.warnings.length) {
92+
var isSuccessful = !messages.errors.length && !messages.warnings.length;
93+
var showInstructions = isSuccessful && (isInteractive || isFirstCompile);
94+
95+
if (isSuccessful) {
8596
console.log(chalk.green('Compiled successfully!'));
97+
}
98+
99+
if (showInstructions) {
86100
console.log();
87101
console.log('The app is running at:');
88102
console.log();
@@ -91,6 +105,7 @@ function setupCompiler(host, port, protocol) {
91105
console.log('Note that the development build is not optimized.');
92106
console.log('To create a production build, use ' + chalk.cyan(cli + ' run build') + '.');
93107
console.log();
108+
isFirstCompile = false;
94109
}
95110

96111
// If errors exist, only show errors.
@@ -138,7 +153,7 @@ function onProxyError(proxy) {
138153
// And immediately send the proper error response to the client.
139154
// Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
140155
if (res.writeHead && !res.headersSent) {
141-
res.writeHead(500);
156+
res.writeHead(500);
142157
}
143158
res.end('Proxy error: Could not proxy request ' + req.url + ' from ' +
144159
host + ' to ' + proxy + ' (' + err.code + ').'
@@ -180,18 +195,25 @@ function addMiddleware(devServer) {
180195
// - /sockjs-node/* (WebpackDevServer uses this for hot reloading)
181196
// Tip: use https://jex.im/regulex/ to visualize the regex
182197
var mayProxy = /^(?!\/(index\.html$|.*\.hot-update\.json$|sockjs-node\/)).*$/;
183-
devServer.use(mayProxy,
184-
// Pass the scope regex both to Express and to the middleware for proxying
185-
// of both HTTP and WebSockets to work without false positives.
186-
httpProxyMiddleware(pathname => mayProxy.test(pathname), {
187-
target: proxy,
188-
logLevel: 'silent',
189-
onError: onProxyError(proxy),
190-
secure: false,
191-
changeOrigin: true
192-
})
193-
);
198+
199+
// Pass the scope regex both to Express and to the middleware for proxying
200+
// of both HTTP and WebSockets to work without false positives.
201+
var hpm = httpProxyMiddleware(pathname => mayProxy.test(pathname), {
202+
target: proxy,
203+
logLevel: 'silent',
204+
onError: onProxyError(proxy),
205+
secure: false,
206+
changeOrigin: true,
207+
ws: true
208+
});
209+
devServer.use(mayProxy, hpm);
210+
211+
// Listen for the websocket 'upgrade' event and upgrade the connection.
212+
// If this is not done, httpProxyMiddleware will not try to upgrade until
213+
// an initial plain HTTP request is made.
214+
devServer.listeningApp.on('upgrade', hpm.upgrade);
194215
}
216+
195217
// Finally, by now we have certainly resolved the URL.
196218
// It may be /index.html, so let the dev server try serving it again.
197219
devServer.use(devServer.middleware);
@@ -250,10 +272,13 @@ function runDevServer(host, port, protocol) {
250272
return console.log(err);
251273
}
252274

253-
clearConsole();
275+
if (isInteractive) {
276+
clearConsole();
277+
}
254278
console.log(chalk.cyan('Starting the development server...'));
255279
console.log();
256-
if (process.env && process.env.OPEN_BROWSER !== 'false') {
280+
281+
if (isInteractive && process.env.OPEN_BROWSER !== 'false') {
257282
openBrowser(protocol + '://' + host + ':' + port + '/');
258283
}
259284
});
@@ -274,14 +299,20 @@ detect(DEFAULT_PORT).then(port => {
274299
return;
275300
}
276301

277-
clearConsole();
278-
var question =
279-
chalk.yellow('Something is already running on port ' + DEFAULT_PORT + '.') +
302+
if (isInteractive) {
303+
clearConsole();
304+
var existingProcess = getProcessForPort(DEFAULT_PORT);
305+
var question =
306+
chalk.yellow('Something is already running on port ' + DEFAULT_PORT + '.' +
307+
((existingProcess) ? ' Probably:\n ' + existingProcess : '')) +
280308
'\n\nWould you like to run the app on another port instead?';
281309

282-
prompt(question, true).then(shouldChangePort => {
283-
if (shouldChangePort) {
284-
run(port);
285-
}
286-
});
310+
prompt(question, true).then(shouldChangePort => {
311+
if (shouldChangePort) {
312+
run(port);
313+
}
314+
});
315+
} else {
316+
console.log(chalk.red('Something is already running on port ' + DEFAULT_PORT + '.'));
317+
}
287318
});

0 commit comments

Comments
 (0)