diff --git a/.gitignore b/.gitignore
index 1900a2f2cf9..7444dad4ec2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ my-app*
template/src/__tests__/__snapshots__/
lerna-debug.log
npm-debug.log
+/.changelog
diff --git a/.travis.yml b/.travis.yml
index 75383b87806..bb9c8112081 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,7 @@
---
language: node_js
node_js:
+ - 0.10
- 4
- 6
cache:
@@ -9,3 +10,6 @@ cache:
- packages/create-react-app/node_modules
- packages/react-scripts/node_modules
script: tasks/e2e.sh
+env:
+ - USE_YARN=no
+ - USE_YARN=yes
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a37b867c6a9..113bf641366 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,481 @@
+## 0.8.5 (January 9, 2017)
+
+#### :bug: Bug Fix
+* `create-react-app`, `react-scripts`
+ * [#1365](https://github.com/facebookincubator/create-react-app/pull/1365) Use yarnpkg alias to run Yarn. ([@fson](https://github.com/fson))
+
+ Fixes an issue where running `create-react-app` failed on systems with Apache Hadoop installed because it falsely detected Hadoop YARN executable as Yarn package manager.
+
+#### Committers: 1
+- Ville Immonen ([fson](https://github.com/fson))
+
+### Migrating from 0.8.4 to 0.8.5
+
+Inside any created project that has not been ejected, run:
+
+```
+npm install --save-dev --save-exact react-scripts@0.8.5
+```
+
+You may also optionally update the global command-line utility:
+
+```
+npm install -g create-react-app@1.0.3
+```
+
+## 0.8.4 (December 11, 2016)
+
+#### :bug: Bug Fix
+* `react-scripts`
+
+ * [#1233](https://github.com/facebookincubator/create-react-app/pull/1233) Disable subresource integrity temporarily. ([@Timer](https://github.com/Timer))
+
+ We added [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) checks to the build output in 0.8.2 but it turns out that they may fail in browsers using special compression proxies, such as Chrome on Android, when served over HTTP. We disabled the checks until we can find a safe way to add them.
+
+* `react-dev-utils`
+
+ * [#1226](https://github.com/facebookincubator/create-react-app/pull/1226) Fix weird lint output. ([@n3tr](https://github.com/n3tr))
+
+ Fixes strange lint message formatting in some edge cases.
+
+ * [#1215](https://github.com/facebookincubator/create-react-app/pull/1215) Fix - openChrome won't open default browser (using Canary). ([@n3tr](https://github.com/n3tr))
+
+ Fixes a regression that caused stable Google Chrome to be opened even if you are using Canary as the default browser.
+
+* `create-react-app`
+
+ * [#1223](https://github.com/facebookincubator/create-react-app/pull/1223) Clean up Yarn detection and install code. ([@fson](https://github.com/fson))
+
+ Fixes noisy output on Windows when Yarn is not installed.
+
+ * [#1224](https://github.com/facebookincubator/create-react-app/pull/1224) Exit with an error code when npm/yarn install fails. ([@fson](https://github.com/fson))
+
+#### :nail_care: Enhancement
+* `react-scripts`
+
+ * [#1237](https://github.com/facebookincubator/create-react-app/pull/1237) Clear scrollback in test mode. ([@gaearon](https://github.com/gaearon))
+
+ Ensures test watcher clears the console before running.
+
+ * [#1229](https://github.com/facebookincubator/create-react-app/pull/1229) Disable jest watch mode when --coverage flag is present [#1207]. ([@BenoitAverty](https://github.com/BenoitAverty))
+
+ Since coverage doesn't work well with watch mode, we don’t run the watcher on `npm test -- --coverage` anymore.
+
+ * [#1212](https://github.com/facebookincubator/create-react-app/pull/1212) Proxy rewrites Origin header to match the target server URL. ([@koles](https://github.com/koles))
+
+ Makes sure more API endpoints can work with the `proxy` setting.
+
+ * [#1222](https://github.com/facebookincubator/create-react-app/pull/1222) Disable gh-page setup instruction if scripts.deploy has been added. ([@n3tr](https://github.com/n3tr))
+
+ Suppresses the instructions printed at the end of `npm run build` if `npm run deploy` already exists.
+
+* `create-react-app`
+
+ * [#1236](https://github.com/facebookincubator/create-react-app/pull/1236) Tweak console messages. ([@gaearon](https://github.com/gaearon))
+
+ Makes error messages more friendly.
+
+ * [#1195](https://github.com/facebookincubator/create-react-app/pull/1195) Use "commander" for cli argv handling. ([@EnoahNetzach](https://github.com/EnoahNetzach))
+
+ Adds `create-react-app --help` with a list of options.
+
+* `react-dev-utils`
+
+ * [#1211](https://github.com/facebookincubator/create-react-app/pull/1211) Use a better clear console sequence. ([@gaearon](https://github.com/gaearon))
+
+ Ensures the development server clears the terminal when files are changed.
+
+#### :memo: Documentation
+* `react-dev-utils`
+
+ * [#1232](https://github.com/facebookincubator/create-react-app/pull/1232) [documentation] fix html-dev-plugin link in react-dev-utils doc. ([@shogunsea](https://github.com/shogunsea))
+
+* `react-scripts`
+
+ * [#1220](https://github.com/facebookincubator/create-react-app/pull/1220) Adding troubleshooting information about Subresource Integrity digests.. ([@dfbaskin](https://github.com/dfbaskin))
+
+#### :house: Internal
+* `react-scripts`
+
+ * [#1214](https://github.com/facebookincubator/create-react-app/pull/1214) Bump babel-eslint version. ([@existentialism](https://github.com/existentialism))
+
+#### Committers: 10
+- Benoit Averty ([BenoitAverty](https://github.com/BenoitAverty))
+- Brian Ng ([existentialism](https://github.com/existentialism))
+- Dan Abramov ([gaearon](https://github.com/gaearon))
+- Dave Baskin ([dfbaskin](https://github.com/dfbaskin))
+- Fabrizio Castellarin ([EnoahNetzach](https://github.com/EnoahNetzach))
+- Jirat Ki. ([n3tr](https://github.com/n3tr))
+- Joe Haddad ([Timer](https://github.com/Timer))
+- Pavel Kolesnikov ([koles](https://github.com/koles))
+- Shogun Sea ([shogunsea](https://github.com/shogunsea))
+- Ville Immonen ([fson](https://github.com/fson))
+
+### Migrating from 0.8.3 to 0.8.4
+
+Inside any created project that has not been ejected, run:
+
+```
+npm install --save-dev --save-exact react-scripts@0.8.4
+```
+
+You may also optionally update the global command-line utility:
+
+```
+npm install -g create-react-app@1.0.2
+```
+
+## 0.8.3 (December 8, 2016)
+
+#### :bug: Bug Fix
+* `create-react-app`
+ * [#1204](https://github.com/facebookincubator/create-react-app/pull/1204) Catch synchronous errors from spawning yarn. ([@gaearon](https://github.com/gaearon))
+
+ Fixes a crash when running `create-react-app` in some cases.
+
+* `react-scripts`
+ * [#1203](https://github.com/facebookincubator/create-react-app/pull/1203) Update webpack-subresource-integrity to fix Windows builds. ([@gaearon](https://github.com/gaearon))
+
+ Fixes a crash when running `npm run build` on Windows.
+
+ * [#1201](https://github.com/facebookincubator/create-react-app/pull/1201) Instruct Jest to load native components from RNW instead of RN. ([@remon-georgy](https://github.com/remon-georgy))
+
+ Fixes tests for users of React Native Web.
+
+#### :memo: Documentation
+* `react-scripts`
+
+ * [#806](https://github.com/facebookincubator/create-react-app/pull/806) Add syntax highlighting configuration guide. ([@mareksuscak](https://github.com/mareksuscak))
+
+#### Committers: 3
+- Dan Abramov ([gaearon](https://github.com/gaearon))
+- Marek Suscak ([mareksuscak](https://github.com/mareksuscak))
+- Remon Georgy ([remon-georgy](https://github.com/remon-georgy))
+
+### Migrating from 0.8.2 to 0.8.3
+
+Inside any created project that has not been ejected, run:
+
+```
+npm install --save-dev --save-exact react-scripts@0.8.3
+```
+
+You can optionally update the global CLI too:
+
+```
+npm install -g create-react-app@1.0.1
+```
+
+## 0.8.2 (December 7, 2016)
+
+#### :rocket: New Feature
+* `react-scripts`
+ * [#1176](https://github.com/facebookincubator/create-react-app/pull/1176) Add Subresource Integrity support. ([@XVincentX](https://github.com/XVincentX))
+
+ The generated HTML now includes [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) attributes ensuring that your users aren't served malicious code if your CDN gets compromised.
+
+#### :bug: Bug Fix
+* `react-scripts`
+ * [#1197](https://github.com/facebookincubator/create-react-app/pull/1197) Let Jest handle all file types. ([@gaearon](https://github.com/gaearon))
+
+ Since 0.8.0, we started treating imports of any unknown file extensions as URLs. However, we had to revert this change for the test configuration in 0.8.1 because of a bug causing false positives. In 0.8.2, we are fixing this and making test configuration treat imports with unknown extensions the same way as we do in the browser environment.
+
+ * [#1194](https://github.com/facebookincubator/create-react-app/pull/1194) Only honor relative `NODE_PATH`. ([@gaearon](https://github.com/gaearon))
+
+ Historically we have allowed specifying `NODE_PATH` environment variable as a way to allow “absolute imports”. For example, running `NODE_PATH=src npm start` in Bash or `set NODE_PATH=src&&npm start` in Windows Cmd would let you import anything inside `src` without specifying a relative path. However, we found a few nasty edge cases when Node.js core modules end up being in `NODE_PATH` and erroneously become bundled. As a result the build would crash on some systems when some libraries are imported. To fix this, we now only honor relative paths from `NODE_PATH` in Create React App. This means the existing use case for absolute imports is still supported (`src` in the example above is relative), but absolute paths in `NODE_PATH` (such as paths to Node.js core modules) will be ignored.
+
+ * [#1188](https://github.com/facebookincubator/create-react-app/pull/1188) Update Webpack to fix source map issues. ([@gaearon](https://github.com/gaearon))
+
+ Since 0.8.0, we show source maps in development instead of the compiled code. However, it has come to our attention that Webpack's source map implementation had issues interpreting Babel output, and caused source maps to be wrong and breakpoints to be unusable in some cases. Webpack has released a fix for this, and we have updated the minimal version of Webpack that we are using.
+
+ * [#1180](https://github.com/facebookincubator/create-react-app/pull/1180) Use `file-loader` for svgs. ([@bogdansoare](https://github.com/bogdansoare))
+
+ Since 0.8.0, we are treating all imports with non-JS/CSS extensions the same way. Importing them gives you a string with their URL, and if their content is small enough (less than 10K), the URL is in fact an inlined [data URI](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs). However, this doesn't work well with SVGs in case you use them for a sprite system since fragments don't work in data URIs, and it's wasteful to inline the same sprite SVG many times. To fix this, we have added an exception so that SVG files never get inlined.
+
+* `react-dev-utils`
+ * [#1165](https://github.com/facebookincubator/create-react-app/pull/1165) Chrome 'open tab' reuse an empty tab when possible. ([@n3tr](https://github.com/n3tr))
+
+ Fixes an issue that caused two tabs to get opened instead of just one. It also fixes some cases where the window with the existing tab would not get activated.
+
+* `babel-preset-react-app`
+ * [#1179](https://github.com/facebookincubator/create-react-app/pull/1179) Fix Babel issues in tests by applying the right transforms. ([@gaearon](https://github.com/gaearon))
+
+ Fixes regressions in test environment that caused syntax errors with generators and `async` / `await`.
+
+#### :nail_care: Enhancement
+* `eslint-config-react-app`
+ * [#1191](https://github.com/facebookincubator/create-react-app/pull/1191) Relax peerDependencies for ESLint preset. ([@gaearon](https://github.com/gaearon))
+
+ This allows the preset to be used in more apps without peer dependency conflicts. We still pin the exact versions in apps that haven't ejected for extra safety.
+
+ * [#1159](https://github.com/facebookincubator/create-react-app/pull/1159) Make jsx-no-undef rule an error. ([@existentialism](https://github.com/existentialism))
+
+ Using an undefined type in JSX is now treated as a hard lint error because it is guaranteed to crash application at runtime.
+
+* `react-scripts`
+ * [#1175](https://github.com/facebookincubator/create-react-app/pull/1175) Remove path module from webpack config on eject. ([@harunhasdal](https://github.com/harunhasdal))
+
+ This makes the output after ejecting a bit cleaner.
+
+ * [#1120](https://github.com/facebookincubator/create-react-app/pull/1120) Add `testURL` to Jest config. ([@spudly](https://github.com/spudly))
+
+ This fixes an error when running tests that interact with History API in jsdom.
+
+#### :memo: Documentation
+* `react-scripts`
+ * [#1143](https://github.com/facebookincubator/create-react-app/pull/1143) Add deploy to Firebase CDN on template's README (Closes [#374](https://github.com/facebookincubator/create-react-app/issues/374)). ([@guilhermebruzzi](https://github.com/guilhermebruzzi))
+ * [#1099](https://github.com/facebookincubator/create-react-app/pull/1099) Fix minor typo/grammar. ([@alex-wilmer](https://github.com/alex-wilmer))
+ * [#1168](https://github.com/facebookincubator/create-react-app/pull/1168) Add "npm run build silently fails" to Troubleshooting. ([@gaearon](https://github.com/gaearon))
+
+#### Committers: 12
+- Alex Wilmer ([alex-wilmer](https://github.com/alex-wilmer))
+- Bogdan Soare ([bogdansoare](https://github.com/bogdansoare))
+- Brian Ng ([existentialism](https://github.com/existentialism))
+- Dan Abramov ([gaearon](https://github.com/gaearon))
+- Fabrizio Castellarin ([EnoahNetzach](https://github.com/EnoahNetzach))
+- Guilherme Heynemann Bruzzi ([guilhermebruzzi](https://github.com/guilhermebruzzi))
+- Harun ([harunhasdal](https://github.com/harunhasdal))
+- James Newell ([jameslnewell](https://github.com/jameslnewell))
+- Jirat Ki. ([n3tr](https://github.com/n3tr))
+- Li Xuanji ([zodiac](https://github.com/zodiac))
+- Stephen John Sorensen ([spudly](https://github.com/spudly))
+- Vincenzo Chianese ([XVincentX](https://github.com/XVincentX))
+
+### Migrating from 0.8.1 to 0.8.2
+
+Inside any created project that has not been ejected, run:
+
+```
+npm install --save-dev --save-exact react-scripts@0.8.2
+```
+
+## 0.8.1 (December 4, 2016)
+
+#### :bug: Bug Fix
+* `react-scripts`
+ * [#1149](https://github.com/facebookincubator/create-react-app/pull/1149) Fix incorrectly stubbing JavaScript files with a dot in the import path in tests. ([@fson](https://github.com/fson))
+
+### Migrating from 0.8.0 to 0.8.1
+
+Inside any created project that has not been ejected, run:
+
+```
+npm install --save-dev --save-exact react-scripts@0.8.1
+```
+
+## 0.8.0 (December 3, 2016)
+
+#### :rocket: New Feature
+* `react-scripts`
+ * [#944](https://github.com/facebookincubator/create-react-app/pull/944) Crash the build during CI whenever linter warnings are encountered. ([@excitement-engineer](https://github.com/excitement-engineer))
+
+ Linter warnings and errors are now checked during a continuous integration build (set by the `CI` environment variable) and the build will fail if any issues are found. See [Continuous Integration](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#continuous-integration) for more information.
+
+ * [#1090](https://github.com/facebookincubator/create-react-app/pull/1090) Enable proxying of WebSockets. ([@dceddia](https://github.com/dceddia))
+
+* `create-react-app`, `react-scripts`
+ * [#898](https://github.com/facebookincubator/create-react-app/pull/898) Support Yarn. ([@fson](https://github.com/fson))
+
+ Yarn is a new fast, reliable and secure alternative to the `npm` client. If you have Yarn installed, `create-react-app` will use it to install packages when you create an app. It also creates a `yarn.lock` file that should be checked into source control (e.g. git). This ensures the same versions of packages will be installed each time `yarn install` is run, on any machine.
+
+ `react-scripts` now also displays instructions using `yarn` commands for projects using Yarn (projects having a `yarn.lock` file).
+
+ To create a project using Yarn, simply install `yarn` and use `create-react-app` like before:
+ ```
+ npm install -g yarn create-react-app@latest
+
+ create-react-app my-app # Packages are now installed with Yarn.
+ ```
+
+#### :boom: Breaking Change
+* `babel-preset-react-app`
+ * [#902](https://github.com/facebookincubator/create-react-app/pull/902) Enable useBuiltIns option on object-rest-spread. ([@existentialism](https://github.com/existentialism))
+
+ Object rest spread and JSX now use the native `Object.assign()` method instead of Babel's helper function. If you are using `babel-preset-react-app` directly in your project *and* targeting browsers that don't have `Object.assign()` available, from now on you need a polyfill for it (e.g. [`object-assign`](https://www.npmjs.com/package/object-assign)).
+
+ **Note:** `react-scripts` already adds this polyfill, so no changes are necessary in Create React App projects.
+
+#### :bug: Bug Fix
+* `react-scripts`
+ * [#978](https://github.com/facebookincubator/create-react-app/pull/978) Move the remove-on-eject-end tag at the end of the file. ([@EnoahNetzach](https://github.com/EnoahNetzach))
+
+ Fixes a bug in ejected configuration.
+
+ * [#1017](https://github.com/facebookincubator/create-react-app/pull/1017) Don't look for `.babelrc` file during test. ([@nhajidin](https://github.com/nhajidin))
+
+ Fixes a `.babelrc` file in a parent directory interfering with the `npm test` command.
+
+ * [#951](https://github.com/facebookincubator/create-react-app/pull/951) Check for presence of folders before continuing eject. ([@heldinz](https://github.com/heldinz))
+
+ Fixes a bug where `eject` failed when a `scripts` or `config` folder already existed in the project.
+
+* `react-dev-utils`
+ * [#1035](https://github.com/facebookincubator/create-react-app/pull/1035) Fix Chrome tab reuse. ([@einarlove](https://github.com/einarlove))
+
+ Fixes a bug with the app not opening in the existing tab in Chrome.
+
+ * [#964](https://github.com/facebookincubator/create-react-app/pull/964) Catch and noop call to open web browser. ([@spadin](https://github.com/spadin))
+
+ Not being able to open a browser doesn't crash the development server now.
+
+* `eslint-config-react-app`, `react-scripts`
+ * [#953](https://github.com/facebookincubator/create-react-app/pull/953) Fix `.ico` file extension being handled by test configuration. ([@vadzim](https://github.com/vadzim))
+
+#### :nail_care: Enhancement
+* `react-scripts`
+ * [#1032](https://github.com/facebookincubator/create-react-app/pull/1032) Add support for non-interactive terminal. ([@sheerun](https://github.com/sheerun))
+ * [#1078](https://github.com/facebookincubator/create-react-app/pull/1078) Upgrade Jest to 17.0. ([@fson](https://github.com/fson))
+ * [#1059](https://github.com/facebookincubator/create-react-app/pull/1059) Use `url-loader` with limit 10k as a default loader. ([@bebbi](https://github.com/bebbi))
+
+ `react-scripts` now treats imports with any unknown file extension as a resource. Files with a size below 10 KB are inlined using a data URI and larger files copied to the build folder. This removes the need for an internal [whitelist of supported file extensions](https://github.com/facebookincubator/create-react-app/issues/667). Any file that's not JS or CSS is now handled the same way.
+
+ * [#924](https://github.com/facebookincubator/create-react-app/pull/924) Enable JavaScript source maps in development. ([@ekaradon](https://github.com/ekaradon))
+ * [#1058](https://github.com/facebookincubator/create-react-app/pull/1058) Add missing dev argument in build script message. ([@nhajidin](https://github.com/nhajidin))
+ * [#961](https://github.com/facebookincubator/create-react-app/pull/961) Add `collectCoverageFrom` option to collect coverage on files without any tests. ([@pmackcode](https://github.com/pmackcode))
+
+ The test script now considers all files in the project when calculating test coverage.
+
+ * [#968](https://github.com/facebookincubator/create-react-app/pull/968) Enable gzip compression in the development server (#966). ([@frontsideair](https://github.com/frontsideair))
+* `react-dev-utils`, `react-scripts`
+ * [#816](https://github.com/facebookincubator/create-react-app/pull/816) add logging of existing default port process on start. ([@ianmcnally](https://github.com/ianmcnally))
+
+ `react-scripts` can guess which process is running on the port 3000 when it's not available:
+ ```
+ Something is already running on port 3000. Probably:
+ my-app
+ in /Users/ian/dev/my-app
+
+ Would you like to run the app on another port instead?
+ ```
+* `react-dev-utils`
+ * [#963](https://github.com/facebookincubator/create-react-app/pull/963) Allow webpack 2 as a peerDependency in react-dev-utils. ([@einarlove](https://github.com/einarlove))
+
+#### :memo: Documentation
+* `react-scripts`
+ * [#1126](https://github.com/facebookincubator/create-react-app/pull/1126) Add a note about vscode-jest. ([@orta](https://github.com/orta))
+ * [#1080](https://github.com/facebookincubator/create-react-app/pull/1080) Add a note for OSX users about watchman and jest. ([@dmr](https://github.com/dmr))
+ * [#1071](https://github.com/facebookincubator/create-react-app/pull/1071) Adds to docs - deployment with S3/CloudFront. ([@marcgarreau](https://github.com/marcgarreau))
+ * [#976](https://github.com/facebookincubator/create-react-app/pull/976) Added info on using global variables. ([@jhorneman](https://github.com/jhorneman))
+ * [#996](https://github.com/facebookincubator/create-react-app/pull/996) Remove redundant `function` from export statement. ([@gnowoel](https://github.com/gnowoel))
+ * [#959](https://github.com/facebookincubator/create-react-app/pull/959) Always build before deploying to gh-pages. ([@dsernst](https://github.com/dsernst))
+ * [#974](https://github.com/facebookincubator/create-react-app/pull/974) Gently nudge users towards https by default. ([@Swizec](https://github.com/Swizec))
+* Other
+ * [#1031](https://github.com/facebookincubator/create-react-app/pull/1031) No Configuration -> Convention over Configuration. ([@sheerun](https://github.com/sheerun))
+ * [#995](https://github.com/facebookincubator/create-react-app/pull/995) Add Gatsby to alternatives. ([@KyleAMathews](https://github.com/KyleAMathews))
+
+#### :house: Internal
+* `react-scripts`
+ * [#1072](https://github.com/facebookincubator/create-react-app/pull/1072) Replace rimraf with fs-extra functions. ([@existentialism](https://github.com/existentialism))
+ * [#1068](https://github.com/facebookincubator/create-react-app/pull/1068) Remove bundledDependencies. ([@fson](https://github.com/fson))
+ * [#1057](https://github.com/facebookincubator/create-react-app/pull/1057) Update `css-loader`. ([@nhajidin](https://github.com/nhajidin))
+ * [#983](https://github.com/facebookincubator/create-react-app/pull/983) Remove custom babel-loader cache dir config. ([@fson](https://github.com/fson))
+* `babel-preset-react-app`
+ * [#1052](https://github.com/facebookincubator/create-react-app/pull/1052) Remove unnecessary transform plugins for object spread to work. ([@valscion](https://github.com/valscion))
+ * [#992](https://github.com/facebookincubator/create-react-app/pull/992) Explain the usage of react-jsx-source & react-jsx-self. ([@bboysathish](https://github.com/bboysathish))
+ * [#1051](https://github.com/facebookincubator/create-react-app/pull/1051) Update babel-present-env and use node: 'current' as target. ([@valscion](https://github.com/valscion))
+
+#### Committers: 27
+- Adam Stankiewicz ([sheerun](https://github.com/sheerun))
+- Alice Rose ([heldinz](https://github.com/heldinz))
+- Arunoda Susiripala ([arunoda](https://github.com/arunoda))
+- Brian Ng ([existentialism](https://github.com/existentialism))
+- Daniel Rech ([dmr](https://github.com/dmr))
+- Dave Ceddia ([dceddia](https://github.com/dceddia))
+- David Ernst ([dsernst](https://github.com/dsernst))
+- Dirk-Jan Rutten ([excitement-engineer](https://github.com/excitement-engineer))
+- Einar Löve ([einarlove](https://github.com/einarlove))
+- Fabrizio Castellarin ([EnoahNetzach](https://github.com/EnoahNetzach))
+- Fatih ([frontsideair](https://github.com/frontsideair))
+- Ian McNally ([ianmcnally](https://github.com/ianmcnally))
+- Jurie Horneman ([jhorneman](https://github.com/jhorneman))
+- Kyle Mathews ([KyleAMathews](https://github.com/KyleAMathews))
+- Leo Wong ([gnowoel](https://github.com/gnowoel))
+- Marc Garreau ([marcgarreau](https://github.com/marcgarreau))
+- Nazim Hajidin ([nhajidin](https://github.com/nhajidin))
+- Orta ([orta](https://github.com/orta))
+- Patrick Mackinder ([pmackcode](https://github.com/pmackcode))
+- Sandro Padin ([spadin](https://github.com/spadin))
+- Sathish ([bboysathish](https://github.com/bboysathish))
+- Stefan ([bebbi](https://github.com/bebbi))
+- Swizec Teller ([Swizec](https://github.com/Swizec))
+- Vadzim ([vadzim](https://github.com/vadzim))
+- Vesa Laakso ([valscion](https://github.com/valscion))
+- Ville Immonen ([fson](https://github.com/fson))
+- [ekaradon](https://github.com/ekaradon)
+
+### Migrating from 0.7.0 to 0.8.0
+
+You may optionally update the global command (it’s not required, but it adds Yarn support for new projects):
+
+```
+npm install -g create-react-app@1.0.0
+```
+
+Inside any created project that has not been ejected, run:
+
+```
+npm install --save-dev --save-exact react-scripts@0.8.0
+```
+
+## 0.7.0 (October 22, 2016)
+
+### Build Dependency (`react-scripts`)
+
+* Updates Jest to [version 16.0](http://facebook.github.io/jest/blog/2016/10/03/jest-16.html), with an upgraded CLI, improved snapshot testing, new matchers and more. ([@chase](https://github.com/chase) in [#858](https://github.com/facebookincubator/create-react-app/pull/858))
+* Test setup file `src/setupTests.js` is now called after test framework initialization to support loading custom matchers. ([@just-boris](https://github.com/just-boris) in [#846](https://github.com/facebookincubator/create-react-app/pull/846))
+* Build command shows better instructions for deploying the app to GitHub Pages ([@Janpot](https://github.com/Janpot) in [#841](https://github.com/facebookincubator/create-react-app/pull/841))
+* Build command now generates an asset manifest with mappings from each filename to its final output filename. ([@lukyth](https://github.com/lukyth) in [#891](https://github.com/facebookincubator/create-react-app/pull/891))
+* Build command exits, if there are errors from UglifyJS ([@pdillon](https://github.com/pdillon) in [#859](https://github.com/facebookincubator/create-react-app/pull/859))
+* Eject output is more beautiful now. ([@azakordonets](https://github.com/azakordonets) in [#769](https://github.com/facebookincubator/create-react-app/pull/769))
+* Fixes opening the app in a new tab in Chrome. ([@unixdev](https://github.com/unixdev) in [#831](https://github.com/facebookincubator/create-react-app/pull/831))
+* Fixes environment variables not being defined as normal properties of the `process.env` object. ([@dvkndn](https://github.com/dvkndn) in [#807](https://github.com/facebookincubator/create-react-app/pull/807))
+* Fixes PostCSS autoprefixer not processing CSS files imported with CSS `@import` statements. ([@nhunzaker](https://github.com/nhunzaker) in [#929](https://github.com/facebookincubator/create-react-app/pull/929))
+
+### ESLint Config (`eslint-config-react-app`)
+
+* Adds `import/no-webpack-loader-syntax` rule that forbids using custom Webpack specific syntax to specify Webpack loaders in import statements. ([@fson](https://github.com/fson) in [#803](https://github.com/facebookincubator/create-react-app/pull/803))
+* `react/react-in-jsx-scope` rule ("React must be in scope") is now an error. ([@gaearon](https://github.com/gaearon) in [#822](https://github.com/facebookincubator/create-react-app/pull/822))
+* `no-unused-expressions` rule now allows the use of short circuit and ternary expressions. ([@cannona](https://github.com/cannona) in [#724](https://github.com/facebookincubator/create-react-app/pull/724))
+
+### Babel Preset (`babel-preset-react-app`)
+
+* The preset now detects the Node.js version in test environment and disables unnecessary ES2015 transforms using using `babel-preset-env`. ([@shubheksha](https://github.com/shubheksha) in [#878](https://github.com/facebookincubator/create-react-app/pull/878), [@JeffreyATW](https://github.com/JeffreyATW) in [#927
+](https://github.com/facebookincubator/create-react-app/pull/927))
+* Fixes a duplicate dependency on `babel-plugin-transform-regenerator`. ([@akofman](https://github.com/akofman) in [#864](https://github.com/facebookincubator/create-react-app/pull/864))
+
+### Utilities (`react-dev-utils`)
+
+* The error overlay is now disposed after fixing linting errors. ([@jarlef](https://github.com/jarlef) in [#856](https://github.com/facebookincubator/create-react-app/pull/856))
+* Adds support for Webpack 2 to `webpackHotDevClient`. ([@michalkvasnicak](https://github.com/michalkvasnicak) in [#840](https://github.com/facebookincubator/create-react-app/pull/840))
+
+### Global CLI (`create-react-app`)
+
+* Adds support for passing a scoped package name to the `--scripts-version` argument. ([@pdillon](https://github.com/pdillon) in [#826](https://github.com/facebookincubator/create-react-app/pull/826))
+* Fixes installing pre-release versions using a tarball URL with the `--scripts-version` argument. ([@jihchi](https://github.com/jihchi) in [#876](https://github.com/facebookincubator/create-react-app/pull/876))
+
+### Migrating from 0.6.1 to 0.7.0
+
+You may optionally update the global command (it’s not required):
+
+```
+npm install -g create-react-app@0.6.0
+```
+
+Inside any created project that has not been ejected, run:
+
+```
+npm install --save-dev --save-exact react-scripts@0.7.0
+```
+
+### Breaking Change in 0.7.0
+
+#### Updating Snapshots
+
+Jest 16 includes [improvements to snapshot testing and changes to the snapshot format](https://facebook.github.io/jest/blog/2016/10/03/jest-16.html#snapshot-updates). If your project uses snapshot testing, you'll need to update the snapshot files. To update the snapshots, run:
+```
+npm test -- -u
+```
+
## 0.6.1 (September 27, 2016)
### Build Dependency (`react-scripts`)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bc0f7aa0030..74785fd16ce 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -60,15 +60,18 @@ and then run `npm start` or `npm run build`.
## Cutting a Release
-1. Tag all merged PRs that go into the release with the relevant milestone.
+1. Tag all merged pull requests that go into the release with the relevant milestone. Each merged PR should also be labeled with one of the [labels](https://github.com/facebookincubator/create-react-app/labels) named `tag: ...` to indicate what kind of change it is.
2. Close the milestone.
3. In most releases, only `react-scripts` needs to be released. If you don’t have any changes to the `packages/create-react-app` folder, you don’t need to bump its version or publish it (the publish script will publish only changed packages).
4. Note that files in `packages/create-react-app` should be modified with extreme caution. Since it’s a global CLI, any version of `create-react-app` (global CLI) including very old ones should work with the latest version of `react-scripts`.
-5. Add an entry to `CHANGELOG.md` detailing what has changed with links to PRs and their authors. Use previous entries for inspiration. Group changes to `react-scripts` and `create-react-app` separately in the notes, for example like in `0.2.0` release notes.
+5. Create a change log entry for the release:
+ * You'll need an [access token for the GitHub API](https://help.github.com/articles/creating-an-access-token-for-command-line-use/). Save it to this environment variable: `export GITHUB_AUTH="..."`
+ * Run `npm run changelog`. The command will find all the labeled pull requests merged since the last release and group them by the label and affected packages, and create a change log entry with all the changes and links to PRs and their authors. Copy and paste it to `CHANGELOG.md`.
+ * Add a four-space indented paragraph after each non-trivial list item, explaining what changed and why. For each breaking change also write who it affects and instructions for migrating existing code.
6. Make sure to include “Migrating from ...” instructions for the previous release. Often you can copy and paste them.
7. After merging the changelog update, create a GitHub Release with the same text. See previous Releases for inspiration.
8. **Do not run `npm publish`. Instead, run `npm run publish`.**
-9. Wait for a long time, and it will get published. Don’t worry that it’s stuck. It will bundle dependencies into a single tarball before publishing for faster installs. In the end the publish script will prompt for versions before publishing the packages.
+9. Wait for a long time, and it will get published. Don’t worry that it’s stuck. In the end the publish script will prompt for versions before publishing the packages.
Make sure to test the released version! If you want to be extra careful, you can publish a prerelease by running `npm run publish -- --tag next` instead of `npm run publish`.
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index 2bcdd77dc36..374dbf17958 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,5 +1,25 @@
If you are reporting a bug, please fill in below. Otherwise feel free to remove this template entirely.
+### Can you reproduce the problem with latest npm?
+
+Many errors, especially related to "missing modules", are due to npm bugs.
+
+If you're using Windows, [follow these instructions to update npm](https://github.com/npm/npm/wiki/Troubleshooting#upgrading-on-windows).
+
+If you're using OS X or Linux, run this to update npm:
+
+```
+npm install -g npm@latest
+
+cd your_project_directory
+rm -rf node_modules
+npm install
+```
+
+Then try to reproduce the issue again.
+
+Can you still reproduce it?
+
### Description
What are you reporting?
diff --git a/README.md b/README.md
index 334dd477e85..9ad9303c5bc 100644
--- a/README.md
+++ b/README.md
@@ -102,23 +102,29 @@ The [User Guide](https://github.com/facebookincubator/create-react-app/blob/mast
- [Updating to New Releases](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#updating-to-new-releases)
- [Folder Structure](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#folder-structure)
- [Available Scripts](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#available-scripts)
+- [Syntax Highlighting in the Editor](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#syntax-highlighting-in-the-editor)
- [Displaying Lint Output in the Editor](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#displaying-lint-output-in-the-editor)
+- [Changing the Page `
`](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#changing-the-page-title)
- [Installing a Dependency](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#installing-a-dependency)
- [Importing a Component](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#importing-a-component)
- [Adding a Stylesheet](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-stylesheet)
- [Post-Processing CSS](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#post-processing-css)
- [Adding Images and Fonts](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-images-and-fonts)
- [Using the `public` Folder](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#using-the-public-folder)
+- [Using Global Variables](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#using-global-variables)
- [Adding Bootstrap](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-bootstrap)
- [Adding Flow](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-flow)
- [Adding Custom Environment Variables](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-custom-environment-variables)
- [Can I Use Decorators?](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#can-i-use-decorators)
-- [Integrating with a Node Backend](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#integrating-with-a-node-backend)
+- [Integrating with an API Backend](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md##integrating-with-an-api-backend)
- [Proxying API Requests in Development](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#proxying-api-requests-in-development)
- [Using HTTPS in Development](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#using-https-in-development)
- [Generating Dynamic `` Tags on the Server](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#generating-dynamic-meta-tags-on-the-server)
- [Running Tests](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#running-tests)
+- [Developing Components in Isolation](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#developing-components-in-isolation)
+- [Making a Progressive Web App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app)
- [Deployment](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#deployment)
+- [Troubleshooting](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#troubleshooting)
A copy of the user guide will be created as `README.md` in your project folder.
@@ -130,7 +136,7 @@ Please refer to the [User Guide](https://github.com/facebookincubator/create-rea
* **One Dependency:** There is just one build dependency. It uses Webpack, Babel, ESLint, and other amazing projects, but provides a cohesive curated experience on top of them.
-* **Zero Configuration:** There are no configuration files or command line options. Configuring both development and production builds is handled for you so you can focus on writing code.
+* **Convention over Configuration:** You don't need to configure anything by default. Reasonably good configuration of both development and production builds is handled for you so you can focus on writing code.
* **No Lock-In:** You can “eject” to a custom setup at any time. Run a single command, and all the configuration and build dependencies will be moved directly into your project, so you can pick up right where you left off.
@@ -138,7 +144,7 @@ Please refer to the [User Guide](https://github.com/facebookincubator/create-rea
**If you’re getting started** with React, use `create-react-app` to automate the build of your app. There is no configuration file, and `react-scripts` is the only extra build dependency in your `package.json`. Your environment will have everything you need to build a modern React app:
-* React, JSX, and ES6 support.
+* React, JSX, ES6, and Flow syntax support.
* Language extras beyond ES6 like the object spread operator.
* A dev server that lints for common errors.
* Import CSS and image files directly from JavaScript.
@@ -205,6 +211,8 @@ Some of the more popular and actively maintained ones are:
* [insin/nwb](https://github.com/insin/nwb)
* [mozilla/neo](https://github.com/mozilla/neo)
* [NYTimes/kyt](https://github.com/NYTimes/kyt)
+* [zeit/next.js](https://github.com/zeit/next.js)
+* [gatsbyjs/gatsby](https://github.com/gatsbyjs/gatsby)
Notable alternatives also include:
diff --git a/lerna.json b/lerna.json
index efe8073fd0c..00b2a8875a0 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,4 +1,16 @@
{
- "lerna": "2.0.0-beta.29",
- "version": "independent"
+ "lerna": "2.0.0-beta.30",
+ "version": "independent",
+ "changelog": {
+ "repo": "facebookincubator/create-react-app",
+ "labels": {
+ "tag: new feature": ":rocket: New Feature",
+ "tag: breaking change": ":boom: Breaking Change",
+ "tag: bug fix": ":bug: Bug Fix",
+ "tag: enhancement": ":nail_care: Enhancement",
+ "tag: documentation": ":memo: Documentation",
+ "tag: internal": ":house: Internal"
+ },
+ "cacheDir": ".changelog"
+ }
}
diff --git a/package.json b/package.json
index 1029bc47758..6645ea27971 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,7 @@
"private": true,
"scripts": {
"build": "node packages/react-scripts/scripts/build.js",
+ "changelog": "lerna-changelog",
"create-react-app": "tasks/cra.sh",
"e2e": "tasks/e2e.sh",
"postinstall": "lerna bootstrap",
@@ -12,11 +13,12 @@
"devDependencies": {
"babel-eslint": "6.1.2",
"eslint": "3.5.0",
- "eslint-config-react-app": "file:packages/eslint-config-react-app",
+ "eslint-config-react-app": "0.2.1",
"eslint-plugin-flowtype": "2.18.1",
"eslint-plugin-import": "1.12.0",
"eslint-plugin-jsx-a11y": "2.2.2",
"eslint-plugin-react": "6.3.0",
- "lerna": "2.0.0-beta.29"
+ "lerna": "2.0.0-beta.30",
+ "lerna-changelog": "^0.2.3"
}
}
diff --git a/packages/babel-preset-react-app/README.md b/packages/babel-preset-react-app/README.md
index c7548b84531..5221c41af59 100644
--- a/packages/babel-preset-react-app/README.md
+++ b/packages/babel-preset-react-app/README.md
@@ -23,3 +23,5 @@ Then create a file named `.babelrc` with following contents in the root folder o
"presets": ["react-app"]
}
```
+
+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.
diff --git a/packages/babel-preset-react-app/index.js b/packages/babel-preset-react-app/index.js
index d3063aee304..a028babc06c 100644
--- a/packages/babel-preset-react-app/index.js
+++ b/packages/babel-preset-react-app/index.js
@@ -11,24 +11,27 @@
var path = require('path');
const plugins = [
- // class { handleClick = () => { } }
- require.resolve('babel-plugin-transform-class-properties'),
- // { ...todo, completed: true }
- require.resolve('babel-plugin-transform-object-rest-spread'),
- // function* () { yield 42; yield 43; }
- [require.resolve('babel-plugin-transform-regenerator'), {
- // Async functions are converted to generators by babel-preset-latest
- async: false
- }],
- // Polyfills the runtime needed for async/await and generators
- [require.resolve('babel-plugin-transform-runtime'), {
- helpers: false,
- polyfill: false,
- regenerator: true,
- // Resolve the Babel runtime relative to the config.
- moduleName: path.dirname(require.resolve('babel-runtime/package'))
- }]
- ];
+ // class { handleClick = () => { } }
+ require.resolve('babel-plugin-transform-class-properties'),
+ // The following two plugins use Object.assign directly, instead of Babel's
+ // extends helper. Note that this assumes `Object.assign` is available.
+ // { ...todo, completed: true }
+ [require.resolve('babel-plugin-transform-object-rest-spread'), {
+ useBuiltIns: true
+ }],
+ // Transforms JSX
+ [require.resolve('babel-plugin-transform-react-jsx'), {
+ useBuiltIns: true
+ }],
+ // Polyfills the runtime needed for async/await and generators
+ [require.resolve('babel-plugin-transform-runtime'), {
+ helpers: false,
+ polyfill: false,
+ regenerator: true,
+ // Resolve the Babel runtime relative to the config.
+ moduleName: path.dirname(require.resolve('babel-runtime/package'))
+ }]
+];
// This is similar to how `env` works in Babel:
// https://babeljs.io/docs/usage/babelrc/#env-option
@@ -46,6 +49,12 @@ if (env !== 'development' && env !== 'test' && env !== 'production') {
}
if (env === 'development' || env === 'test') {
+ // The following two plugins are currently necessary to make React warnings
+ // include more valuable information. They are included here because they are
+ // currently not enabled in babel-preset-react. See the below threads for more info:
+ // https://github.com/babel/babel/issues/4702
+ // https://github.com/babel/babel/pull/3540#issuecomment-228673661
+ // https://github.com/facebookincubator/create-react-app/issues/989
plugins.push.apply(plugins, [
// Adds component stack to warning messages
require.resolve('babel-plugin-transform-react-jsx-source'),
@@ -55,12 +64,19 @@ if (env === 'development' || env === 'test') {
}
if (env === 'test') {
+ plugins.push.apply(plugins, [
+ // We always include this plugin regardless of environment
+ // because of a Babel bug that breaks object rest/spread without it:
+ // https://github.com/babel/babel/issues/4851
+ require.resolve('babel-plugin-transform-es2015-parameters')
+ ]);
+
module.exports = {
presets: [
// ES features necessary for user's Node version
[require('babel-preset-env').default, {
targets: {
- node: parseFloat(process.versions.node),
+ node: 'current',
},
}],
// JSX, Flow
@@ -76,7 +92,13 @@ if (env === 'test') {
// JSX, Flow
require.resolve('babel-preset-react')
],
- plugins: plugins
+ plugins: plugins.concat([
+ // function* () { yield 42; yield 43; }
+ [require.resolve('babel-plugin-transform-regenerator'), {
+ // Async functions are converted to generators by babel-preset-latest
+ async: false
+ }],
+ ])
};
if (env === 'production') {
@@ -91,4 +113,3 @@ if (env === 'test') {
// ]);
}
}
-
diff --git a/packages/babel-preset-react-app/package.json b/packages/babel-preset-react-app/package.json
index bd1db0f5722..c9513ae340a 100644
--- a/packages/babel-preset-react-app/package.json
+++ b/packages/babel-preset-react-app/package.json
@@ -1,6 +1,6 @@
{
"name": "babel-preset-react-app",
- "version": "0.2.1",
+ "version": "2.0.1",
"description": "Babel preset used by Create React App",
"repository": "facebookincubator/create-react-app",
"license": "BSD-3-Clause",
@@ -11,16 +11,18 @@
"index.js"
],
"dependencies": {
- "babel-plugin-transform-class-properties": "6.11.5",
- "babel-plugin-transform-object-rest-spread": "6.8.0",
+ "babel-plugin-transform-class-properties": "6.16.0",
+ "babel-plugin-transform-es2015-parameters": "6.18.0",
+ "babel-plugin-transform-object-rest-spread": "6.19.0",
"babel-plugin-transform-react-constant-elements": "6.9.1",
+ "babel-plugin-transform-react-jsx": "6.8.0",
"babel-plugin-transform-react-jsx-self": "6.11.0",
"babel-plugin-transform-react-jsx-source": "6.9.0",
"babel-plugin-transform-regenerator": "6.16.1",
"babel-plugin-transform-runtime": "6.15.0",
- "babel-preset-env": "0.0.4",
- "babel-preset-latest": "6.14.0",
- "babel-preset-react": "6.11.1",
+ "babel-preset-env": "0.0.8",
+ "babel-preset-latest": "6.16.0",
+ "babel-preset-react": "6.16.0",
"babel-runtime": "6.11.6"
}
}
diff --git a/packages/create-react-app/index.js b/packages/create-react-app/index.js
index d6478a13545..9ab11a5e938 100644
--- a/packages/create-react-app/index.js
+++ b/packages/create-react-app/index.js
@@ -38,53 +38,79 @@
'use strict';
-var fs = require('fs');
-var path = require('path');
-var spawn = require('cross-spawn');
var chalk = require('chalk');
-var semver = require('semver');
-var argv = require('minimist')(process.argv.slice(2));
-var pathExists = require('path-exists');
-/**
- * Arguments:
- * --version - to print current version
- * --verbose - to print logs while init
- * --scripts-version
- * Example of valid values:
- * - a specific npm version: "0.22.0-rc1"
- * - a .tgz archive from any npm repo: "https://registry.npmjs.org/react-scripts/-/react-scripts-0.20.0.tgz"
- * - a package prepared with `tasks/clean_pack.sh`: "/Users/home/vjeux/create-react-app/react-scripts-0.22.0.tgz"
- */
-var commands = argv._;
-if (commands.length === 0) {
- if (argv.version) {
- console.log('create-react-app version: ' + require('./package.json').version);
- process.exit();
- }
+var currentNodeVersion = process.versions.node
+if (currentNodeVersion.split('.')[0] < 4) {
console.error(
- 'Usage: create-react-app [--verbose]'
+ chalk.red(
+ 'You are running Node ' + currentNodeVersion + '.\n' +
+ 'Create React App requires Node 4 or higher. \n' +
+ 'Please update your version of Node.'
+ )
);
process.exit(1);
}
-createApp(commands[0], argv.verbose, argv['scripts-version']);
+var fs = require('fs-extra');
+var path = require('path');
+var execSync = require('child_process').execSync;
+var spawn = require('cross-spawn');
+var semver = require('semver');
+
+var projectName;
+
+var program = require('commander')
+ .version(require('./package.json').version)
+ .arguments('')
+ .usage(chalk.green('') + ' [options]')
+ .action(function (name) {
+ projectName = name;
+ })
+ .option('--verbose', 'print additional logs')
+ .option('--scripts-version ', 'use a non-standard version of react-scripts')
+ .on('--help', function () {
+ console.log(' Only ' + chalk.green('') + ' is required.');
+ console.log();
+ console.log(' A custom ' + chalk.cyan('--scripts-version') + ' can be one of:');
+ console.log(' - a specific npm version: ' + chalk.green('0.8.2'));
+ console.log(' - a custom fork published on npm: ' + chalk.green('my-react-scripts'));
+ console.log(' - a .tgz archive: ' + chalk.green('https://mysite.com/my-react-scripts-0.8.2.tgz'));
+ console.log(' It is not needed unless you specifically want to use a fork.');
+ console.log();
+ console.log(' If you have any problems, do not hesitate to file an issue:');
+ console.log(' ' + chalk.cyan('https://github.com/facebookincubator/create-react-app/issues/new'));
+ console.log();
+ })
+ .parse(process.argv)
+
+if (typeof projectName === 'undefined') {
+ console.error('Please specify the project directory:');
+ console.log(' ' + chalk.cyan(program.name()) + chalk.green(' '));
+ console.log();
+ console.log('For example:');
+ console.log(' ' + chalk.cyan(program.name()) + chalk.green(' my-react-app'));
+ console.log();
+ console.log('Run ' + chalk.cyan(program.name() + ' --help') + ' to see all options.');
+ process.exit(1);
+}
+
+createApp(projectName, program.verbose, program.scriptsVersion);
function createApp(name, verbose, version) {
var root = path.resolve(name);
var appName = path.basename(root);
checkAppName(appName);
-
- if (!pathExists.sync(name)) {
- fs.mkdirSync(root);
- } else if (!isSafeToCreateProjectIn(root)) {
- console.log('The directory `' + name + '` contains file(s) that could conflict. Aborting.');
+ fs.ensureDirSync(name);
+ if (!isSafeToCreateProjectIn(root)) {
+ console.log('The directory ' + chalk.green(name) + ' contains files that could conflict.');
+ console.log('Try using a new directory name.');
process.exit(1);
}
console.log(
- 'Creating a new React app in ' + root + '.'
+ 'Creating a new React app in ' + chalk.green(root) + '.'
);
console.log();
@@ -101,27 +127,50 @@ function createApp(name, verbose, version) {
process.chdir(root);
console.log('Installing packages. This might take a couple minutes.');
- console.log('Installing react-scripts from npm...');
+ console.log('Installing ' + chalk.cyan('react-scripts') + '...');
console.log();
run(root, appName, version, verbose, originalDirectory);
}
+function shouldUseYarn() {
+ try {
+ execSync('yarnpkg --version', {stdio: 'ignore'});
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+function install(packageToInstall, verbose, callback) {
+ var command;
+ var args;
+ if (shouldUseYarn()) {
+ command = 'yarnpkg';
+ args = [ 'add', '--dev', '--exact', packageToInstall];
+ } else {
+ command = 'npm';
+ args = ['install', '--save-dev', '--save-exact', packageToInstall];
+ }
+
+ if (verbose) {
+ args.push('--verbose');
+ }
+
+ var child = spawn(command, args, {stdio: 'inherit'});
+ child.on('close', function(code) {
+ callback(code, command, args);
+ });
+}
+
function run(root, appName, version, verbose, originalDirectory) {
- var installPackage = getInstallPackage(version);
- var packageName = getPackageName(installPackage);
- var args = [
- 'install',
- verbose && '--verbose',
- '--save-dev',
- '--save-exact',
- installPackage,
- ].filter(function(e) { return e; });
- var proc = spawn('npm', args, {stdio: 'inherit'});
- proc.on('close', function (code) {
+ var packageToInstall = getInstallPackage(version);
+ var packageName = getPackageName(packageToInstall);
+
+ install(packageToInstall, verbose, function(code, command, args) {
if (code !== 0) {
- console.error('`npm ' + args.join(' ') + '` failed');
- return;
+ console.error(chalk.cyan(command + ' ' + args.join(' ')) + ' failed');
+ process.exit(1);
}
checkNodeVersion(packageName);
@@ -154,7 +203,7 @@ function getInstallPackage(version) {
function getPackageName(installPackage) {
if (installPackage.indexOf('.tgz') > -1) {
// The package name could be with or without semver version, e.g. react-scripts-0.2.0-alpha.1.tgz
- // However, this function returns package name only wihout semver version.
+ // However, this function returns package name only without semver version.
return installPackage.match(/^.+\/(.+?)(?:-\d+.+)?\.tgz$/)[1];
} else if (installPackage.indexOf('@') > 0) {
// Do not match @scope/ when stripping off @version or @tag
@@ -178,8 +227,9 @@ function checkNodeVersion(packageName) {
if (!semver.satisfies(process.version, packageJson.engines.node)) {
console.error(
chalk.red(
- 'You are currently running Node %s but create-react-app requires %s.' +
- ' Please use a supported version of Node.\n'
+ 'You are running Node %s.\n' +
+ 'Create React App requires Node %s or higher. \n' +
+ 'Please update your version of Node.'
),
process.version,
packageJson.engines.node
@@ -197,7 +247,7 @@ function checkAppName(appName) {
if (allDependencies.indexOf(appName) >= 0) {
console.error(
chalk.red(
- 'We cannot create a project called `' + appName + '` because a dependency with the same name exists.\n' +
+ 'We cannot create a project called ' + chalk.green(appName) + ' because a dependency with the same name exists.\n' +
'Due to the way npm works, the following names are not allowed:\n\n'
) +
chalk.cyan(
diff --git a/packages/create-react-app/package.json b/packages/create-react-app/package.json
index 5094b9c78dd..0ccb85e786b 100644
--- a/packages/create-react-app/package.json
+++ b/packages/create-react-app/package.json
@@ -1,6 +1,6 @@
{
"name": "create-react-app",
- "version": "0.5.0",
+ "version": "1.0.3",
"keywords": [
"react"
],
@@ -21,9 +21,9 @@
},
"dependencies": {
"chalk": "^1.1.1",
+ "commander": "^2.9.0",
"cross-spawn": "^4.0.0",
- "minimist": "^1.2.0",
- "path-exists": "^2.1.0",
+ "fs-extra": "^1.0.0",
"semver": "^5.0.3"
}
}
diff --git a/packages/eslint-config-react-app/README.md b/packages/eslint-config-react-app/README.md
index e4fac03e54d..5c20f50ca2e 100644
--- a/packages/eslint-config-react-app/README.md
+++ b/packages/eslint-config-react-app/README.md
@@ -17,7 +17,7 @@ If you want to use this ESLint configuration in a project not built with Create
First, install this package, ESLint and the necessary plugins.
```sh
- npm install --save-dev eslint-config-react-app babel-eslint@6.1.2 eslint@3.5.0 eslint-plugin-flowtype@2.18.1 eslint-plugin-import@1.12.0 eslint-plugin-jsx-a11y@2.2.2 eslint-plugin-react@6.3.0
+ npm install --save-dev eslint-config-react-app babel-eslint@7.0.0 eslint@3.8.1 eslint-plugin-flowtype@2.21.0 eslint-plugin-import@2.0.1 eslint-plugin-jsx-a11y@2.2.3 eslint-plugin-react@6.4.1
```
Then create a file named `.eslintrc` with following contents in the root folder of your project:
diff --git a/packages/eslint-config-react-app/index.js b/packages/eslint-config-react-app/index.js
index 7689a83544b..d93478bc8c9 100644
--- a/packages/eslint-config-react-app/index.js
+++ b/packages/eslint-config-react-app/index.js
@@ -21,8 +21,7 @@ module.exports = {
parser: 'babel-eslint',
- // import plugin is temporarily disabled, scroll below to see why
- plugins: [/*'import', */'flowtype', 'jsx-a11y', 'react'],
+ plugins: ['import', 'flowtype', 'jsx-a11y', 'react'],
env: {
browser: true,
@@ -44,8 +43,7 @@ module.exports = {
settings: {
'import/ignore': [
- 'node_modules',
- '\\.(json|css|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$',
+ 'node_modules'
],
'import/extensions': ['.js'],
'import/resolver': {
@@ -170,6 +168,9 @@ module.exports = {
// This is probably fixable with a patch to eslint-loader.
// When file A is saved, we want to invalidate all files that import it
// *and* that currently have lint errors. This should fix the problem.
+ // (As an exception, import/no-webpack-loader-syntax can be enabled already
+ // because it doesn't depend on whether the file exists, so this issue
+ // doesn't apply to it.)
// 'import/default': 'warn',
// 'import/export': 'warn',
@@ -181,11 +182,14 @@ module.exports = {
// 'import/no-named-as-default': 'warn',
// 'import/no-named-as-default-member': 'warn',
// 'import/no-unresolved': ['warn', { commonjs: true }],
+ // We don't support configuring Webpack using import source strings, so this
+ // is always an error.
+ 'import/no-webpack-loader-syntax': 'error',
// https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
'react/jsx-equals-spacing': ['warn', 'never'],
'react/jsx-no-duplicate-props': ['warn', { ignoreCase: true }],
- 'react/jsx-no-undef': 'warn',
+ 'react/jsx-no-undef': 'error',
'react/jsx-pascal-case': ['warn', {
allowAllCaps: true,
ignore: [],
diff --git a/packages/eslint-config-react-app/package.json b/packages/eslint-config-react-app/package.json
index 90c6a21f269..66e690e90f2 100644
--- a/packages/eslint-config-react-app/package.json
+++ b/packages/eslint-config-react-app/package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-config-react-app",
- "version": "0.2.1",
+ "version": "0.5.0",
"description": "ESLint configuration used by Create React App",
"repository": "facebookincubator/create-react-app",
"license": "BSD-3-Clause",
@@ -11,11 +11,11 @@
"index.js"
],
"peerDependencies": {
- "babel-eslint": "6.1.2",
- "eslint": "3.5.0",
- "eslint-plugin-flowtype": "2.18.1",
- "eslint-plugin-import": "1.12.0",
- "eslint-plugin-jsx-a11y": "2.2.2",
- "eslint-plugin-react": "6.3.0"
+ "babel-eslint": "^7.0.0",
+ "eslint": "^3.8.1",
+ "eslint-plugin-flowtype": "^2.21.0",
+ "eslint-plugin-import": "^2.0.1",
+ "eslint-plugin-jsx-a11y": "^2.2.3",
+ "eslint-plugin-react": "^6.4.1"
}
}
diff --git a/packages/react-dev-utils/README.md b/packages/react-dev-utils/README.md
index 14c69493e5a..455996fcc59 100644
--- a/packages/react-dev-utils/README.md
+++ b/packages/react-dev-utils/README.md
@@ -21,7 +21,7 @@ There is no single entry point. You can only import individual top-level modules
#### `new InterpolateHtmlPlugin(replacements: {[key:string]: string})`
This Webpack plugin lets us interpolate custom variables into `index.html`.
-It works in tandem with [HtmlWebpackPlugin](https://github.com/ampedandwired/html-dev-plugin) 2.x via its [events](https://github.com/ampedandwired/html-dev-plugin#events).
+It works in tandem with [HtmlWebpackPlugin](https://github.com/ampedandwired/html-webpack-plugin) 2.x via its [events](https://github.com/ampedandwired/html-webpack-plugin#events).
```js
var path = require('path');
@@ -117,6 +117,7 @@ Extracts and prettifies warning and error messages from webpack [stats](https://
```js
var webpack = require('webpack');
var config = require('../config/webpack.config.dev');
+var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
var compiler = webpack(config);
@@ -132,16 +133,32 @@ compiler.plugin('done', function(stats) {
}
if (messages.errors.length) {
console.log('Failed to compile.');
- messages.errors.forEach(console.log);
+ messages.errors.forEach(e => console.log(e));
return;
}
if (messages.warnings.length) {
console.log('Compiled with warnings.');
- messages.warnings.forEach(console.log);
+ messages.warnings.forEach(w => console.log(w));
}
});
```
+#### `getProcessForPort(port: number): string`
+
+Finds the currently running process on `port`.
+Returns a string containing the name and directory, e.g.,
+
+```
+create-react-app
+in /Users/developer/create-react-app
+```
+
+```js
+var getProcessForPort = require('react-dev-utils/getProcessForPort');
+
+getProcessForPort(3000);
+```
+
#### `openBrowser(url: string): boolean`
Attempts to open the browser with a given URL.
@@ -168,6 +185,7 @@ You can control the behavior on `` with `isYesDefault`.
```js
var prompt = require('react-dev-utils/prompt');
+
prompt(
'Are you sure you want to eat all the candy?',
/* isYesDefault */ false
diff --git a/packages/react-dev-utils/clearConsole.js b/packages/react-dev-utils/clearConsole.js
index e37af65543a..cfd10155167 100644
--- a/packages/react-dev-utils/clearConsole.js
+++ b/packages/react-dev-utils/clearConsole.js
@@ -7,12 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-var isFirstClear = true;
function clearConsole() {
- // On first run, clear completely so it doesn't show half screen on Windows.
- // On next runs, use a different sequence that properly scrolls back.
- process.stdout.write(isFirstClear ? '\x1bc' : '\x1b[2J\x1b[0f');
- isFirstClear = false;
+ process.stdout.write(process.platform === 'win32' ? '\x1Bc' : '\x1B[2J\x1B[3J\x1B[H');
}
module.exports = clearConsole;
diff --git a/packages/react-dev-utils/formatWebpackMessages.js b/packages/react-dev-utils/formatWebpackMessages.js
index d72d5f734ca..88834a9fc62 100644
--- a/packages/react-dev-utils/formatWebpackMessages.js
+++ b/packages/react-dev-utils/formatWebpackMessages.js
@@ -24,12 +24,6 @@ function isLikelyASyntaxError(message) {
function formatMessage(message) {
var lines = message.split('\n');
- // line #0 is filename
- // line #1 is the main error message
- if (!lines[0] || !lines[1]) {
- return message;
- }
-
// Remove webpack-specific loader notation from filename.
// Before:
// ./~/css-loader!./~/postcss-loader!./src/App.css
@@ -39,6 +33,12 @@ function formatMessage(message) {
lines[0] = lines[0].substr(lines[0].lastIndexOf('!') + 1);
}
+ // line #0 is filename
+ // line #1 is the main error message
+ if (!lines[0] || !lines[1]) {
+ return lines.join('\n');
+ }
+
// Cleans up verbose "module not found" messages for files and packages.
if (lines[1].indexOf('Module not found: ') === 0) {
lines = [
@@ -101,9 +101,12 @@ function formatMessage(message) {
// Reassemble the message.
message = lines.join('\n');
- // Internal stacks are generally useless so we strip them
+ // Internal stacks are generally useless so we strip them... with the
+ // exception of stacks containing `webpack:` because they're normally
+ // from user code generated by WebPack. For more information see
+ // https://github.com/facebookincubator/create-react-app/pull/1050
message = message.replace(
- /^\s*at\s.*:\d+:\d+[\s\)]*\n/gm, ''
+ /^\s*at\s((?!webpack:).)*:\d+:\d+[\s\)]*(\n|$)/gm, ''
); // at ... ...:x:y
return message;
diff --git a/packages/react-dev-utils/getProcessForPort.js b/packages/react-dev-utils/getProcessForPort.js
new file mode 100644
index 00000000000..5540fbad47a
--- /dev/null
+++ b/packages/react-dev-utils/getProcessForPort.js
@@ -0,0 +1,61 @@
+var chalk = require('chalk');
+var execSync = require('child_process').execSync;
+var path = require('path');
+
+var execOptions = {
+ encoding: 'utf8',
+ stdio: [
+ 'pipe', // stdin (default)
+ 'pipe', // stdout (default)
+ 'ignore' //stderr
+ ]
+};
+
+function isProcessAReactApp(processCommand) {
+ return /^node .*react-scripts\/scripts\/start\.js\s?$/.test(processCommand);
+}
+
+function getProcessIdOnPort(port) {
+ return execSync('lsof -i:' + port + ' -P -t -sTCP:LISTEN', execOptions).trim();
+}
+
+function getPackageNameInDirectory(directory) {
+ var packagePath = path.join(directory.trim(), 'package.json');
+
+ try {
+ return require(packagePath).name;
+ } catch(e) {
+ return null;
+ }
+
+}
+
+function getProcessCommand(processId, processDirectory) {
+ var command = execSync('ps -o command -p ' + processId + ' | sed -n 2p', execOptions);
+
+ if (isProcessAReactApp(command)) {
+ const packageName = getPackageNameInDirectory(processDirectory);
+ return (packageName) ? packageName + '\n' : command;
+ } else {
+ return command;
+ }
+
+}
+
+function getDirectoryOfProcessById(processId) {
+ return execSync('lsof -p '+ processId + ' | grep cwd | awk \'{print $9}\'', execOptions).trim();
+}
+
+function getProcessForPort(port) {
+ try {
+ var processId = getProcessIdOnPort(port);
+ var directory = getDirectoryOfProcessById(processId);
+ var command = getProcessCommand(processId, directory);
+ return chalk.cyan(command) + chalk.blue(' in ') + chalk.cyan(directory);
+ } catch(e) {
+ return null;
+ }
+}
+
+module.exports = getProcessForPort;
+
diff --git a/packages/react-dev-utils/openBrowser.js b/packages/react-dev-utils/openBrowser.js
index 76b33a5924a..a3623515e0a 100644
--- a/packages/react-dev-utils/openBrowser.js
+++ b/packages/react-dev-utils/openBrowser.js
@@ -10,8 +10,32 @@
var execSync = require('child_process').execSync;
var opn = require('opn');
+// https://github.com/sindresorhus/opn#app
+var OSX_CHROME = 'google chrome';
+
function openBrowser(url) {
- if (process.platform === 'darwin') {
+ // Attempt to honor this environment variable.
+ // It is specific to the operating system.
+ // See https://github.com/sindresorhus/opn#app for documentation.
+ const browser = process.env.BROWSER;
+
+ // Special case: BROWSER="none" will prevent opening completely.
+ if (browser === 'none') {
+ return false;
+ }
+
+ // If we're on OS X, the user hasn't specifically
+ // requested a different browser, we can try opening
+ // Chrome with AppleScript. This lets us reuse an
+ // existing tab when possible instead of creating a new one.
+ const shouldTryOpenChromeWithAppleScript = (
+ process.platform === 'darwin' && (
+ typeof browser !== 'string' ||
+ browser === OSX_CHROME
+ )
+ );
+
+ if (shouldTryOpenChromeWithAppleScript) {
try {
// Try our best to reuse existing tab
// on OS X Google Chrome with AppleScript
@@ -25,10 +49,12 @@ function openBrowser(url) {
// Ignore errors.
}
}
+
// Fallback to opn
// (It will always open new tab)
try {
- opn(url);
+ var options = {app: browser};
+ opn(url, options).catch(() => {}); // Prevent `unhandledRejection` error.
return true;
} catch (err) {
return false;
diff --git a/packages/react-dev-utils/openChrome.applescript b/packages/react-dev-utils/openChrome.applescript
index 4dfec4a2657..0f56027213b 100644
--- a/packages/react-dev-utils/openChrome.applescript
+++ b/packages/react-dev-utils/openChrome.applescript
@@ -7,6 +7,10 @@ This source code is licensed under the BSD-style license found in the
of patent rights can be found in the PATENTS file in the same directory.
*)
+property targetTab: null
+property targetTabIndex: -1
+property targetWindow: null
+
on run argv
set theURL to item 1 of argv
@@ -16,14 +20,57 @@ on run argv
make new window
end if
- -- Find a tab currently running the debugger
+ -- 1: Looking for tab running debugger
+ -- then, Reload debugging tab if found
+ -- then return
+ set found to my lookupTabWithUrl(theURL)
+ if found then
+ set targetWindow's active tab index to targetTabIndex
+ tell targetTab to reload
+ tell targetWindow to activate
+ set index of targetWindow to 1
+ return
+ end if
+
+ -- 2: Looking for Empty tab
+ -- In case debugging tab was not found
+ -- We try to find an empty tab instead
+ set found to my lookupTabWithUrl("chrome://newtab/")
+ if found then
+ set targetWindow's active tab index to targetTabIndex
+ set URL of targetTab to theURL
+ tell targetWindow to activate
+ return
+ end if
+
+ -- 3: Create new tab
+ -- both debugging and empty tab were not found
+ -- make a new tab with url
+ tell window 1
+ activate
+ make new tab with properties {URL:theURL}
+ end tell
+ end tell
+end run
+
+-- Function:
+-- Lookup tab with given url
+-- if found, store tab, index, and window in properties
+-- (properties were declared on top of file)
+on lookupTabWithUrl(lookupUrl)
+ tell application "Chrome"
+ -- Find a tab with the given url
set found to false
set theTabIndex to -1
repeat with theWindow in every window
set theTabIndex to 0
repeat with theTab in every tab of theWindow
set theTabIndex to theTabIndex + 1
- if theTab's URL is theURL then
+ if (theTab's URL as string) contains lookupUrl then
+ -- assign tab, tab index, and window to properties
+ set targetTab to theTab
+ set targetTabIndex to theTabIndex
+ set targetWindow to theWindow
set found to true
exit repeat
end if
@@ -33,16 +80,6 @@ on run argv
exit repeat
end if
end repeat
-
- if found then
- tell theTab to reload
- set index of theWindow to 1
- set theWindow's active tab index to theTabIndex
- else
- tell window 1
- activate
- make new tab with properties {URL:theURL}
- end tell
- end if
end tell
-end run
+ return found
+end lookupTabWithUrl
diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json
index 8de715d1916..f3062c56d19 100644
--- a/packages/react-dev-utils/package.json
+++ b/packages/react-dev-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "react-dev-utils",
- "version": "0.2.1",
+ "version": "0.4.2",
"description": "Webpack utilities used by Create React App",
"repository": "facebookincubator/create-react-app",
"license": "BSD-3-Clause",
@@ -14,6 +14,7 @@
"clearConsole.js",
"checkRequiredFiles.js",
"formatWebpackMessages.js",
+ "getProcessForPort.js",
"InterpolateHtmlPlugin.js",
"openChrome.applescript",
"openBrowser.js",
@@ -27,10 +28,7 @@
"escape-string-regexp": "1.0.5",
"html-entities": "1.2.0",
"opn": "4.0.2",
- "sockjs-client": "1.0.3",
+ "sockjs-client": "1.0.1",
"strip-ansi": "3.0.1"
- },
- "peerDependencies": {
- "webpack": "^1.13.2"
}
}
diff --git a/packages/react-dev-utils/webpackHotDevClient.js b/packages/react-dev-utils/webpackHotDevClient.js
index f15fd06f291..7b1768d8fa0 100644
--- a/packages/react-dev-utils/webpackHotDevClient.js
+++ b/packages/react-dev-utils/webpackHotDevClient.js
@@ -248,6 +248,7 @@ connection.onmessage = function(e) {
case 'hash':
handleAvailableHash(message.data);
break;
+ case 'still-ok':
case 'ok':
handleSuccess();
break;
diff --git a/packages/react-scripts/config/jest/transform.js b/packages/react-scripts/config/jest/babelTransform.js
similarity index 84%
rename from packages/react-scripts/config/jest/transform.js
rename to packages/react-scripts/config/jest/babelTransform.js
index 11a0149f97d..145bd86cc9a 100644
--- a/packages/react-scripts/config/jest/transform.js
+++ b/packages/react-scripts/config/jest/babelTransform.js
@@ -9,5 +9,6 @@
const babelJest = require('babel-jest');
module.exports = babelJest.createTransformer({
- presets: [require.resolve('babel-preset-react-app')]
+ presets: [require.resolve('babel-preset-react-app')],
+ babelrc: false
});
diff --git a/packages/react-scripts/config/jest/FileStub.js b/packages/react-scripts/config/jest/cssTransform.js
similarity index 52%
rename from packages/react-scripts/config/jest/FileStub.js
rename to packages/react-scripts/config/jest/cssTransform.js
index c95c3e790a1..eead954406b 100644
--- a/packages/react-scripts/config/jest/FileStub.js
+++ b/packages/react-scripts/config/jest/cssTransform.js
@@ -5,9 +5,18 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- *
- * @flow
*/
// @remove-on-eject-end
-module.exports = "test-file-stub";
+// This is a custom Jest transformer turning style imports into empty objects.
+// http://facebook.github.io/jest/docs/tutorial-webpack.html
+
+module.exports = {
+ process() {
+ return 'module.exports = {};';
+ },
+ getCacheKey(fileData, filename) {
+ // The output is always the same.
+ return 'cssTransform';
+ },
+};
diff --git a/packages/react-scripts/config/jest/CSSStub.js b/packages/react-scripts/config/jest/fileTransform.js
similarity index 54%
rename from packages/react-scripts/config/jest/CSSStub.js
rename to packages/react-scripts/config/jest/fileTransform.js
index 05810269ac6..82c672bebd3 100644
--- a/packages/react-scripts/config/jest/CSSStub.js
+++ b/packages/react-scripts/config/jest/fileTransform.js
@@ -5,9 +5,16 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- *
- * @flow
*/
// @remove-on-eject-end
-module.exports = {};
+const path = require('path');
+
+// This is a custom Jest transformer turning file imports into filenames.
+// http://facebook.github.io/jest/docs/tutorial-webpack.html
+
+module.exports = {
+ process(src, filename) {
+ return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
+ },
+};
diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js
index 1c154c36164..2f10ea2fb8a 100644
--- a/packages/react-scripts/config/paths.js
+++ b/packages/react-scripts/config/paths.js
@@ -30,9 +30,14 @@ function resolveApp(relativePath) {
// It will then be used by Webpack configs.
// Jest doesn’t need this because it already handles `NODE_PATH` out of the box.
+// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
+// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
+// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
+
var nodePaths = (process.env.NODE_PATH || '')
.split(process.platform === 'win32' ? ';' : ':')
.filter(Boolean)
+ .filter(folder => !path.isAbsolute(folder))
.map(resolveApp);
// config after eject: we're in ./config/
@@ -43,6 +48,7 @@ module.exports = {
appIndexJs: resolveApp('src/index.js'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
+ yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveApp('src/setupTests.js'),
appNodeModules: resolveApp('node_modules'),
ownNodeModules: resolveApp('node_modules'),
@@ -62,13 +68,13 @@ module.exports = {
appIndexJs: resolveApp('src/index.js'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
+ yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveApp('src/setupTests.js'),
appNodeModules: resolveApp('node_modules'),
// this is empty with npm3 but node resolution searches higher anyway:
ownNodeModules: resolveOwn('../node_modules'),
nodePaths: nodePaths
};
-// @remove-on-eject-end
// config before publish: we're in ./packages/react-scripts/config/
if (__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1) {
@@ -79,9 +85,11 @@ if (__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1)
appIndexJs: resolveOwn('../template/src/index.js'),
appPackageJson: resolveOwn('../package.json'),
appSrc: resolveOwn('../template/src'),
+ yarnLockFile: resolveOwn('../template/yarn.lock'),
testsSetup: resolveOwn('../template/src/setupTests.js'),
appNodeModules: resolveOwn('../node_modules'),
ownNodeModules: resolveOwn('../node_modules'),
nodePaths: nodePaths
};
}
+// @remove-on-eject-end
diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js
index 8a8b59ed859..96fd632b795 100644
--- a/packages/react-scripts/config/webpack.config.dev.js
+++ b/packages/react-scripts/config/webpack.config.dev.js
@@ -9,10 +9,8 @@
*/
// @remove-on-eject-end
-var path = require('path');
var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
-var findCacheDir = require('find-cache-dir');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
@@ -20,6 +18,11 @@ var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeMod
var getClientEnvironment = require('./env');
var paths = require('./paths');
+// @remove-on-eject-begin
+// `path` is not used after eject - see https://github.com/facebookincubator/create-react-app/issues/1174
+var path = require('path');
+// @remove-on-eject-end
+
// Webpack uses `publicPath` to determine where the app is being served from.
// In development, we always serve from the root. This makes config easier.
var publicPath = '/';
@@ -34,11 +37,9 @@ var env = getClientEnvironment(publicUrl);
// It is focused on developer experience and fast rebuilds.
// The production configuration is different and lives in a separate file.
module.exports = {
- // This makes the bundle appear split into separate modules in the devtools.
- // We don't use source maps here because they can be confusing:
- // https://github.com/facebookincubator/create-react-app/issues/343#issuecomment-237241875
- // You may want 'cheap-module-source-map' instead if you prefer source maps.
- devtool: 'eval',
+ // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
+ // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
+ devtool: 'cheap-module-source-map',
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
@@ -111,6 +112,34 @@ module.exports = {
}
],
loaders: [
+ // Default loader: load all assets that are not handled
+ // by other loaders with the url loader.
+ // Note: This list needs to be updated with every change of extensions
+ // the other loaders match.
+ // E.g., when adding a loader for a new supported file extension,
+ // we need to add the supported extension to this loader too.
+ // Add one new line in `exclude` for each loader.
+ //
+ // "file" loader makes sure those assets get served by WebpackDevServer.
+ // When you `import` an asset, you get its (virtual) filename.
+ // In production, they would get copied to the `build` folder.
+ // "url" loader works like "file" loader except that it embeds assets
+ // smaller than specified limit in bytes as data URLs to avoid requests.
+ // A missing `test` is equivalent to a match.
+ {
+ exclude: [
+ /\.html$/,
+ /\.(js|jsx)$/,
+ /\.css$/,
+ /\.json$/,
+ /\.svg$/
+ ],
+ loader: 'url',
+ query: {
+ limit: 10000,
+ name: 'static/media/[name].[hash:8].[ext]'
+ }
+ },
// Process JS with Babel.
{
test: /\.(js|jsx)$/,
@@ -122,12 +151,9 @@ module.exports = {
presets: [require.resolve('babel-preset-react-app')],
// @remove-on-eject-end
// This is a feature of `babel-loader` for webpack (not Babel itself).
- // It enables caching results in ./node_modules/.cache/react-scripts/
- // directory for faster rebuilds. We use findCacheDir() because of:
- // https://github.com/facebookincubator/create-react-app/issues/483
- cacheDirectory: findCacheDir({
- name: 'react-scripts'
- })
+ // It enables caching results in ./node_modules/.cache/babel-loader/
+ // directory for faster rebuilds.
+ cacheDirectory: true
}
},
// "postcss" loader applies autoprefixer to our CSS.
@@ -137,7 +163,7 @@ module.exports = {
// in development "style" loader enables hot editing of CSS.
{
test: /\.css$/,
- loader: 'style!css!postcss'
+ loader: 'style!css?importLoaders=1!postcss'
},
// JSON is not enabled by default in Webpack but both Node and Browserify
// allow it implicitly so we also enable it.
@@ -145,25 +171,13 @@ module.exports = {
test: /\.json$/,
loader: 'json'
},
- // "file" loader makes sure those assets get served by WebpackDevServer.
- // When you `import` an asset, you get its (virtual) filename.
- // In production, they would get copied to the `build` folder.
+ // "file" loader for svg
{
- test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
+ test: /\.svg$/,
loader: 'file',
query: {
name: 'static/media/[name].[hash:8].[ext]'
}
- },
- // "url" loader works just like "file" loader but it also embeds
- // assets smaller than specified size as data URLs to avoid requests.
- {
- test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
- loader: 'url',
- query: {
- limit: 10000,
- name: 'static/media/[name].[hash:8].[ext]'
- }
}
]
},
diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js
index fa787d43ea7..058db0d7921 100644
--- a/packages/react-scripts/config/webpack.config.prod.js
+++ b/packages/react-scripts/config/webpack.config.prod.js
@@ -9,7 +9,6 @@
*/
// @remove-on-eject-end
-var path = require('path');
var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
@@ -20,6 +19,11 @@ var url = require('url');
var paths = require('./paths');
var getClientEnvironment = require('./env');
+// @remove-on-eject-begin
+// `path` is not used after eject - see https://github.com/facebookincubator/create-react-app/issues/1174
+var path = require('path');
+// @remove-on-eject-end
+
function ensureSlash(path, needsSlash) {
var hasSlash = path.endsWith('/');
if (hasSlash && !needsSlash) {
@@ -116,6 +120,32 @@ module.exports = {
}
],
loaders: [
+ // Default loader: load all assets that are not handled
+ // by other loaders with the url loader.
+ // Note: This list needs to be updated with every change of extensions
+ // the other loaders match.
+ // E.g., when adding a loader for a new supported file extension,
+ // we need to add the supported extension to this loader too.
+ // Add one new line in `exclude` for each loader.
+ //
+ // "file" loader makes sure those assets end up in the `build` folder.
+ // When you `import` an asset, you get its filename.
+ // "url" loader works just like "file" loader but it also embeds
+ // assets smaller than specified size as data URLs to avoid requests.
+ {
+ exclude: [
+ /\.html$/,
+ /\.(js|jsx)$/,
+ /\.css$/,
+ /\.json$/,
+ /\.svg$/
+ ],
+ loader: 'url',
+ query: {
+ limit: 10000,
+ name: 'static/media/[name].[hash:8].[ext]'
+ }
+ },
// Process JS with Babel.
{
test: /\.(js|jsx)$/,
@@ -142,15 +172,7 @@ module.exports = {
// in the main CSS file.
{
test: /\.css$/,
- // "?-autoprefixer" disables autoprefixer in css-loader itself:
- // https://github.com/webpack/css-loader/issues/281
- // We already have it thanks to postcss. We only pass this flag in
- // production because "css" loader only enables autoprefixer-powered
- // removal of unnecessary prefixes when Uglify plugin is enabled.
- // Webpack 1.x uses Uglify plugin as a signal to minify *all* the assets
- // including CSS. This is confusing and will be removed in Webpack 2:
- // https://github.com/webpack/webpack/issues/283
- loader: ExtractTextPlugin.extract('style', 'css?-autoprefixer!postcss')
+ loader: ExtractTextPlugin.extract('style', 'css?importLoaders=1!postcss')
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
// JSON is not enabled by default in Webpack but both Node and Browserify
@@ -159,24 +181,13 @@ module.exports = {
test: /\.json$/,
loader: 'json'
},
- // "file" loader makes sure those assets end up in the `build` folder.
- // When you `import` an asset, you get its filename.
+ // "file" loader for svg
{
- test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
+ test: /\.svg$/,
loader: 'file',
query: {
name: 'static/media/[name].[hash:8].[ext]'
}
- },
- // "url" loader works just like "file" loader but it also embeds
- // assets smaller than specified size as data URLs to avoid requests.
- {
- test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
- loader: 'url',
- query: {
- limit: 10000,
- name: 'static/media/[name].[hash:8].[ext]'
- }
}
]
},
diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json
index 004ba9ee088..38a6f86dbd6 100644
--- a/packages/react-scripts/package.json
+++ b/packages/react-scripts/package.json
@@ -1,6 +1,6 @@
{
"name": "react-scripts",
- "version": "0.6.1",
+ "version": "0.8.5",
"description": "Configuration and scripts for Create React App.",
"repository": "facebookincubator/create-react-app",
"license": "BSD-3-Clause",
@@ -23,102 +23,53 @@
"react-scripts": "./bin/react-scripts.js"
},
"dependencies": {
- "autoprefixer": "6.4.1",
- "babel-core": "6.14.0",
- "babel-eslint": "6.1.2",
- "babel-jest": "16.0.0",
- "babel-loader": "6.2.5",
- "babel-preset-react-app": "^0.2.1",
+ "autoprefixer": "6.5.1",
+ "babel-core": "6.17.0",
+ "babel-eslint": "7.1.1",
+ "babel-jest": "18.0.0",
+ "babel-loader": "6.2.10",
+ "babel-preset-react-app": "^2.0.1",
"case-sensitive-paths-webpack-plugin": "1.1.4",
"chalk": "1.1.3",
"connect-history-api-fallback": "1.3.0",
- "cross-spawn": "4.0.0",
- "css-loader": "0.24.0",
- "detect-port": "1.0.0",
+ "cross-spawn": "4.0.2",
+ "css-loader": "0.26.0",
+ "detect-port": "1.0.1",
"dotenv": "2.0.0",
- "eslint": "3.5.0",
- "eslint-config-react-app": "^0.2.1",
- "eslint-loader": "1.5.0",
- "eslint-plugin-flowtype": "2.18.1",
- "eslint-plugin-import": "1.12.0",
- "eslint-plugin-jsx-a11y": "2.2.2",
- "eslint-plugin-react": "6.3.0",
+ "eslint": "3.8.1",
+ "eslint-config-react-app": "^0.5.0",
+ "eslint-loader": "1.6.0",
+ "eslint-plugin-flowtype": "2.21.0",
+ "eslint-plugin-import": "2.0.1",
+ "eslint-plugin-jsx-a11y": "2.2.3",
+ "eslint-plugin-react": "6.4.1",
"extract-text-webpack-plugin": "1.0.1",
"file-loader": "0.9.0",
"filesize": "3.3.0",
- "find-cache-dir": "0.1.1",
"fs-extra": "0.30.0",
"gzip-size": "3.0.0",
- "html-webpack-plugin": "2.22.0",
- "http-proxy-middleware": "0.17.1",
- "jest": "16.0.1",
+ "html-webpack-plugin": "2.24.0",
+ "http-proxy-middleware": "0.17.2",
+ "jest": "18.0.0",
"json-loader": "0.5.4",
"object-assign": "4.1.0",
- "path-exists": "2.1.0",
- "postcss-loader": "0.13.0",
+ "postcss-loader": "1.0.0",
"promise": "7.1.1",
- "react-dev-utils": "^0.2.1",
+ "react-dev-utils": "^0.4.2",
"recursive-readdir": "2.1.0",
- "rimraf": "2.5.4",
"strip-ansi": "3.0.1",
"style-loader": "0.13.1",
"url-loader": "0.5.7",
- "webpack": "1.13.2",
- "webpack-dev-server": "1.16.1",
- "webpack-manifest-plugin": "1.0.1",
+ "webpack": "1.14.0",
+ "webpack-dev-server": "1.16.2",
+ "webpack-manifest-plugin": "1.1.0",
"whatwg-fetch": "1.0.0"
},
"devDependencies": {
- "bundle-deps": "1.0.0",
"react": "^15.3.0",
"react-dom": "^15.3.0"
},
"optionalDependencies": {
"fsevents": "1.0.14"
- },
- "bundledDependencies": [
- "autoprefixer",
- "babel-core",
- "babel-eslint",
- "babel-jest",
- "babel-loader",
- "babel-preset-react-app",
- "case-sensitive-paths-webpack-plugin",
- "chalk",
- "connect-history-api-fallback",
- "cross-spawn",
- "css-loader",
- "detect-port",
- "dotenv",
- "eslint",
- "eslint-config-react-app",
- "eslint-loader",
- "eslint-plugin-flowtype",
- "eslint-plugin-import",
- "eslint-plugin-jsx-a11y",
- "eslint-plugin-react",
- "extract-text-webpack-plugin",
- "file-loader",
- "filesize",
- "find-cache-dir",
- "fs-extra",
- "gzip-size",
- "html-webpack-plugin",
- "http-proxy-middleware",
- "jest",
- "json-loader",
- "object-assign",
- "path-exists",
- "postcss-loader",
- "promise",
- "react-dev-utils",
- "recursive-readdir",
- "rimraf",
- "strip-ansi",
- "style-loader",
- "url-loader",
- "webpack",
- "webpack-dev-server",
- "whatwg-fetch"
- ]
+ }
}
diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js
index d0b92f6a73b..42be50d43a8 100644
--- a/packages/react-scripts/scripts/build.js
+++ b/packages/react-scripts/scripts/build.js
@@ -23,7 +23,6 @@ var fs = require('fs-extra');
var path = require('path');
var filesize = require('filesize');
var gzipSize = require('gzip-size').sync;
-var rimrafSync = require('rimraf').sync;
var webpack = require('webpack');
var config = require('../config/webpack.config.prod');
var paths = require('../config/paths');
@@ -31,6 +30,8 @@ var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
var recursive = require('recursive-readdir');
var stripAnsi = require('strip-ansi');
+var useYarn = fs.existsSync(paths.yarnLockFile);
+
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
@@ -75,7 +76,7 @@ recursive(paths.appBuild, (err, fileNames) => {
// Remove all content but keep the directory so that
// if you're in it, you don't end up in Trash
- rimrafSync(paths.appBuild + '/*');
+ fs.emptyDirSync(paths.appBuild);
// Start the webpack build
build(previousSizeMap);
@@ -142,6 +143,11 @@ function build(previousSizeMap) {
process.exit(1);
}
+ if (process.env.CI && stats.compilation.warnings.length) {
+ printErrors('Failed to compile.', stats.compilation.warnings);
+ process.exit(1);
+ }
+
console.log(chalk.green('Compiled successfully.'));
console.log();
@@ -151,7 +157,8 @@ function build(previousSizeMap) {
console.log();
var openCommand = process.platform === 'win32' ? 'start' : 'open';
- var homepagePath = require(paths.appPackageJson).homepage;
+ var appPackage = require(paths.appPackageJson);
+ var homepagePath = appPackage.homepage;
var publicPath = config.output.publicPath;
if (homepagePath && homepagePath.indexOf('.github.io/') !== -1) {
// "homepage": "http://user.github.io/project"
@@ -160,20 +167,28 @@ function build(previousSizeMap) {
console.log();
console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.');
console.log('To publish it at ' + chalk.green(homepagePath) + ', run:');
+ // If script deploy has been added to package.json, skip the instructions
+ if (typeof appPackage.scripts.deploy === 'undefined') {
+ console.log();
+ if (useYarn) {
+ console.log(' ' + chalk.cyan('yarn') + ' add --dev gh-pages');
+ } else {
+ console.log(' ' + chalk.cyan('npm') + ' install --save-dev gh-pages');
+ }
+ console.log();
+ console.log('Add the following script in your ' + chalk.cyan('package.json') + '.');
+ console.log();
+ console.log(' ' + chalk.dim('// ...'));
+ console.log(' ' + chalk.yellow('"scripts"') + ': {');
+ console.log(' ' + chalk.dim('// ...'));
+ console.log(' ' + chalk.yellow('"predeploy"') + ': ' + chalk.yellow('"npm run build",'));
+ console.log(' ' + chalk.yellow('"deploy"') + ': ' + chalk.yellow('"gh-pages -d build"'));
+ console.log(' }');
+ console.log();
+ console.log('Then run:');
+ }
console.log();
- console.log(' ' + chalk.cyan('npm') + ' install --save-dev gh-pages');
- console.log();
- console.log('Add the following script in your ' + chalk.cyan('package.json') + '.');
- console.log();
- console.log(' ' + chalk.dim('// ...'));
- console.log(' ' + chalk.yellow('"scripts"') + ': {');
- console.log(' ' + chalk.dim('// ...'));
- console.log(' ' + chalk.yellow('"deploy"') + ': ' + chalk.yellow('"gh-pages -d build"'));
- console.log(' }');
- console.log();
- console.log('Then run:');
- console.log();
- console.log(' ' + chalk.cyan('npm') + ' run deploy');
+ console.log(' ' + chalk.cyan(useYarn ? 'yarn' : 'npm') + ' run deploy');
console.log();
} else if (publicPath !== '/') {
// "homepage": "http://mywebsite.com/project"
@@ -200,7 +215,11 @@ function build(previousSizeMap) {
console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.');
console.log('You may also serve it locally with a static server:')
console.log();
- console.log(' ' + chalk.cyan('npm') + ' install -g pushstate-server');
+ if (useYarn) {
+ console.log(' ' + chalk.cyan('yarn') + ' global add pushstate-server');
+ } else {
+ console.log(' ' + chalk.cyan('npm') + ' install -g pushstate-server');
+ }
console.log(' ' + chalk.cyan('pushstate-server') + ' build');
console.log(' ' + chalk.cyan(openCommand) + ' http://localhost:9000');
console.log();
diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js
index d14aec6abef..86dbc15c3ae 100644
--- a/packages/react-scripts/scripts/eject.js
+++ b/packages/react-scripts/scripts/eject.js
@@ -8,10 +8,10 @@
*/
var createJestConfig = require('../utils/createJestConfig');
-var fs = require('fs');
+var fs = require('fs-extra');
var path = require('path');
+var paths = require('../config/paths');
var prompt = require('react-dev-utils/prompt');
-var rimrafSync = require('rimraf').sync;
var spawnSync = require('cross-spawn').sync;
var chalk = require('chalk');
var green = chalk.green;
@@ -30,36 +30,46 @@ prompt(
var ownPath = path.join(__dirname, '..');
var appPath = path.join(ownPath, '..', '..');
+
+ function verifyAbsent(file) {
+ if (fs.existsSync(path.join(appPath, file))) {
+ console.error(
+ '`' + file + '` already exists in your app folder. We cannot ' +
+ 'continue as you would lose all the changes in that file or directory. ' +
+ 'Please move or delete it (maybe make a copy for backup) and run this ' +
+ 'command again.'
+ );
+ process.exit(1);
+ }
+ }
+
+ var folders = [
+ 'config',
+ path.join('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', 'CSSStub.js'),
- path.join('config', 'jest', 'FileStub.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')
];
// Ensure that the app folder is clean and we won't override any files
- files.forEach(function(file) {
- if (fs.existsSync(path.join(appPath, file))) {
- console.error(
- '`' + file + '` already exists in your app folder. We cannot ' +
- 'continue as you would lose all the changes in that file or directory. ' +
- 'Please delete it (maybe make a copy for backup) and run this ' +
- 'command again.'
- );
- process.exit(1);
- }
- });
+ folders.forEach(verifyAbsent);
+ files.forEach(verifyAbsent);
// Copy the files over
- fs.mkdirSync(path.join(appPath, 'config'));
- fs.mkdirSync(path.join(appPath, 'config', 'jest'));
- fs.mkdirSync(path.join(appPath, 'scripts'));
+ folders.forEach(function(folder) {
+ fs.mkdirSync(path.join(appPath, folder))
+ });
console.log();
console.log(cyan('Copying files into ' + appPath));
@@ -133,9 +143,15 @@ prompt(
);
console.log();
- console.log(cyan('Running npm install...'));
- rimrafSync(ownPath);
- spawnSync('npm', ['install'], {stdio: 'inherit'});
+ if (fs.existsSync(paths.yarnLockFile)) {
+ console.log(cyan('Running yarn...'));
+ fs.removeSync(ownPath);
+ spawnSync('yarnpkg', [], {stdio: 'inherit'});
+ } else {
+ console.log(cyan('Running npm install...'));
+ fs.removeSync(ownPath);
+ spawnSync('npm', ['install'], {stdio: 'inherit'});
+ }
console.log(green('Ejected successfully!'));
console.log();
diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js
index fa42f6dcee6..e438e5a2ee2 100644
--- a/packages/react-scripts/scripts/init.js
+++ b/packages/react-scripts/scripts/init.js
@@ -10,13 +10,13 @@
var fs = require('fs-extra');
var path = require('path');
var spawn = require('cross-spawn');
-var pathExists = require('path-exists');
var chalk = require('chalk');
module.exports = function(appPath, appName, verbose, originalDirectory) {
var ownPackageName = require(path.join(__dirname, '..', 'package.json')).name;
var ownPath = path.join(appPath, 'node_modules', ownPackageName);
var appPackage = require(path.join(appPath, 'package.json'));
+ var useYarn = fs.existsSync(path.join(appPath, 'yarn.lock'));
// Copy over some of the devDependencies
appPackage.dependencies = appPackage.dependencies || {};
@@ -35,7 +35,7 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
JSON.stringify(appPackage, null, 2)
);
- var readmeExists = pathExists.sync(path.join(appPath, 'README.md'));
+ var readmeExists = fs.existsSync(path.join(appPath, 'README.md'));
if (readmeExists) {
fs.renameSync(path.join(appPath, 'README.md'), path.join(appPath, 'README.old.md'));
}
@@ -58,21 +58,31 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
}
});
- // Run another npm install for react and react-dom
- console.log('Installing react and react-dom from npm...');
+ // Run yarn or npm for react and react-dom
+ // TODO: having to do two npm/yarn installs is bad, can we avoid it?
+ var command;
+ var args;
+
+ if (useYarn) {
+ command = 'yarnpkg';
+ args = ['add'];
+ } else {
+ command = 'npm';
+ args = [
+ 'install',
+ '--save',
+ verbose && '--verbose'
+ ].filter(function(e) { return e; });
+ }
+ args.push('react', 'react-dom');
+
+ console.log('Installing react and react-dom using ' + command + '...');
console.log();
- // TODO: having to do two npm installs is bad, can we avoid it?
- var args = [
- 'install',
- 'react',
- 'react-dom',
- '--save',
- verbose && '--verbose'
- ].filter(function(e) { return e; });
- var proc = spawn('npm', args, {stdio: 'inherit'});
+
+ var proc = spawn(command, args, {stdio: 'inherit'});
proc.on('close', function (code) {
if (code !== 0) {
- console.error('`npm ' + args.join(' ') + '` failed');
+ console.error('`' + command + ' ' + args.join(' ') + '` failed');
return;
}
@@ -91,23 +101,23 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
console.log('Success! Created ' + appName + ' at ' + appPath);
console.log('Inside that directory, you can run several commands:');
console.log();
- console.log(chalk.cyan(' npm start'));
+ console.log(chalk.cyan(' ' + command + ' start'));
console.log(' Starts the development server.');
console.log();
- console.log(chalk.cyan(' npm run build'));
+ console.log(chalk.cyan(' ' + command + ' run build'));
console.log(' Bundles the app into static files for production.');
console.log();
- console.log(chalk.cyan(' npm test'));
+ console.log(chalk.cyan(' ' + command + ' test'));
console.log(' Starts the test runner.');
console.log();
- console.log(chalk.cyan(' npm run eject'));
+ console.log(chalk.cyan(' ' + command + ' run eject'));
console.log(' Removes this tool and copies build dependencies, configuration files');
console.log(' and scripts into the app directory. If you do this, you can’t go back!');
console.log();
console.log('We suggest that you begin by typing:');
console.log();
console.log(chalk.cyan(' cd'), cdpath);
- console.log(' ' + chalk.cyan('npm start'));
+ console.log(' ' + chalk.cyan(command + ' start'));
if (readmeExists) {
console.log();
console.log(chalk.yellow('You had a `README.md` file, we renamed it to `README.old.md`'));
diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js
index 8723c281637..8615fb074a9 100644
--- a/packages/react-scripts/scripts/start.js
+++ b/packages/react-scripts/scripts/start.js
@@ -26,11 +26,17 @@ 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 useYarn = fs.existsSync(paths.yarnLockFile);
+var cli = useYarn ? 'yarn' : 'npm';
+var isInteractive = process.stdout.isTTY;
+
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
@@ -64,29 +70,42 @@ function setupCompiler(host, port, protocol) {
// 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() {
- clearConsole();
+ 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) {
- clearConsole();
+ 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));
- if (!messages.errors.length && !messages.warnings.length) {
+ 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('npm run build') + '.');
+ console.log('To create a production build, use ' + chalk.cyan(cli + ' run build') + '.');
console.log();
+ isFirstCompile = false;
}
// If errors exist, only show errors.
@@ -176,18 +195,33 @@ function addMiddleware(devServer) {
// - /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\/)).*$/;
- devServer.use(mayProxy,
- // Pass the scope regex both to Express and to the middleware for proxying
- // of both HTTP and WebSockets to work without false positives.
- httpProxyMiddleware(pathname => mayProxy.test(pathname), {
- target: proxy,
- logLevel: 'silent',
- onError: onProxyError(proxy),
- secure: false,
- changeOrigin: true
- })
- );
+
+ // 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);
@@ -195,6 +229,8 @@ function addMiddleware(devServer) {
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',
@@ -244,9 +280,12 @@ function runDevServer(host, port, protocol) {
return console.log(err);
}
- clearConsole();
+ if (isInteractive) {
+ clearConsole();
+ }
console.log(chalk.cyan('Starting the development server...'));
console.log();
+
openBrowser(protocol + '://' + host + ':' + port + '/');
});
}
@@ -266,14 +305,20 @@ detect(DEFAULT_PORT).then(port => {
return;
}
- clearConsole();
- var question =
- chalk.yellow('Something is already running on port ' + DEFAULT_PORT + '.') +
- '\n\nWould you like to run the app on another port instead?';
+ if (isInteractive) {
+ clearConsole();
+ var existingProcess = getProcessForPort(DEFAULT_PORT);
+ var question =
+ 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?';
- prompt(question, true).then(shouldChangePort => {
- if (shouldChangePort) {
- run(port);
- }
- });
+ prompt(question, true).then(shouldChangePort => {
+ if (shouldChangePort) {
+ run(port);
+ }
+ });
+ } else {
+ console.log(chalk.red('Something is already running on port ' + DEFAULT_PORT + '.'));
+ }
});
diff --git a/packages/react-scripts/scripts/test.js b/packages/react-scripts/scripts/test.js
index 90d1f835d54..9de5181d739 100644
--- a/packages/react-scripts/scripts/test.js
+++ b/packages/react-scripts/scripts/test.js
@@ -21,8 +21,8 @@ require('dotenv').config({silent: true});
const jest = require('jest');
const argv = process.argv.slice(2);
-// Watch unless on CI
-if (!process.env.CI) {
+// Watch unless on CI or in coverage mode
+if (!process.env.CI && argv.indexOf('--coverage') < 0) {
argv.push('--watch');
}
diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md
index 268265bdb6d..786937fb465 100644
--- a/packages/react-scripts/template/README.md
+++ b/packages/react-scripts/template/README.md
@@ -13,18 +13,26 @@ You can find the most recent version of this guide [here](https://github.com/fac
- [npm test](#npm-test)
- [npm run build](#npm-run-build)
- [npm run eject](#npm-run-eject)
+- [Syntax Highlighting in the Editor](#syntax-highlighting-in-the-editor)
- [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor)
+- [Changing the Page ``](#changing-the-page-title)
- [Installing a Dependency](#installing-a-dependency)
- [Importing a Component](#importing-a-component)
- [Adding a Stylesheet](#adding-a-stylesheet)
- [Post-Processing CSS](#post-processing-css)
- [Adding Images and Fonts](#adding-images-and-fonts)
- [Using the `public` Folder](#using-the-public-folder)
+ - [Changing the HTML](#changing-the-html)
+ - [Adding Assets Outside of the Module System](#adding-assets-outside-of-the-module-system)
+ - [When to Use the `public` Folder](#when-to-use-the-public-folder)
+- [Using Global Variables](#using-global-variables)
- [Adding Bootstrap](#adding-bootstrap)
- [Adding Flow](#adding-flow)
- [Adding Custom Environment Variables](#adding-custom-environment-variables)
- [Can I Use Decorators?](#can-i-use-decorators)
-- [Integrating with a Node Backend](#integrating-with-a-node-backend)
+- [Integrating with an API Backend](#integrating-with-an-api-backend)
+ -[Node](#node)
+ -[Ruby on Rails](#ruby-on-rails)
- [Proxying API Requests in Development](#proxying-api-requests-in-development)
- [Using HTTPS in Development](#using-https-in-development)
- [Generating Dynamic `` Tags on the Server](#generating-dynamic-meta-tags-on-the-server)
@@ -41,14 +49,24 @@ You can find the most recent version of this guide [here](https://github.com/fac
- [Continuous Integration](#continuous-integration)
- [Disabling jsdom](#disabling-jsdom)
- [Experimental Snapshot Testing](#experimental-snapshot-testing)
+ - [Editor Integration](#editor-integration)
+- [Developing Components in Isolation](#developing-components-in-isolation)
+- [Making a Progressive Web App](#making-a-progressive-web-app)
- [Deployment](#deployment)
+ - [Serving Apps with Client-Side Routing](#serving-apps-with-client-side-routing)
- [Building for Relative Paths](#building-for-relative-paths)
+ - [Firebase](#firebase)
- [GitHub Pages](#github-pages)
- [Heroku](#heroku)
- [Modulus](#modulus)
- [Netlify](#netlify)
- [Now](#now)
+ - [S3 and CloudFront](#s3-and-cloudfront)
- [Surge](#surge)
+- [Troubleshooting](#troubleshooting)
+ - [`npm test` hangs on macOS Sierra](#npm-test-hangs-on-macos-sierra)
+ - [`npm run build` silently fails](#npm-run-build-silently-fails)
+ - [`npm run build` fails on Heroku](#npm-run-build-fails-on-heroku)
- [Something Missing?](#something-missing)
## Updating to New Releases
@@ -134,6 +152,8 @@ It correctly bundles React in production mode and optimizes the build for the be
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
+See the section about [deployment](#deployment) for more information.
+
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
@@ -144,6 +164,10 @@ Instead, it will copy all the configuration files and the transitive dependencie
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
+## Syntax Highlighting in the Editor
+
+To configure the syntax highlighting in your favorite text editor, head to the [relevant Babel documentation page](https://babeljs.io/docs/editors) and follow the instructions. Some of the most popular editors are covered.
+
## Displaying Lint Output in the Editor
>Note: this feature is available with `react-scripts@0.2.0` and higher.
@@ -174,11 +198,21 @@ Then add this block to the `package.json` file of your project:
Finally, you will need to install some packages *globally*:
```sh
-npm install -g eslint-config-react-app@0.2.1 eslint@3.5.0 babel-eslint@6.1.2 eslint-plugin-react@6.3.0 eslint-plugin-import@1.12.0 eslint-plugin-jsx-a11y@2.2.2 eslint-plugin-flowtype@2.18.1
+npm install -g eslint-config-react-app@0.3.0 eslint@3.8.1 babel-eslint@7.0.0 eslint-plugin-react@6.4.1 eslint-plugin-import@2.0.1 eslint-plugin-jsx-a11y@2.2.3 eslint-plugin-flowtype@2.21.0
```
We recognize that this is suboptimal, but it is currently required due to the way we hide the ESLint dependency. The ESLint team is already [working on a solution to this](https://github.com/eslint/eslint/issues/3458) so this may become unnecessary in a couple of months.
+## Changing the Page ``
+
+You can find the source HTML file in the `public` folder of the generated project. You may edit the `` tag in it to change the title from “React App” to anything else.
+
+Note that normally you wouldn't edit files in the `public` folder very often. For example, [adding a stylesheet](#adding-a-stylesheet) is done without touching the HTML.
+
+If you need to dynamically update the page title based on the content, you can use the browser [`document.title`](https://developer.mozilla.org/en-US/docs/Web/API/Document/title) API. For more complex scenarios when you want to change the title from React components, you can use [React Helmet](https://github.com/nfl/react-helmet), a third party library.
+
+Finally, if you use a custom server for your app in production and want to modify the title before it gets sent to the browser, you can follow advice in [this section](#generating-dynamic-meta-tags-on-the-server).
+
## Installing a Dependency
The generated project includes React and ReactDOM as dependencies. It also includes a set of scripts used by Create React App as a development dependency. You may install other dependencies (for example, React Router) with `npm`:
@@ -320,7 +354,7 @@ function Header() {
return
;
}
-export default function Header;
+export default Header;
```
This ensures that when the project is built, Webpack will correctly move the images into the build folder, and provide us with correct paths.
@@ -344,7 +378,18 @@ An alternative way of handling static assets is described in the next section.
>Note: this feature is available with `react-scripts@0.5.0` and higher.
-Normally we encourage you to `import` assets in JavaScript files as described above. This mechanism provides a number of benefits:
+### Changing the HTML
+
+The `public` folder contains the HTML file so you can tweak it, for example, to [set the page title](#changing-the-page-title).
+The `