From 4b110c4cdbd9a895721e9b70a849e4e340ff4853 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 5 Aug 2016 17:15:49 +0100 Subject: [PATCH 001/248] Clarify why we only need css?-autoprefixer in development Fixes #377 --- config/webpack.config.prod.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index dbac03f1aaf..2a3b1a81868 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -116,7 +116,12 @@ module.exports = { include: [paths.appSrc, paths.appNodeModules], // "?-autoprefixer" disables autoprefixer in css-loader itself: // https://github.com/webpack/css-loader/issues/281 - // We already have it thanks to postcss. + // 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') // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, From 3fe65ee0f3c20cc3b8c9ddda00aa8b4ba73d121e Mon Sep 17 00:00:00 2001 From: Matt Brennan Date: Fri, 5 Aug 2016 17:27:25 +0100 Subject: [PATCH 002/248] add shebang to tasks scripts (#376) --- tasks/e2e.sh | 1 + tasks/release.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/tasks/e2e.sh b/tasks/e2e.sh index 8189847f7f7..a1566a85bdb 100755 --- a/tasks/e2e.sh +++ b/tasks/e2e.sh @@ -1,3 +1,4 @@ +#!/bin/bash # Copyright (c) 2015-present, Facebook, Inc. # All rights reserved. # diff --git a/tasks/release.sh b/tasks/release.sh index b30ab86abd5..c52d7c40bef 100755 --- a/tasks/release.sh +++ b/tasks/release.sh @@ -1,3 +1,4 @@ +#!/bin/bash # Copyright (c) 2015-present, Facebook, Inc. # All rights reserved. # From ecacd5532eef533b791ca581bc38eb2777b8525d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 5 Aug 2016 18:39:50 +0100 Subject: [PATCH 003/248] Tweak Jest default settings (#378) Disable timer mocking and enable verbose output. --- config/jest/environment.js | 7 +++++++ scripts/eject.js | 1 + scripts/utils/createJestConfig.js | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 config/jest/environment.js diff --git a/config/jest/environment.js b/config/jest/environment.js new file mode 100644 index 00000000000..e7c1df906c6 --- /dev/null +++ b/config/jest/environment.js @@ -0,0 +1,7 @@ +// Currently, Jest mocks setTimeout() and similar functions by default: +// https://facebook.github.io/jest/docs/timer-mocks.html +// We think this is confusing, so we disable this feature. +// If you see value in it, run `jest.useFakeTimers()` in individual tests. +beforeEach(() => { + jest.useRealTimers(); +}); diff --git a/scripts/eject.js b/scripts/eject.js index 82202d6eed9..55661d19285 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -41,6 +41,7 @@ prompt( path.join('config', 'webpack.config.prod.js'), path.join('config', 'jest', 'CSSStub.js'), path.join('config', 'jest', 'FileStub.js'), + path.join('config', 'jest', 'environment.js'), path.join('config', 'jest', 'transform.js'), path.join('scripts', 'build.js'), path.join('scripts', 'start.js'), diff --git a/scripts/utils/createJestConfig.js b/scripts/utils/createJestConfig.js index 282705f0dd3..d4ee867f473 100644 --- a/scripts/utils/createJestConfig.js +++ b/scripts/utils/createJestConfig.js @@ -19,7 +19,9 @@ module.exports = (resolve, rootDir) => { setupFiles: [ resolve('config/polyfills.js') ], - testEnvironment: 'node' + setupTestFrameworkScriptFile: resolve('config/jest/environment.js'), + testEnvironment: 'node', + verbose: true }; if (rootDir) { config.rootDir = rootDir; From 8ad2dcc6ce7725632ad92be86628548703de0c61 Mon Sep 17 00:00:00 2001 From: Kamil Burzynski Date: Sat, 6 Aug 2016 10:54:22 +0200 Subject: [PATCH 004/248] Fixed typo (#382) --- template/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/README.md b/template/README.md index 441953eef69..65984ecafb9 100644 --- a/template/README.md +++ b/template/README.md @@ -489,7 +489,7 @@ This way, when you `fetch('/api/todos')` in development, the development server Conveniently, this avoids [CORS issues](http://stackoverflow.com/questions/21854516/understanding-ajax-cors-and-security-considerations) and error messages like this in development: ``` -Fetch API cannot load http://localhost:400/api/todos. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. +Fetch API cannot load http://localhost:4000/api/todos. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. ``` Keep in mind that `proxy` only has effect in development (with `npm start`), and it is up to you to ensure that URLs like `/api/todos` point to the right thing in production. You don’t have to use the `/api` prefix. Any unrecognized request will be redirected to the specified `proxy`. From 46fe4a6572eff02f039cc770ad74ed5fa76d54b4 Mon Sep 17 00:00:00 2001 From: Rifat Nabi Date: Mon, 8 Aug 2016 10:05:58 +0600 Subject: [PATCH 005/248] Creating a new app in the current directory (#368) * Creating a new app in the current directory * Fixed style mistakes --- global-cli/index.js | 24 ++++++++++++++++++------ global-cli/package.json | 1 + package.json | 1 + scripts/init.js | 24 +++++++++++++++++++++++- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/global-cli/index.js b/global-cli/index.js index d1319aba06f..e8dc5a7184a 100644 --- a/global-cli/index.js +++ b/global-cli/index.js @@ -41,6 +41,7 @@ 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: @@ -67,21 +68,20 @@ if (commands.length === 0) { createApp(commands[0], argv.verbose, argv['scripts-version']); function createApp(name, verbose, version) { - if (fs.existsSync(name)) { - console.log('The directory `' + name + '` already exists. Aborting.'); + var root = path.resolve(name); + if (!pathExists.sync(name)) { + fs.mkdirSync(root); + } else if (!isGitHubBoilerplate(root)) { + console.log('The directory `' + name + '` contains file(s) that could conflict. Aborting.'); process.exit(1); } - var root = path.resolve(name); var appName = path.basename(root); - console.log( 'Creating a new React app in ' + root + '.' ); console.log(); - fs.mkdirSync(root); - var packageJson = { name: appName, version: '0.0.1', @@ -166,3 +166,15 @@ function checkNodeVersion() { process.exit(1); } } + +// Check if GitHub boilerplate compatible +// https://github.com/facebookincubator/create-react-app/pull/368#issuecomment-237875655 +function isGitHubBoilerplate(root) { + var validFiles = [ + '.DS_Store', 'Thumbs.db', '.git', '.gitignore', 'README.md', 'LICENSE' + ]; + return fs.readdirSync(root) + .every(function(file) { + return validFiles.indexOf(file) >= 0; + }); +} diff --git a/global-cli/package.json b/global-cli/package.json index 3e98c4c939a..8d038be6783 100644 --- a/global-cli/package.json +++ b/global-cli/package.json @@ -20,6 +20,7 @@ "chalk": "^1.1.1", "cross-spawn": "^4.0.0", "minimist": "^1.2.0", + "path-exists": "^3.0.0", "semver": "^5.0.3" } } diff --git a/package.json b/package.json index bf3d853af2a..accba6a051f 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "jest": "14.1.0", "json-loader": "0.5.4", "opn": "4.0.2", + "path-exists": "^3.0.0", "postcss-loader": "0.9.1", "promise": "7.1.1", "recursive-readdir": "2.0.0", diff --git a/scripts/init.js b/scripts/init.js index 50cc9d25ba7..074fe428aef 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -10,6 +10,8 @@ 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 ownPath = path.join(appPath, 'node_modules', 'react-scripts'); @@ -43,12 +45,28 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { JSON.stringify(appPackage, null, 2) ); + var readmeExists = pathExists.sync(path.join(appPath, 'README.md')); + if (readmeExists) { + fs.renameSync(path.join(appPath, 'README.md'), path.join(appPath, 'README.old.md')); + } + // Copy the files for the user fs.copySync(path.join(ownPath, 'template'), appPath); // Rename gitignore after the fact to prevent npm from renaming it to .npmignore // See: https://github.com/npm/npm/issues/1862 - fs.move(path.join(appPath, 'gitignore'), path.join(appPath, '.gitignore'), []); + fs.move(path.join(appPath, 'gitignore'), path.join(appPath, '.gitignore'), [], function (err) { + if (err) { + // Append if there's already a `.gitignore` file there + if (err.code === 'EEXIST') { + var data = fs.readFileSync(path.join(appPath, 'gitignore')); + fs.appendFileSync(path.join(appPath, '.gitignore'), data); + fs.unlinkSync(path.join(appPath, 'gitignore')); + } else { + throw err; + } + } + }); // Run another npm install for react and react-dom console.log('Installing react and react-dom from npm...'); @@ -88,6 +106,10 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { console.log(); console.log(' cd', cdpath); console.log(' npm start'); + if (readmeExists) { + console.log(); + console.log(chalk.yellow('You had a `README.md` file, we renamed it to `README.old.md`')); + } console.log(); console.log('Happy hacking!'); }); From 73a116edc2420198ecb1f1025b901b45ccbc3470 Mon Sep 17 00:00:00 2001 From: Gregory Shehet Date: Mon, 8 Aug 2016 14:53:38 +0300 Subject: [PATCH 006/248] Update package.json (#397) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index accba6a051f..4f82dd29a13 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "jest": "14.1.0", "json-loader": "0.5.4", "opn": "4.0.2", - "path-exists": "^3.0.0", + "path-exists": "3.0.0", "postcss-loader": "0.9.1", "promise": "7.1.1", "recursive-readdir": "2.0.0", From 0af726288048ef553fb4fbc9fd30403263309cc1 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 8 Aug 2016 13:50:49 +0100 Subject: [PATCH 007/248] Add Object.assign() polyfill (#399) --- config/polyfills.js | 4 ++++ package.json | 1 + 2 files changed, 5 insertions(+) diff --git a/config/polyfills.js b/config/polyfills.js index 1f71e4ac4f2..7e601502b24 100644 --- a/config/polyfills.js +++ b/config/polyfills.js @@ -8,3 +8,7 @@ if (typeof Promise === 'undefined') { // fetch() polyfill for making API calls. require('whatwg-fetch'); + +// Object.assign() is commonly used with React. +// It will use the native implementation if it's present and isn't buggy. +Object.assign = require('object-assign'); diff --git a/package.json b/package.json index 4f82dd29a13..4dafc9670e7 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "http-proxy-middleware": "0.17.0", "jest": "14.1.0", "json-loader": "0.5.4", + "object-assign": "4.1.0", "opn": "4.0.2", "path-exists": "3.0.0", "postcss-loader": "0.9.1", From 94886745285946ee5a45a874468872abc60276d2 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 8 Aug 2016 13:58:40 +0100 Subject: [PATCH 008/248] Bump case-sensitive-paths-webpack-plugin Fixes #391 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4dafc9670e7..4b83b1343fd 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "babel-preset-es2016": "6.11.3", "babel-preset-react": "6.11.1", "babel-runtime": "6.11.6", - "case-sensitive-paths-webpack-plugin": "1.1.2", + "case-sensitive-paths-webpack-plugin": "1.1.3", "chalk": "1.1.3", "connect-history-api-fallback": "1.2.0", "cross-spawn": "4.0.0", From 4b39705b2d63f0b85597fcdd9d1d50a8e9555537 Mon Sep 17 00:00:00 2001 From: Marco Botto Date: Mon, 8 Aug 2016 15:19:17 +0200 Subject: [PATCH 009/248] Add Surge.sh to deploy instructions (#379) * Add Surge.sh to deploy instructions * Add it also to the Table of Contents --- template/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/template/README.md b/template/README.md index 65984ecafb9..6245d730885 100644 --- a/template/README.md +++ b/template/README.md @@ -24,6 +24,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [Deployment](#deployment) - [Now](#now) - [Heroku](#heroku) + - [Surge](#surge) - [GitHub Pages](#github-pages) - [Something Missing?](#something-missing) @@ -519,6 +520,27 @@ See [this example](https://github.com/xkawi/create-react-app-now) for a zero-con Use the [Heroku Buildpack for create-react-app](https://github.com/mars/create-react-app-buildpack). +### Surge + +Install the Surge CLI if you haven't already by running `npm install -g surge`. Run the `surge` command and log in you or create a new account. You just need to specify the *build* folder and your custom domain, and you are done. + +```sh + email: email@domain.com + password: ******** + project path: /path/to/project/build + size: 7 files, 1.8 MB + domain: create-react-app.surge.sh + upload: [====================] 100%, eta: 0.0s + propagate on CDN: [====================] 100% + plan: Free + users: email@domain.com + IP Address: X.X.X.X + + Success! Project is published and running at create-react-app.surge.sh +``` + +Note that in order to support routers that use html5 `pushState` API, you may want to rename the `index.html` in your build folder to `200.html` before deploying to Surge. This [ensures that every URL falls back to that file](https://surge.sh/help/adding-a-200-page-for-client-side-routing). + ### GitHub Pages >Note: this feature is available with `react-scripts@0.2.0` and higher. From 975b2ba84161bfd6060834b59020026ffb34291f Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 8 Aug 2016 14:23:12 +0100 Subject: [PATCH 010/248] Allow popular test path conventions (#400) --- scripts/utils/createJestConfig.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/utils/createJestConfig.js b/scripts/utils/createJestConfig.js index d4ee867f473..3072074807e 100644 --- a/scripts/utils/createJestConfig.js +++ b/scripts/utils/createJestConfig.js @@ -20,6 +20,12 @@ module.exports = (resolve, rootDir) => { resolve('config/polyfills.js') ], setupTestFrameworkScriptFile: resolve('config/jest/environment.js'), + testPathIgnorePatterns: ['/node_modules/', '/build/'], + // Allow three popular conventions: + // **/__tests__/*.js + // **/*.test.js + // **/*.spec.js + testRegex: '(__tests__/.*|\\.(test|spec))\\.js$', testEnvironment: 'node', verbose: true }; From 2dbab0b35f1c292475d621dca89fb0340972bdeb Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 8 Aug 2016 18:49:51 +0100 Subject: [PATCH 011/248] Make build output more chill --- scripts/build.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index 1f3079f2594..b02d8dc3200 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -130,13 +130,13 @@ function build(previousSizeMap) { console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.'); console.log('To publish it at ' + chalk.green(homepagePath) + ', run:'); console.log(); - console.log(' ' + chalk.blue('git') + chalk.cyan(' commit -am ') + chalk.yellow('"Save local changes"')); - console.log(' ' + chalk.blue('git') + chalk.cyan(' checkout -B gh-pages')); - console.log(' ' + chalk.blue('git') + chalk.cyan(' add -f build')); - console.log(' ' + chalk.blue('git') + chalk.cyan(' commit -am ' + chalk.yellow('"Rebuild website"'))); - console.log(' ' + chalk.blue('git') + chalk.cyan(' filter-branch -f --prune-empty --subdirectory-filter build')); - console.log(' ' + chalk.blue('git') + chalk.cyan(' push -f origin gh-pages')); - console.log(' ' + chalk.blue('git') + chalk.cyan(' checkout -')); + console.log(' ' + chalk.cyan('git') + ' commit -am ' + chalk.yellow('"Save local changes"')); + console.log(' ' + chalk.cyan('git') + ' checkout -B gh-pages'); + console.log(' ' + chalk.cyan('git') + ' add -f build'); + console.log(' ' + chalk.cyan('git') + ' commit -am ' + chalk.yellow('"Rebuild website"')); + console.log(' ' + chalk.cyan('git') + ' filter-branch -f --prune-empty --subdirectory-filter build'); + console.log(' ' + chalk.cyan('git') + ' push -f origin gh-pages'); + console.log(' ' + chalk.cyan('git') + ' checkout -'); console.log(); } else if (publicPath !== '/') { // "homepage": "http://mywebsite.com/project" @@ -163,9 +163,9 @@ 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.blue('npm') + chalk.cyan(' install -g pushstate-server')); - console.log(' ' + chalk.blue('pushstate-server') + chalk.cyan(' build')); - console.log(' ' + chalk.blue(openCommand) + chalk.cyan(' http://localhost:9000')); + 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(); } }); From 239741353f6d36fc372e2e8316a13f89e61adcd4 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 8 Aug 2016 18:58:32 +0100 Subject: [PATCH 012/248] Make missing module output slimmer Thanks to @geowarin for the tip in https://github.com/facebookincubator/create-react-app/issues/401#issuecomment-238291901 --- scripts/start.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/start.js b/scripts/start.js index fcd1338d3c3..84cf4f71272 100644 --- a/scripts/start.js +++ b/scripts/start.js @@ -108,7 +108,9 @@ function setupCompiler(port) { // 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 json = stats.toJson(); + // We use stats.toJson({}, true) to make output more compact and readable: + // https://github.com/facebookincubator/create-react-app/issues/401#issuecomment-238291901 + var json = stats.toJson({}, true); var formattedErrors = json.errors.map(message => 'Error in ' + formatMessage(message) ); From 078e011fe9d8b2cff8b8824ca0d8f72b82cc5d52 Mon Sep 17 00:00:00 2001 From: Luigi Maselli Date: Tue, 9 Aug 2016 12:42:37 +0200 Subject: [PATCH 013/248] Add React Native Web support (#407) --- config/webpack.config.dev.js | 3 ++- config/webpack.config.prod.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index a3db11f8ec7..ae95e0d92b8 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -76,7 +76,8 @@ module.exports = { // if we don't have a good solution, we should just make `babel-runtime` // a dependency in generated projects. // See https://github.com/facebookincubator/create-react-app/issues/255 - 'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator') + 'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator'), + 'react-native': 'react-native-web' } }, // Resolve loaders (webpack plugins for CSS, images, transpilation) from the diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 2a3b1a81868..66ca7a8cec1 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -71,7 +71,8 @@ module.exports = { // if we don't have a good solution, we should just make `babel-runtime` // a dependency in generated projects. // See https://github.com/facebookincubator/create-react-app/issues/255 - 'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator') + 'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator'), + 'react-native': 'react-native-web' } }, // Resolve loaders (webpack plugins for CSS, images, transpilation) from the From 905157a3bf223489d6c7f886ca3ae53426a10458 Mon Sep 17 00:00:00 2001 From: Max Stoiber Date: Thu, 11 Aug 2016 23:04:29 +0200 Subject: [PATCH 014/248] Disable dot rule of connect-history-api-fallback (#422) Ref #387 --- package.json | 2 +- scripts/start.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b83b1343fd..77910fcf349 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "babel-runtime": "6.11.6", "case-sensitive-paths-webpack-plugin": "1.1.3", "chalk": "1.1.3", - "connect-history-api-fallback": "1.2.0", + "connect-history-api-fallback": "1.3.0", "cross-spawn": "4.0.0", "css-loader": "0.23.1", "detect-port": "1.0.0", diff --git a/scripts/start.js b/scripts/start.js index 84cf4f71272..aa68ab40ff3 100644 --- a/scripts/start.js +++ b/scripts/start.js @@ -173,6 +173,8 @@ function addMiddleware(devServer) { // Every unrecognized request will be forwarded to it. var proxy = require(paths.appPackageJson).proxy; devServer.use(historyApiFallback({ + // Allow paths with dots in them to be loaded, reference issue #387 + disableDotRule: true, // For single page apps, we generally want to fallback to /index.html. // However we also want to respect `proxy` for API calls. // So if `proxy` is specified, we need to decide which fallback to use. From 799131fa1c3c77dcca77a18c9521ed6f488bf3ed Mon Sep 17 00:00:00 2001 From: Andrey Popp <8mayday@gmail.com> Date: Sat, 13 Aug 2016 00:37:54 +0300 Subject: [PATCH 015/248] Load favicon through html-loader. (#428) * Load favicon through html-loader. Fixes #291. * Add test for *.ico in e2e test suite * Configure html-loader to process * Address feedback on html-loader inclusion. * Place favicon.ico at the root of the build dir * Make comment style consistent between prod and dev webpack configs * Fix html-loader config in dev mode --- config/paths.js | 3 --- config/webpack.config.dev.js | 22 ++++++++++++++++++++-- config/webpack.config.prod.js | 30 ++++++++++++++++++++++++------ package.json | 1 + tasks/e2e.sh | 3 +++ template/index.html | 1 + template/{ => src}/favicon.ico | Bin 7 files changed, 49 insertions(+), 11 deletions(-) rename template/{ => src}/favicon.ico (100%) diff --git a/config/paths.js b/config/paths.js index 7645917fbc9..e6f2ff6cb3a 100644 --- a/config/paths.js +++ b/config/paths.js @@ -36,7 +36,6 @@ if (isInCreateReactAppSource) { module.exports = { appBuild: resolveOwn('../build'), appHtml: resolveOwn('../template/index.html'), - appFavicon: resolveOwn('../template/favicon.ico'), appPackageJson: resolveOwn('../package.json'), appSrc: resolveOwn('../template/src'), appNodeModules: resolveOwn('../node_modules'), @@ -47,7 +46,6 @@ if (isInCreateReactAppSource) { module.exports = { appBuild: resolveApp('build'), appHtml: resolveApp('index.html'), - appFavicon: resolveApp('favicon.ico'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), appNodeModules: resolveApp('node_modules'), @@ -59,7 +57,6 @@ if (isInCreateReactAppSource) { module.exports = { appBuild: resolveApp('build'), appHtml: resolveApp('index.html'), - appFavicon: resolveApp('favicon.ico'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), appNodeModules: resolveApp('node_modules'), diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index ae95e0d92b8..5e28bb7c916 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -126,13 +126,23 @@ module.exports = { // When you `import` an asset, you get its (virtual) filename. // In production, they would get copied to the `build` folder. { - test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, include: [paths.appSrc, paths.appNodeModules], + exclude: /\/favicon.ico$/, loader: 'file', query: { name: 'static/media/[name].[ext]' } }, + // A special case for favicon.ico to place it into build root directory. + { + test: /\/favicon.ico$/, + include: [paths.appSrc], + loader: 'file', + query: { + name: 'favicon.ico?[hash:8]' + } + }, // "url" loader works just like "file" loader but it also embeds // assets smaller than specified size as data URLs to avoid requests. { @@ -143,6 +153,15 @@ module.exports = { limit: 10000, name: 'static/media/[name].[ext]' } + }, + // "html" loader is used to process template page (index.html) to resolve + // resources linked with HTML tags. + { + test: /\.html$/, + loader: 'html', + query: { + attrs: ['link:href'], + } } ] }, @@ -169,7 +188,6 @@ module.exports = { new HtmlWebpackPlugin({ inject: true, template: paths.appHtml, - favicon: paths.appFavicon, }), // Makes some environment variables available to the JS code, for example: // if (process.env.NODE_ENV === 'development') { ... }. See `env.js`. diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 66ca7a8cec1..ffeb75a9488 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -126,23 +126,33 @@ module.exports = { loader: ExtractTextPlugin.extract('style', 'css?-autoprefixer!postcss') // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, + // JSON is not enabled by default in Webpack but both Node and Browserify + // allow it implicitly so we also enable it. { - // JSON is not enabled by default in Webpack but both Node and Browserify - // allow it implicitly so we also enable it. test: /\.json$/, include: [paths.appSrc, paths.appNodeModules], 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 makes sure those assets end up in the `build` folder. - // When you `import` an asset, you get its filename. - test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + exclude: /\/favicon.ico$/, include: [paths.appSrc, paths.appNodeModules], loader: 'file', query: { name: 'static/media/[name].[hash:8].[ext]' } }, + // A special case for favicon.ico to place it into build root directory. + { + test: /\/favicon.ico$/, + include: [paths.appSrc], + loader: 'file', + query: { + name: 'favicon.ico?[hash:8]' + } + }, // "url" loader works just like "file" loader but it also embeds // assets smaller than specified size as data URLs to avoid requests. { @@ -153,6 +163,15 @@ module.exports = { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' } + }, + // "html" loader is used to process template page (index.html) to resolve + // resources linked with HTML tags. + { + test: /\.html$/, + loader: 'html', + query: { + attrs: ['link:href'], + } } ] }, @@ -181,7 +200,6 @@ module.exports = { new HtmlWebpackPlugin({ inject: true, template: paths.appHtml, - favicon: paths.appFavicon, minify: { removeComments: true, collapseWhitespace: true, diff --git a/package.json b/package.json index 77910fcf349..1b389da8005 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "filesize": "3.3.0", "fs-extra": "0.30.0", "gzip-size": "3.0.0", + "html-loader": "0.4.3", "html-webpack-plugin": "2.22.0", "http-proxy-middleware": "0.17.0", "jest": "14.1.0", diff --git a/tasks/e2e.sh b/tasks/e2e.sh index a1566a85bdb..6e6c20c9420 100755 --- a/tasks/e2e.sh +++ b/tasks/e2e.sh @@ -67,6 +67,7 @@ test -e build/*.html test -e build/static/js/*.js test -e build/static/css/*.css test -e build/static/media/*.svg +test -e build/favicon.ico # Run tests npm run test @@ -96,6 +97,7 @@ test -e build/*.html test -e build/static/js/*.js test -e build/static/css/*.css test -e build/static/media/*.svg +test -e build/favicon.ico # Run tests npm run test @@ -113,6 +115,7 @@ test -e build/*.html test -e build/static/js/*.js test -e build/static/css/*.css test -e build/static/media/*.svg +test -e build/favicon.ico # Run tests npm run test diff --git a/template/index.html b/template/index.html index 72e10e94c6c..f89671553eb 100644 --- a/template/index.html +++ b/template/index.html @@ -3,6 +3,7 @@ + React App diff --git a/template/favicon.ico b/template/src/favicon.ico similarity index 100% rename from template/favicon.ico rename to template/src/favicon.ico From 598cdb3382aa9f44b284fb8ae4220a90527b9b1c Mon Sep 17 00:00:00 2001 From: Arunoda Susiripala Date: Tue, 16 Aug 2016 00:23:19 +0530 Subject: [PATCH 016/248] Add a hash to media files even in the devmode. (#446) This will work correctly when there are duplicate filenames in different paths. Fixes: #445 --- config/webpack.config.dev.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 5e28bb7c916..397acd315e9 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -131,7 +131,7 @@ module.exports = { exclude: /\/favicon.ico$/, loader: 'file', query: { - name: 'static/media/[name].[ext]' + name: 'static/media/[name].[hash:8].[ext]' } }, // A special case for favicon.ico to place it into build root directory. @@ -151,7 +151,7 @@ module.exports = { loader: 'url', query: { limit: 10000, - name: 'static/media/[name].[ext]' + name: 'static/media/[name].[hash:8].[ext]' } }, // "html" loader is used to process template page (index.html) to resolve From a32afd3af0de1179f4a9faf3f325b4da29ba6aaf Mon Sep 17 00:00:00 2001 From: Gregory Shehet Date: Thu, 18 Aug 2016 21:47:39 +0300 Subject: [PATCH 017/248] add otf font format to loaders (#434) * add off font format to loaders * add otf format support --- config/eslint.js | 2 +- config/webpack.config.dev.js | 2 +- config/webpack.config.prod.js | 2 +- scripts/utils/createJestConfig.js | 2 +- template/README.md | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/eslint.js b/config/eslint.js index 513ad2de02f..761add0f718 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -45,7 +45,7 @@ module.exports = { settings: { 'import/ignore': [ 'node_modules', - '\\.(json|css|jpg|png|gif|eot|svg|ttf|woff|woff2|mp4|webm)$', + '\\.(json|css|jpg|png|gif|eot|otf|svg|ttf|woff|woff2|mp4|webm)$', ], 'import/extensions': ['.js'], 'import/resolver': { diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 397acd315e9..2b6da367f79 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -126,7 +126,7 @@ module.exports = { // When you `import` an asset, you get its (virtual) filename. // In production, they would get copied to the `build` folder. { - test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|otf|svg|ttf|woff|woff2)(\?.*)?$/, include: [paths.appSrc, paths.appNodeModules], exclude: /\/favicon.ico$/, loader: 'file', diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index ffeb75a9488..5781ae8636b 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -136,7 +136,7 @@ module.exports = { // "file" loader makes sure those assets end up in the `build` folder. // When you `import` an asset, you get its filename. { - test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|otf|svg|ttf|woff|woff2)(\?.*)?$/, exclude: /\/favicon.ico$/, include: [paths.appSrc, paths.appNodeModules], loader: 'file', diff --git a/scripts/utils/createJestConfig.js b/scripts/utils/createJestConfig.js index 3072074807e..a420e6fd6bc 100644 --- a/scripts/utils/createJestConfig.js +++ b/scripts/utils/createJestConfig.js @@ -11,7 +11,7 @@ module.exports = (resolve, rootDir) => { const config = { automock: false, moduleNameMapper: { - '^[./a-zA-Z0-9$_-]+\\.(jpg|png|gif|eot|svg|ttf|woff|woff2|mp4|webm)$': resolve('config/jest/FileStub.js'), + '^[./a-zA-Z0-9$_-]+\\.(jpg|png|gif|eot|otf|svg|ttf|woff|woff2|mp4|webm)$': resolve('config/jest/FileStub.js'), '^[./a-zA-Z0-9$_-]+\\.css$': resolve('config/jest/CSSStub.js') }, persistModuleRegistryBetweenSpecs: true, diff --git a/template/README.md b/template/README.md index 6245d730885..821b0b68a67 100644 --- a/template/README.md +++ b/template/README.md @@ -373,7 +373,7 @@ esproposal.class_static_fields=enable esproposal.class_instance_fields=enable module.name_mapper='^\(.*\)\.css$' -> 'react-scripts/config/flow/css' -module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> 'react-scripts/config/flow/file' +module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|otf\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> 'react-scripts/config/flow/file' suppress_type=$FlowIssue suppress_type=$FlowFixMe @@ -385,7 +385,7 @@ If you later `eject`, you’ll need to replace `react-scripts` references with t ```ini module.name_mapper='^\(.*\)\.css$' -> '/config/flow/css' -module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> '/config/flow/file' +module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|otf\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> '/config/flow/file' ``` We will consider integrating more tightly with Flow in the future so that you don’t have to do this. From 4ad0b4291339d28f370e9a8db2a8916d2bfe2d9a Mon Sep 17 00:00:00 2001 From: Robin Ricard Date: Mon, 22 Aug 2016 14:51:20 +0200 Subject: [PATCH 018/248] Deactivate the `new-cap` rule in ESLint (#470) This rule is considered dangerous in certain situations. This is especially true for Immutable.js users. See the discussion at issue #465 for more information about this. --- config/eslint.js | 1 - 1 file changed, 1 deletion(-) diff --git a/config/eslint.js b/config/eslint.js index 761add0f718..b2fb7dd7bdc 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -62,7 +62,6 @@ module.exports = { 'dot-location': ['warn', 'property'], eqeqeq: ['warn', 'allow-null'], 'guard-for-in': 'warn', - 'new-cap': ['warn', { newIsCap: true }], 'new-parens': 'warn', 'no-array-constructor': 'warn', 'no-caller': 'warn', From 70e4e2401a9e172d7edd9a6cba67b118b4db32b2 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 22 Aug 2016 19:47:49 +0100 Subject: [PATCH 019/248] Add 0.2.2 changelog (#475) --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04129633274..8f3786f6b6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## 0.2.2 (August 22, 2016) + +### Build Dependency (`react-scripts`) + +* `npm install`ing a missing dependency now forces a rebuild. ([@gaearon](https://github.com/gaearon) in [#349](https://github.com/facebookincubator/create-react-app/pull/349)) +* Autoprefixer config now includes more commonly supported browsers. ([@kripod](https://github.com/kripod) in [#345](https://github.com/facebookincubator/create-react-app/pull/345)) +* All the configuration is now documented inline so ejecting doesn’t leave you in the dark. ([@gaearon](https://github.com/gaearon) in [#362](https://github.com/facebookincubator/create-react-app/pull/362)) +* `Object.assign()` polyfill is now bundled by default. ([@gaearon](https://github.com/gaearon) in [#399](https://github.com/facebookincubator/create-react-app/pull/399)) +* [React Native Web](https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/) now works out of the box. ([@grigio](https://github.com/grigio) in [#407](https://github.com/facebookincubator/create-react-app/pull/407)) +* Same asset filenames in different folders don’t confuse the server now. ([@arunoda](https://github.com/arunoda) in [#446](https://github.com/facebookincubator/create-react-app/pull/446)) +* The `otf` font format is now supported. ([@A-gambit](https://github.com/A-gambit) in [#434](https://github.com/facebookincubator/create-react-app/pull/434)) +* The `new-cap` linting rule has been disabled thanks to feedback from Immutable.js users. ([@rricard](https://github.com/rricard) in [#470](https://github.com/facebookincubator/create-react-app/pull/470)) + ## 0.2.1 (August 1, 2016) ### Build Dependency (`react-scripts`) From 34a849ed93634a2583c11735c112c7f0e5c4690d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 22 Aug 2016 19:48:59 +0100 Subject: [PATCH 020/248] Add migration instructions --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f3786f6b6f..066065fc0f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ * The `otf` font format is now supported. ([@A-gambit](https://github.com/A-gambit) in [#434](https://github.com/facebookincubator/create-react-app/pull/434)) * The `new-cap` linting rule has been disabled thanks to feedback from Immutable.js users. ([@rricard](https://github.com/rricard) in [#470](https://github.com/facebookincubator/create-react-app/pull/470)) +### Migrating from 0.2.1 to 0.2.2 + +Update `react-scripts` to point to `0.2.2` in your `package.json` and run `npm install`. You shouldn’t need to do anything else. + +Newly created projects will use `0.2.2` automatically. You **don’t** need to update the global `create-react-app` CLI itself. It stays at `0.2.0` for now because it doesn’t have any changes. + + ## 0.2.1 (August 1, 2016) ### Build Dependency (`react-scripts`) From 9b6c1fb44f5d74fbc9a549422445489177fa1987 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 22 Aug 2016 20:21:35 +0100 Subject: [PATCH 021/248] Link to Heroku article --- template/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/template/README.md b/template/README.md index 821b0b68a67..37800052b31 100644 --- a/template/README.md +++ b/template/README.md @@ -518,7 +518,8 @@ See [this example](https://github.com/xkawi/create-react-app-now) for a zero-con ### Heroku -Use the [Heroku Buildpack for create-react-app](https://github.com/mars/create-react-app-buildpack). +Use the [Heroku Buildpack for Create React App](https://github.com/mars/create-react-app-buildpack). +You can find instructions in [Deploying React with Zero Configuration](https://blog.heroku.com/deploying-react-with-zero-configuration). ### Surge From 6c17901c5f0944d6436c075e072ebda8120948ea Mon Sep 17 00:00:00 2001 From: Felipe Moyano Date: Tue, 23 Aug 2016 10:13:13 -0500 Subject: [PATCH 022/248] Added support for webp images in #442 (#458) --- config/eslint.js | 2 +- config/webpack.config.dev.js | 2 +- config/webpack.config.prod.js | 2 +- scripts/utils/createJestConfig.js | 2 +- template/README.md | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/eslint.js b/config/eslint.js index b2fb7dd7bdc..eb2a87ce135 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -45,7 +45,7 @@ module.exports = { settings: { 'import/ignore': [ 'node_modules', - '\\.(json|css|jpg|png|gif|eot|otf|svg|ttf|woff|woff2|mp4|webm)$', + '\\.(json|css|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm)$', ], 'import/extensions': ['.js'], 'import/resolver': { diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 2b6da367f79..b93abcdad20 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -126,7 +126,7 @@ module.exports = { // When you `import` an asset, you get its (virtual) filename. // In production, they would get copied to the `build` folder. { - test: /\.(ico|jpg|png|gif|eot|otf|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/, include: [paths.appSrc, paths.appNodeModules], exclude: /\/favicon.ico$/, loader: 'file', diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 5781ae8636b..8b04ec4b650 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -136,7 +136,7 @@ module.exports = { // "file" loader makes sure those assets end up in the `build` folder. // When you `import` an asset, you get its filename. { - test: /\.(ico|jpg|png|gif|eot|otf|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/, exclude: /\/favicon.ico$/, include: [paths.appSrc, paths.appNodeModules], loader: 'file', diff --git a/scripts/utils/createJestConfig.js b/scripts/utils/createJestConfig.js index a420e6fd6bc..8b6bfd52492 100644 --- a/scripts/utils/createJestConfig.js +++ b/scripts/utils/createJestConfig.js @@ -11,7 +11,7 @@ module.exports = (resolve, rootDir) => { const config = { automock: false, moduleNameMapper: { - '^[./a-zA-Z0-9$_-]+\\.(jpg|png|gif|eot|otf|svg|ttf|woff|woff2|mp4|webm)$': resolve('config/jest/FileStub.js'), + '^[./a-zA-Z0-9$_-]+\\.(jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm)$': resolve('config/jest/FileStub.js'), '^[./a-zA-Z0-9$_-]+\\.css$': resolve('config/jest/CSSStub.js') }, persistModuleRegistryBetweenSpecs: true, diff --git a/template/README.md b/template/README.md index 37800052b31..0395c0f496a 100644 --- a/template/README.md +++ b/template/README.md @@ -373,7 +373,7 @@ esproposal.class_static_fields=enable esproposal.class_instance_fields=enable module.name_mapper='^\(.*\)\.css$' -> 'react-scripts/config/flow/css' -module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|otf\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> 'react-scripts/config/flow/file' +module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|otf\|webp\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> 'react-scripts/config/flow/file' suppress_type=$FlowIssue suppress_type=$FlowFixMe @@ -385,7 +385,7 @@ If you later `eject`, you’ll need to replace `react-scripts` references with t ```ini module.name_mapper='^\(.*\)\.css$' -> '/config/flow/css' -module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|otf\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> '/config/flow/file' +module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|otf\|webp\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> '/config/flow/file' ``` We will consider integrating more tightly with Flow in the future so that you don’t have to do this. From 2af565cb1e964c5681fa73b63e49296489b8add0 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 23 Aug 2016 23:19:37 +0100 Subject: [PATCH 023/248] Clarify "homepage" field has special meaning --- template/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/template/README.md b/template/README.md index 0395c0f496a..e98584eaccc 100644 --- a/template/README.md +++ b/template/README.md @@ -552,6 +552,9 @@ Open your `package.json` and add a `homepage` field: "homepage": "http://myusername.github.io/my-app", ``` +**The above step is important!** +Create React App uses the `homepage` field to determine the root URL in the built HTML file. + Now, whenever you run `npm run build`, you will see a cheat sheet with a sequence of commands to deploy to GitHub pages: ```sh From fe7af217ded05e91a42d5317f70cfddbd2e454d3 Mon Sep 17 00:00:00 2001 From: Gautier Date: Wed, 24 Aug 2016 11:46:54 +0200 Subject: [PATCH 024/248] Correcting typo on README.md (#479) Small typo line 572 "becasue" to "because" --- template/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/README.md b/template/README.md index e98584eaccc..d6a97de9186 100644 --- a/template/README.md +++ b/template/README.md @@ -569,7 +569,7 @@ git checkout - You may copy and paste them, or put them into a custom shell script. You may also customize them for another hosting provider. -Note that GitHub Pages doesn't support routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`). This is becasue when there is a fresh page load for a url like `http://user.github.io/todomvc/todos/42`, where `/todos/42` is a frontend route, the GitHub Pages server returns 404 because it knows nothing of `/todos/42`. If you want to add a router to a project hosted on GitHub Pages, here are a couple of solutions: +Note that GitHub Pages doesn't support routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`). This is because when there is a fresh page load for a url like `http://user.github.io/todomvc/todos/42`, where `/todos/42` is a frontend route, the GitHub Pages server returns 404 because it knows nothing of `/todos/42`. If you want to add a router to a project hosted on GitHub Pages, here are a couple of solutions: * You could switch from using HTML5 history API to routing with hashes. If you use React Router, you can switch to `hashHistory` for this effect, but the URL will be longer and more verbose (for example, `http://user.github.io/todomvc/#/todos/42?_k=yknaj`). [Read more](https://github.com/reactjs/react-router/blob/master/docs/guides/Histories.md#histories) about different history implementations in React Router. * Alternatively, you can use a trick to teach GitHub Pages to handle 404 by redirecting to your `index.html` page with a special redirect parameter. You would need to add a `404.html` file with the redirection code to the `build` folder before deploying your project, and you’ll need to add code handling the redirect parameter to `index.html`. You can find a detailed explanation of this technique [in this guide](https://github.com/rafrex/spa-github-pages). From 00f0625117b940437cc9f8b757bf7190535d4098 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 25 Aug 2016 11:10:49 +0100 Subject: [PATCH 025/248] Clarify 0.3.0 is not out yet --- template/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/template/README.md b/template/README.md index d6a97de9186..ed745e73c9e 100644 --- a/template/README.md +++ b/template/README.md @@ -392,7 +392,8 @@ We will consider integrating more tightly with Flow in the future so that you do ## Adding Custom Environment Variables -> Note: this feature is available with `react-scripts@0.3.0` and higher. +**Note: this feature will be available with `react-scripts@0.3.0` and higher.** +**It is not released yet, but it will be a part of a future release.** Your project can consume variables declared in your environment as if they were declared locally in your JS files. By default you will have `NODE_ENV` defined for you, and any other environment variables starting with @@ -466,7 +467,8 @@ Check out [this tutorial](https://www.fullstackreact.com/articles/using-create-r ## Proxying API Requests in Development ->Note: this feature is available with `react-scripts@0.3.0` and higher. +**Note: this feature will be available with `react-scripts@0.3.0` and higher.** +**It is not released yet, but it will be a part of a future release.** People often serve the front-end React app from the same host and port as their backend implementation. For example, a production setup might look like this after the app is deployed: From b5fee9b6cdb21725b42a9a1b0215f4757e5f3915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Poduszl=C3=B3?= Date: Thu, 25 Aug 2016 12:20:00 +0200 Subject: [PATCH 026/248] Fix default package version added by global CLI (#491) According to the official SemVer FAQ, versioning should start at 0.1.0 (http://semver.org/#how-should-i-deal-with-revisions-in-the-0yz-initial-development-phase) --- global-cli/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global-cli/index.js b/global-cli/index.js index e8dc5a7184a..9a298b83a61 100644 --- a/global-cli/index.js +++ b/global-cli/index.js @@ -84,7 +84,7 @@ function createApp(name, verbose, version) { var packageJson = { name: appName, - version: '0.0.1', + version: '0.1.0', private: true, }; fs.writeFileSync( From 4769fcc8b6f185510f8583e5f16333199ac397d7 Mon Sep 17 00:00:00 2001 From: William Horton Date: Thu, 25 Aug 2016 06:32:11 -0400 Subject: [PATCH 027/248] Use most recent React version (#477) * Get latest version numbers of react and react-dom from npm before install. * Run separate npm installs for react, react-dom, and react-test-renderer. * Consolidate into a single npm install. * Fix misplaced parenthesis, add missing semicolon. * Add missing semicolon. --- scripts/init.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/scripts/init.js b/scripts/init.js index 074fe428aef..14ace414295 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -17,17 +17,10 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { var ownPath = path.join(appPath, 'node_modules', 'react-scripts'); var appPackage = require(path.join(appPath, 'package.json')); - var ownPackage = require(path.join(ownPath, 'package.json')); // Copy over some of the devDependencies appPackage.dependencies = appPackage.dependencies || {}; appPackage.devDependencies = appPackage.devDependencies || {}; - ['react', 'react-dom'].forEach(function (key) { - appPackage.dependencies[key] = ownPackage.devDependencies[key]; - }); - ['react-test-renderer'].forEach(function (key) { - appPackage.devDependencies[key] = ownPackage.devDependencies[key]; - }); // Setup the script rules appPackage.scripts = {}; @@ -74,6 +67,10 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { // TODO: having to do two npm installs is bad, can we avoid it? var args = [ 'install', + 'react', + 'react-dom', + 'react-test-renderer', + '--save', verbose && '--verbose' ].filter(function(e) { return e; }); var proc = spawn('npm', args, {stdio: 'inherit'}); From 2f6a2c53f01fe02ed83f5d0099020a780d0e4fb9 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 25 Aug 2016 13:34:27 +0100 Subject: [PATCH 028/248] =?UTF-8?q?Add=20missing=20Changelog=20entry?= =?UTF-8?q?=E2=80=94thanks=20@elijahmanor!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 066065fc0f8..add65d9c673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Build Dependency (`react-scripts`) +* When the bundle size changes, we now display the difference after build. ([@elijahmanor](https://github.com/elijahmanor) in [#340](https://github.com/facebookincubator/create-react-app/pull/340)) * `npm install`ing a missing dependency now forces a rebuild. ([@gaearon](https://github.com/gaearon) in [#349](https://github.com/facebookincubator/create-react-app/pull/349)) * Autoprefixer config now includes more commonly supported browsers. ([@kripod](https://github.com/kripod) in [#345](https://github.com/facebookincubator/create-react-app/pull/345)) * All the configuration is now documented inline so ejecting doesn’t leave you in the dark. ([@gaearon](https://github.com/gaearon) in [#362](https://github.com/facebookincubator/create-react-app/pull/362)) From 3ca516b678bd205eb84303b29bdb54182eff897a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Poduszl=C3=B3?= Date: Thu, 25 Aug 2016 14:52:16 +0200 Subject: [PATCH 029/248] Started using babel-preset-latest (#490) * Started using babel-preset-latest * Updated babel dependencies * Remove redundant babel-plugin-syntax-async-functions * Disabled redundant regenerator transform --- config/babel.dev.js | 15 ++++++--------- config/babel.prod.js | 15 ++++++--------- package.json | 11 ++++------- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/config/babel.dev.js b/config/babel.dev.js index 89096734713..56533109097 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -14,24 +14,21 @@ module.exports = { // It enables caching results in OS temporary directory for faster rebuilds. cacheDirectory: true, presets: [ - // let, const, destructuring, classes, modules - require.resolve('babel-preset-es2015'), - // exponentiation - require.resolve('babel-preset-es2016'), + // Latest stable ECMAScript features + require.resolve('babel-preset-latest'), // JSX, Flow require.resolve('babel-preset-react') ], plugins: [ - // function x(a, b, c,) { } - require.resolve('babel-plugin-syntax-trailing-function-commas'), - // await fetch() - require.resolve('babel-plugin-syntax-async-functions'), // 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'), + [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, diff --git a/config/babel.prod.js b/config/babel.prod.js index 92491bfcacb..32f4bd66583 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -11,24 +11,21 @@ module.exports = { // Don't try to find .babelrc because we want to force this configuration. babelrc: false, presets: [ - // let, const, destructuring, classes, modules - require.resolve('babel-preset-es2015'), - // exponentiation - require.resolve('babel-preset-es2016'), + // Latest stable ECMAScript features + require.resolve('babel-preset-latest'), // JSX, Flow require.resolve('babel-preset-react') ], plugins: [ - // function x(a, b, c,) { } - require.resolve('babel-plugin-syntax-trailing-function-commas'), - // await fetch() - require.resolve('babel-plugin-syntax-async-functions'), // 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'), + [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, diff --git a/package.json b/package.json index 1b389da8005..1694ded2b12 100644 --- a/package.json +++ b/package.json @@ -29,19 +29,16 @@ }, "dependencies": { "autoprefixer": "6.4.0", - "babel-core": "6.11.4", + "babel-core": "6.14.0", "babel-eslint": "6.1.2", "babel-jest": "14.1.0", - "babel-loader": "6.2.4", - "babel-plugin-syntax-async-functions": "6.8.0", - "babel-plugin-syntax-trailing-function-commas": "6.8.0", + "babel-loader": "6.2.5", "babel-plugin-transform-class-properties": "6.11.5", "babel-plugin-transform-object-rest-spread": "6.8.0", "babel-plugin-transform-react-constant-elements": "6.9.1", - "babel-plugin-transform-regenerator": "6.11.4", + "babel-plugin-transform-regenerator": "6.14.0", "babel-plugin-transform-runtime": "6.12.0", - "babel-preset-es2015": "6.9.0", - "babel-preset-es2016": "6.11.3", + "babel-preset-latest": "6.14.0", "babel-preset-react": "6.11.1", "babel-runtime": "6.11.6", "case-sensitive-paths-webpack-plugin": "1.1.3", From f6b7cb24c8cdbc2895b234dc3a350febcdd3e5de Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 25 Aug 2016 14:40:49 +0100 Subject: [PATCH 030/248] Prepare for 0.2.3 release --- template/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/template/README.md b/template/README.md index ed745e73c9e..4dd68fcd621 100644 --- a/template/README.md +++ b/template/README.md @@ -392,8 +392,7 @@ We will consider integrating more tightly with Flow in the future so that you do ## Adding Custom Environment Variables -**Note: this feature will be available with `react-scripts@0.3.0` and higher.** -**It is not released yet, but it will be a part of a future release.** +>Note: this feature is available with `react-scripts@0.2.3` and higher. Your project can consume variables declared in your environment as if they were declared locally in your JS files. By default you will have `NODE_ENV` defined for you, and any other environment variables starting with @@ -467,8 +466,7 @@ Check out [this tutorial](https://www.fullstackreact.com/articles/using-create-r ## Proxying API Requests in Development -**Note: this feature will be available with `react-scripts@0.3.0` and higher.** -**It is not released yet, but it will be a part of a future release.** +>Note: this feature is available with `react-scripts@0.2.3` and higher. People often serve the front-end React app from the same host and port as their backend implementation. For example, a production setup might look like this after the app is deployed: From 07acaff340502da79116d88b19252f347ac5a37a Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 25 Aug 2016 14:57:12 +0100 Subject: [PATCH 031/248] Update CHANGELOG.md (#492) --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index add65d9c673..fb5fea84c92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +## 0.2.3 (August 25, 2016) + +### Build Dependency (`react-scripts`) + +* You can now [proxy requests to an API server](https://github.com/facebookincubator/create-react-app/blob/ef94b0561d5afb9b50b905fa5cd3f94e965c69c0/template/README.md#proxying-api-requests-in-development) without worrying about CORS. ([@gaearon](https://github.com/gaearon) in [#282](https://github.com/facebookincubator/create-react-app/pull/282)) +* You can now [pass custom environment variables](https://github.com/facebookincubator/create-react-app/blob/ef94b0561d5afb9b50b905fa5cd3f94e965c69c0/template/README.md#adding-custom-environment-variables) to your application. ([@eliperelman](https://github.com/eliperelman) in [#342](https://github.com/facebookincubator/create-react-app/pull/342)) +* You can now [use `async` and `await`](https://ponyfoo.com/articles/understanding-javascript-async-await) syntax. ([@gaearon](https://github.com/gaearon) in [#327](https://github.com/facebookincubator/create-react-app/pull/327), [@fson](https://github.com/fson) in [#332](https://github.com/facebookincubator/create-react-app/pull/332)) +* Paths with period in them now load successfully on the development server. ([@mxstbr](https://github.com/mxstbr) in [#422](https://github.com/facebookincubator/create-react-app/pull/422)) +* Images with `.webp` extension are now supported. ([@gafemoyano](https://github.com/gafemoyano) in [#458](https://github.com/facebookincubator/create-react-app/pull/458)) +* The most recent version of React is now added to `package.json`. ([@wdhorton](https://github.com/wdhorton) in [#477](https://github.com/facebookincubator/create-react-app/pull/477)) +* Babel configuration is simplified. ([@kripod](https://github.com/kripod) in [#490](https://github.com/facebookincubator/create-react-app/pull/490)) + +### Migrating from 0.2.2 to 0.2.3 + +Update `react-scripts` to point to `0.2.3` in your `package.json` and run `npm install`. You shouldn’t need to do anything else. + +Newly created projects will use `0.2.3` automatically. You **don’t** need to update the global `create-react-app` CLI itself. It stays at `0.2.0` for now because it doesn’t have any changes. + ## 0.2.2 (August 22, 2016) ### Build Dependency (`react-scripts`) From b2b0ddcf73992cd42818f58013dbfb7f8af16a74 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Sun, 28 Aug 2016 13:32:17 +0100 Subject: [PATCH 032/248] Mark react-scripts as executable --- bin/react-scripts.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/react-scripts.js diff --git a/bin/react-scripts.js b/bin/react-scripts.js old mode 100644 new mode 100755 From bf26f634f048f8baa670e43a1869e27d14089b35 Mon Sep 17 00:00:00 2001 From: Ville Immonen Date: Sun, 28 Aug 2016 20:49:25 +0300 Subject: [PATCH 033/248] Allow importing static file outside src and node_modules folders (#504) Remove the `include` setting from webpack loaders for CSS, JSON and other static assets. This way it's possible to import files from a separate config folder, a parent directory etc. --- config/webpack.config.dev.js | 4 ---- config/webpack.config.prod.js | 4 ---- 2 files changed, 8 deletions(-) diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index b93abcdad20..2a66d3dd816 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -112,14 +112,12 @@ module.exports = { // in development "style" loader enables hot editing of CSS. { test: /\.css$/, - include: [paths.appSrc, paths.appNodeModules], loader: 'style!css!postcss' }, // JSON is not enabled by default in Webpack but both Node and Browserify // allow it implicitly so we also enable it. { test: /\.json$/, - include: [paths.appSrc, paths.appNodeModules], loader: 'json' }, // "file" loader makes sure those assets get served by WebpackDevServer. @@ -127,7 +125,6 @@ module.exports = { // In production, they would get copied to the `build` folder. { test: /\.(ico|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/, - include: [paths.appSrc, paths.appNodeModules], exclude: /\/favicon.ico$/, loader: 'file', query: { @@ -147,7 +144,6 @@ module.exports = { // assets smaller than specified size as data URLs to avoid requests. { test: /\.(mp4|webm)(\?.*)?$/, - include: [paths.appSrc, paths.appNodeModules], loader: 'url', query: { limit: 10000, diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 8b04ec4b650..48a37d04e61 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -114,7 +114,6 @@ module.exports = { // in the main CSS file. { test: /\.css$/, - include: [paths.appSrc, paths.appNodeModules], // "?-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 @@ -130,7 +129,6 @@ module.exports = { // allow it implicitly so we also enable it. { test: /\.json$/, - include: [paths.appSrc, paths.appNodeModules], loader: 'json' }, // "file" loader makes sure those assets end up in the `build` folder. @@ -138,7 +136,6 @@ module.exports = { { test: /\.(ico|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/, exclude: /\/favicon.ico$/, - include: [paths.appSrc, paths.appNodeModules], loader: 'file', query: { name: 'static/media/[name].[hash:8].[ext]' @@ -157,7 +154,6 @@ module.exports = { // assets smaller than specified size as data URLs to avoid requests. { test: /\.(mp4|webm)(\?.*)?$/, - include: [paths.appSrc, paths.appNodeModules], loader: 'url', query: { limit: 10000, From 54283186f3d53104c5005154daebc6a5f11dca14 Mon Sep 17 00:00:00 2001 From: Geoffroy Warin Date: Tue, 30 Aug 2016 01:32:43 +0200 Subject: [PATCH 034/248] Add tarec to the alternatives (#516) Shameless plug of course. If you want hot reloading and the best DX experience (friendly errors, desktop notifications, decorators, very fast reload times with dlls...) you should really check out [The Awsesom REact Cli](https://github.com/geowarin/tarec) (tarec). I have used it in numerous projects that now run in production and I continue to make it better day after day with a lot of love :smile: Typescript and SSR are on the roadmap! Thanks for create-react-app, it's an awesome project and a great source of inspiration :heart: --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index aac5d0b0f18..fcc1f93e18e 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,7 @@ If you don’t agree with the choices made in this project, you might want to ex * [react-app](https://github.com/kriasoft/react-app) * [dev-toolkit](https://github.com/stoikerty/dev-toolkit) * [mozilla-neo](https://github.com/mozilla/neo) +* [tarec](https://github.com/geowarin/tarec) You can also use module bundlers like [webpack](http://webpack.github.io) and [Browserify](http://browserify.org/) directly.
React documentation includes [a walkthrough](https://facebook.github.io/react/docs/package-management.html) on this topic. From 9f652118783f689600fdcfa60ead35f75480c577 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 31 Aug 2016 12:31:10 +0100 Subject: [PATCH 035/248] Add instructions on tags --- template/README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/template/README.md b/template/README.md index 4dd68fcd621..2e7c5df09cb 100644 --- a/template/README.md +++ b/template/README.md @@ -21,6 +21,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [Adding Custom Environment Variables](#adding-custom-environment-variables) - [Integrating with a Node Backend](#integrating-with-a-node-backend) - [Proxying API Requests in Development](#proxying-api-requests-in-development) +- [Adding `` Tags](#adding-meta-tags) - [Deployment](#deployment) - [Now](#now) - [Heroku](#heroku) @@ -501,6 +502,24 @@ If the `proxy` option is **not** flexible enough for you, alternatively you can: * Enable CORS on your server ([here’s how to do it for Express](http://enable-cors.org/server_expressjs.html)). * Use [environment variables](#adding-custom-environment-variables) to inject the right server host and port into your app. +## Adding `` Tags + +You can edit the generated `index.html` and add any tags you’d like to it. However, since Create React App doesn’t support server rendering, you might be wondering how to make `` tags dynamic and reflect the current URL. + +To solve this, we recommend to add placeholders into the HTML, like this: + +```html + + + + + +``` + +Then, on the server, regardless of the backend you use, you can read `index.html` into memory and replace `$OG_TITLE`, `$OG_DESCRIPTION`, and any other placeholders with values depending on the current URL. Just make sure to sanitize and escape the interpolated values so that they are safe to embed into HTML! + +If you use a Node server, you can even share the route matching logic between the client and the server. However duplicating it also works fine in simple cases. + ## Deployment By default, Create React App produces a build assuming your app is hosted at the server root. From 1e605090eb366ccc60e5ddad33c197bd2013acf6 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 31 Aug 2016 14:00:57 +0100 Subject: [PATCH 036/248] Add a link back to CRA --- template/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/template/README.md b/template/README.md index 2e7c5df09cb..31c2802d041 100644 --- a/template/README.md +++ b/template/README.md @@ -1,3 +1,5 @@ +This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app). + Below you will find some information on how to perform common tasks. You can find the most recent version of this guide [here](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md). From 7b86b810bbf1af6713b605be9d3f2bcdd0e59eca Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 31 Aug 2016 17:21:57 +0400 Subject: [PATCH 037/248] ignore .idea folder (#522) * ignore .idea folder this change is requred for IntelliJ-based products because project information files are written before actual generator is invoked * better method name and explanation --- global-cli/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/global-cli/index.js b/global-cli/index.js index 9a298b83a61..dc6262b71ac 100644 --- a/global-cli/index.js +++ b/global-cli/index.js @@ -71,7 +71,7 @@ function createApp(name, verbose, version) { var root = path.resolve(name); if (!pathExists.sync(name)) { fs.mkdirSync(root); - } else if (!isGitHubBoilerplate(root)) { + } else if (!isSafeToCreateProjectIn(root)) { console.log('The directory `' + name + '` contains file(s) that could conflict. Aborting.'); process.exit(1); } @@ -167,11 +167,12 @@ function checkNodeVersion() { } } -// Check if GitHub boilerplate compatible -// https://github.com/facebookincubator/create-react-app/pull/368#issuecomment-237875655 -function isGitHubBoilerplate(root) { +// If project only contains files generated by GH, it’s safe. +// We also special case IJ-based products .idea because it integrates with CRA: +// https://github.com/facebookincubator/create-react-app/pull/368#issuecomment-243446094 +function isSafeToCreateProjectIn(root) { var validFiles = [ - '.DS_Store', 'Thumbs.db', '.git', '.gitignore', 'README.md', 'LICENSE' + '.DS_Store', 'Thumbs.db', '.git', '.gitignore', '.idea', 'README.md', 'LICENSE' ]; return fs.readdirSync(root) .every(function(file) { From 3901d7c041c9a4a9c142e5cdfcf4a91c07502ed8 Mon Sep 17 00:00:00 2001 From: Ville Immonen Date: Wed, 31 Aug 2016 16:58:46 +0300 Subject: [PATCH 038/248] Add a more prominent link to the guide (#524) * Add a more prominent link to the guide As a contributor, I know where to find the documentation/guide since know the codebase, but I've seen people miss the link to it in the README, because it's not very prominent. Let's try to make it more discoverable by including a link to it right on top of the page. * Make the wording of links more obvious * Rename the "How Do I...?" section to "User Guide" for consistency --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fcc1f93e18e..2fa9f43d158 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ Create React apps with no build configuration. +* [Getting Started](#getting-started) – How to create a new app. +* [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md) – How to develop apps bootstrapped with Create React App. + ## tl;dr ```sh @@ -81,7 +84,7 @@ 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! -## How Do I…? +## User Guide The generated project will include a guide in its README.
You can also read its latest version [here](https://github.com/facebookincubator/create-react-app/blob/master/template/README.md). From 4335f03d39c8e8facb7453d5b21ecc6bc7f7c3e3 Mon Sep 17 00:00:00 2001 From: Cory House Date: Wed, 31 Aug 2016 10:28:19 -0500 Subject: [PATCH 039/248] Typo fix (#526) --- config/eslint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/eslint.js b/config/eslint.js index eb2a87ce135..502cdfa4cf6 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -21,7 +21,7 @@ module.exports = { parser: 'babel-eslint', - // import plugin is termporarily disabled, scroll below to see why + // import plugin is temporarily disabled, scroll below to see why plugins: [/*'import', */'flowtype', 'jsx-a11y', 'react'], env: { From f994f3b7a750ec487bff264c7335b05d7c6ba322 Mon Sep 17 00:00:00 2001 From: Sophia Date: Wed, 31 Aug 2016 14:24:34 -0700 Subject: [PATCH 040/248] removing no-return-assign lint rule (#528) (#529) --- config/eslint.js | 1 - 1 file changed, 1 deletion(-) diff --git a/config/eslint.js b/config/eslint.js index 502cdfa4cf6..8eaeacbd73d 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -115,7 +115,6 @@ module.exports = { 'LabeledStatement', 'WithStatement', ], - 'no-return-assign': 'warn', 'no-script-url': 'warn', 'no-self-assign': 'warn', 'no-self-compare': 'warn', From 6be8ae0331a6b9d3e017692124ece594533cb2d0 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 1 Sep 2016 02:08:27 +0100 Subject: [PATCH 041/248] Update Jest (#530) * Update Jest * Remove default snapshot test * Fix a few things * Add a simple default test * App.spec.js -> App.test.js * Fix e2e test * Bump Jest --- config/jest/environment.js | 7 ------- package.json | 9 ++++----- scripts/eject.js | 11 +++++----- scripts/init.js | 11 +++++----- scripts/test.js | 7 ++++--- scripts/utils/createJestConfig.js | 17 +++------------- tasks/e2e.sh | 32 +++++++++++++++++------------- template/src/App.test.js | 10 ++++++++++ template/src/__tests__/App-test.js | 11 ---------- 9 files changed, 51 insertions(+), 64 deletions(-) delete mode 100644 config/jest/environment.js create mode 100644 template/src/App.test.js delete mode 100644 template/src/__tests__/App-test.js diff --git a/config/jest/environment.js b/config/jest/environment.js deleted file mode 100644 index e7c1df906c6..00000000000 --- a/config/jest/environment.js +++ /dev/null @@ -1,7 +0,0 @@ -// Currently, Jest mocks setTimeout() and similar functions by default: -// https://facebook.github.io/jest/docs/timer-mocks.html -// We think this is confusing, so we disable this feature. -// If you see value in it, run `jest.useFakeTimers()` in individual tests. -beforeEach(() => { - jest.useRealTimers(); -}); diff --git a/package.json b/package.json index 1694ded2b12..ee3f741fabc 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "create-react-app": "node global-cli/index.js --scripts-version \"$PWD/`npm pack`\"", "e2e": "tasks/e2e.sh", "start": "node scripts/start.js --debug-template", - "test": "node scripts/test.js --debug-template" + "test": "node scripts/test.js --debug-template --watch --env=jsdom" }, "files": [ "PATENTS", @@ -31,7 +31,7 @@ "autoprefixer": "6.4.0", "babel-core": "6.14.0", "babel-eslint": "6.1.2", - "babel-jest": "14.1.0", + "babel-jest": "15.0.0", "babel-loader": "6.2.5", "babel-plugin-transform-class-properties": "6.11.5", "babel-plugin-transform-object-rest-spread": "6.8.0", @@ -61,7 +61,7 @@ "html-loader": "0.4.3", "html-webpack-plugin": "2.22.0", "http-proxy-middleware": "0.17.0", - "jest": "14.1.0", + "jest": "15.0.1", "json-loader": "0.5.4", "object-assign": "4.1.0", "opn": "4.0.2", @@ -80,8 +80,7 @@ "devDependencies": { "bundle-deps": "1.0.0", "react": "^15.3.0", - "react-dom": "^15.3.0", - "react-test-renderer": "^15.3.0" + "react-dom": "^15.3.0" }, "optionalDependencies": { "fsevents": "1.0.14" diff --git a/scripts/eject.js b/scripts/eject.js index 55661d19285..74d1cf09f12 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -41,7 +41,6 @@ prompt( path.join('config', 'webpack.config.prod.js'), path.join('config', 'jest', 'CSSStub.js'), path.join('config', 'jest', 'FileStub.js'), - path.join('config', 'jest', 'environment.js'), path.join('config', 'jest', 'transform.js'), path.join('scripts', 'build.js'), path.join('scripts', 'start.js'), @@ -99,17 +98,19 @@ prompt( }); console.log('Updating scripts'); + delete appPackage.scripts['eject']; Object.keys(appPackage.scripts).forEach(function (key) { - appPackage.scripts[key] = 'node ./scripts/' + key + '.js' + appPackage.scripts[key] = appPackage.scripts[key] + .replace(/react-scripts test/g, 'jest') + .replace(/react-scripts (\w+)/g, 'node scripts/$1.js'); }); - delete appPackage.scripts['eject']; - appPackage.scripts.test = 'jest'; + // Add Jest config appPackage.jest = createJestConfig( filePath => path.join('', filePath) ); - // explicitly specify ESLint config path for editor plugins + // Explicitly specify ESLint config path for editor plugins appPackage.eslintConfig = { extends: './config/eslint.js', }; diff --git a/scripts/init.js b/scripts/init.js index 14ace414295..9402b930e6e 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -23,10 +23,12 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { appPackage.devDependencies = appPackage.devDependencies || {}; // Setup the script rules - appPackage.scripts = {}; - ['start', 'build', 'eject', 'test'].forEach(function(command) { - appPackage.scripts[command] = 'react-scripts ' + command; - }); + appPackage.scripts = { + 'start': 'react-scripts start', + 'build': 'react-scripts build', + 'test': 'react-scripts test --watch --env=jsdom', + 'eject': 'react-scripts eject' + }; // explicitly specify ESLint config path for editor plugins appPackage.eslintConfig = { @@ -69,7 +71,6 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { 'install', 'react', 'react-dom', - 'react-test-renderer', '--save', verbose && '--verbose' ].filter(function(e) { return e; }); diff --git a/scripts/test.js b/scripts/test.js index f11cda5a428..b173656b5db 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -16,9 +16,10 @@ const paths = require('../config/paths'); const argv = process.argv.slice(2); -const index = argv.indexOf('--debug-template'); -if (index !== -1) { - argv.splice(index, 1); +// Don't pass this option to Jest +const debugTemplateIndex = argv.indexOf('--debug-template'); +if (debugTemplateIndex !== -1) { + argv.splice(debugTemplateIndex, 1); } argv.push('--config', JSON.stringify(createJestConfig( diff --git a/scripts/utils/createJestConfig.js b/scripts/utils/createJestConfig.js index 8b6bfd52492..21b8ca54364 100644 --- a/scripts/utils/createJestConfig.js +++ b/scripts/utils/createJestConfig.js @@ -9,25 +9,14 @@ module.exports = (resolve, rootDir) => { const config = { - automock: false, moduleNameMapper: { '^[./a-zA-Z0-9$_-]+\\.(jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm)$': resolve('config/jest/FileStub.js'), '^[./a-zA-Z0-9$_-]+\\.css$': resolve('config/jest/CSSStub.js') }, - persistModuleRegistryBetweenSpecs: true, scriptPreprocessor: resolve('config/jest/transform.js'), - setupFiles: [ - resolve('config/polyfills.js') - ], - setupTestFrameworkScriptFile: resolve('config/jest/environment.js'), - testPathIgnorePatterns: ['/node_modules/', '/build/'], - // Allow three popular conventions: - // **/__tests__/*.js - // **/*.test.js - // **/*.spec.js - testRegex: '(__tests__/.*|\\.(test|spec))\\.js$', - testEnvironment: 'node', - verbose: true + setupFiles: [resolve('config/polyfills.js')], + testPathIgnorePatterns: ['/(build|docs|node_modules)/'], + testEnvironment: 'node' }; if (rootDir) { config.rootDir = rootDir; diff --git a/tasks/e2e.sh b/tasks/e2e.sh index 6e6c20c9420..1e841d8699a 100755 --- a/tasks/e2e.sh +++ b/tasks/e2e.sh @@ -12,7 +12,8 @@ cd "$(dirname "$0")" function cleanup { echo 'Cleaning up.' cd $initial_path - rm ../template/src/__tests__/__snapshots__/App-test.js.snap + # Uncomment when snapshot testing is enabled by default: + # rm ../template/src/__snapshots__/App.test.js.snap rm -rf $temp_cli_path $temp_app_path } @@ -53,12 +54,9 @@ perl -i -p0e 's/bundledDependencies.*?]/bundledDependencies": []/s' package.json npm install scripts_path=$PWD/`npm pack` -# lint +# Lint ./node_modules/.bin/eslint --ignore-path .gitignore ./ -# Test local start command -npm start -- --smoke-test - # Test local build command npm run build @@ -69,9 +67,13 @@ test -e build/static/css/*.css test -e build/static/media/*.svg test -e build/favicon.ico -# Run tests -npm run test -test -e template/src/__tests__/__snapshots__/App-test.js.snap +# Run tests, overriding watch option to disable it +npm test -- --watch=no +# Uncomment when snapshot testing is enabled by default: +# test -e template/src/__snapshots__/App.test.js.snap + +# Test local start command +npm start -- --smoke-test # Pack CLI cd global-cli @@ -99,9 +101,10 @@ test -e build/static/css/*.css test -e build/static/media/*.svg test -e build/favicon.ico -# Run tests -npm run test -test -e src/__tests__/__snapshots__/App-test.js.snap +# Run tests, overriding watch option to disable it +npm test -- --watch=no +# Uncomment when snapshot testing is enabled by default: +# test -e src/__snapshots__/App.test.js.snap # Test the server npm start -- --smoke-test @@ -117,9 +120,10 @@ test -e build/static/css/*.css test -e build/static/media/*.svg test -e build/favicon.ico -# Run tests -npm run test -test -e src/__tests__/__snapshots__/App-test.js.snap +# Run tests, overriding watch option to disable it +npm test -- --watch=no +# Uncomment when snapshot testing is enabled by default: +# test -e src/__snapshots__/App.test.js.snap # Test the server npm start -- --smoke-test diff --git a/template/src/App.test.js b/template/src/App.test.js new file mode 100644 index 00000000000..55dbf38ce2c --- /dev/null +++ b/template/src/App.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +describe('App', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); +}); diff --git a/template/src/__tests__/App-test.js b/template/src/__tests__/App-test.js deleted file mode 100644 index 7d36ff192a2..00000000000 --- a/template/src/__tests__/App-test.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import App from '../App'; -import renderer from 'react-test-renderer'; - -describe('App', () => { - it('renders a welcome view', () => { - const instance = renderer.create(); - const tree = instance.toJSON(); - expect(tree).toMatchSnapshot(); - }); -}); From 50f4a03a23329368803579b618ce4ebf5c1d03e9 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 1 Sep 2016 02:09:00 +0100 Subject: [PATCH 042/248] 0.3.0-beta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ee3f741fabc..08901febcb7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-scripts", - "version": "0.3.0-alpha", + "version": "0.3.0-beta", "description": "Configuration and scripts for Create React App.", "repository": "facebookincubator/create-react-app", "license": "BSD-3-Clause", From f148a34bbfafdb01e8bfd186809da55751cb15de Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 1 Sep 2016 17:25:21 +0100 Subject: [PATCH 043/248] Enable watch implicitly unless on CI (#533) Fixes #532 --- package.json | 2 +- scripts/eject.js | 2 +- scripts/init.js | 2 +- scripts/test.js | 5 +++++ tasks/e2e.sh | 11 ++++++----- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 08901febcb7..1899f89b5cb 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "create-react-app": "node global-cli/index.js --scripts-version \"$PWD/`npm pack`\"", "e2e": "tasks/e2e.sh", "start": "node scripts/start.js --debug-template", - "test": "node scripts/test.js --debug-template --watch --env=jsdom" + "test": "node scripts/test.js --debug-template --env=jsdom" }, "files": [ "PATENTS", diff --git a/scripts/eject.js b/scripts/eject.js index 74d1cf09f12..7fef22687b3 100644 --- a/scripts/eject.js +++ b/scripts/eject.js @@ -101,7 +101,7 @@ prompt( delete appPackage.scripts['eject']; Object.keys(appPackage.scripts).forEach(function (key) { appPackage.scripts[key] = appPackage.scripts[key] - .replace(/react-scripts test/g, 'jest') + .replace(/react-scripts test/g, 'jest --watch') .replace(/react-scripts (\w+)/g, 'node scripts/$1.js'); }); diff --git a/scripts/init.js b/scripts/init.js index 9402b930e6e..5beed2e1b47 100644 --- a/scripts/init.js +++ b/scripts/init.js @@ -26,7 +26,7 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { appPackage.scripts = { 'start': 'react-scripts start', 'build': 'react-scripts build', - 'test': 'react-scripts test --watch --env=jsdom', + 'test': 'react-scripts test --env=jsdom', 'eject': 'react-scripts eject' }; diff --git a/scripts/test.js b/scripts/test.js index b173656b5db..b8d047333ad 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -22,6 +22,11 @@ if (debugTemplateIndex !== -1) { argv.splice(debugTemplateIndex, 1); } +// Watch unless on CI +if (!process.env.CI) { + argv.push('--watch'); +} + argv.push('--config', JSON.stringify(createJestConfig( relativePath => path.resolve(__dirname, '..', relativePath), path.resolve(paths.appSrc, '..') diff --git a/tasks/e2e.sh b/tasks/e2e.sh index 1e841d8699a..4fedfe63bac 100755 --- a/tasks/e2e.sh +++ b/tasks/e2e.sh @@ -67,8 +67,8 @@ test -e build/static/css/*.css test -e build/static/media/*.svg test -e build/favicon.ico -# Run tests, overriding watch option to disable it -npm test -- --watch=no +# Run tests with CI flag +CI=true npm test # Uncomment when snapshot testing is enabled by default: # test -e template/src/__snapshots__/App.test.js.snap @@ -101,8 +101,8 @@ test -e build/static/css/*.css test -e build/static/media/*.svg test -e build/favicon.ico -# Run tests, overriding watch option to disable it -npm test -- --watch=no +# Run tests with CI flag +CI=true npm test # Uncomment when snapshot testing is enabled by default: # test -e src/__snapshots__/App.test.js.snap @@ -120,7 +120,8 @@ test -e build/static/css/*.css test -e build/static/media/*.svg test -e build/favicon.ico -# Run tests, overriding watch option to disable it +# Run tests, overring the watch option to disable it +# TODO: make CI flag respected after ejecting as well npm test -- --watch=no # Uncomment when snapshot testing is enabled by default: # test -e src/__snapshots__/App.test.js.snap From 63197c4769437fd8dad6c09fe4690b18443501f4 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 1 Sep 2016 17:51:28 +0100 Subject: [PATCH 044/248] Disable react-constant-elements because of bugs (#534) Disabled because of issues: * https://github.com/facebookincubator/create-react-app/issues/525 * https://phabricator.babeljs.io/search/query/pCNlnC2xzwzx/ TODO: Enable again when these issues are resolved. --- config/babel.prod.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/config/babel.prod.js b/config/babel.prod.js index 32f4bd66583..107872181f5 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -33,6 +33,10 @@ module.exports = { regenerator: true }], // Optimization: hoist JSX that never changes out of render() - require.resolve('babel-plugin-transform-react-constant-elements') + // Disabled because of issues: + // * https://github.com/facebookincubator/create-react-app/issues/525 + // * https://phabricator.babeljs.io/search/query/pCNlnC2xzwzx/ + // TODO: Enable again when these issues are resolved. + // require.resolve('babel-plugin-transform-react-constant-elements') ] }; From c2a56cbc438d4748c2769db16ea366637e688e77 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 1 Sep 2016 18:01:11 +0100 Subject: [PATCH 045/248] Resolve babel-runtime relative to the config (#535) This makes generators work with Jest. Fixes #255. Replaces #262. --- config/babel.dev.js | 7 ++++++- config/babel.prod.js | 7 ++++++- config/webpack.config.dev.js | 11 ++--------- config/webpack.config.prod.js | 11 ++--------- package.json | 2 +- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/config/babel.dev.js b/config/babel.dev.js index 56533109097..ebaab1156b3 100644 --- a/config/babel.dev.js +++ b/config/babel.dev.js @@ -7,6 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +var path = require('path'); + module.exports = { // Don't try to find .babelrc because we want to force this configuration. babelrc: false, @@ -33,7 +35,10 @@ module.exports = { [require.resolve('babel-plugin-transform-runtime'), { helpers: false, polyfill: false, - regenerator: true + regenerator: true, + // Resolve the Babel runtime relative to the config. + // You can safely remove this after ejecting: + moduleName: path.dirname(require.resolve('babel-runtime/package')) }] ] }; diff --git a/config/babel.prod.js b/config/babel.prod.js index 107872181f5..d1f105f575a 100644 --- a/config/babel.prod.js +++ b/config/babel.prod.js @@ -7,6 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +var path = require('path'); + module.exports = { // Don't try to find .babelrc because we want to force this configuration. babelrc: false, @@ -30,7 +32,10 @@ module.exports = { [require.resolve('babel-plugin-transform-runtime'), { helpers: false, polyfill: false, - regenerator: true + regenerator: true, + // Resolve the Babel runtime relative to the config. + // You can safely remove this after ejecting: + moduleName: path.dirname(require.resolve('babel-runtime/package')) }], // Optimization: hoist JSX that never changes out of render() // Disabled because of issues: diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 2a66d3dd816..c72435ac813 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -68,15 +68,8 @@ module.exports = { // These are the reasonable defaults supported by the Node ecosystem. extensions: ['.js', '.json', ''], alias: { - // This `alias` section can be safely removed after ejection. - // We do this because `babel-runtime` may be inside `react-scripts`, - // so when `babel-plugin-transform-runtime` imports it, it will not be - // available to the app directly. This is a temporary solution that lets - // us ship support for generators. However it is far from ideal, and - // if we don't have a good solution, we should just make `babel-runtime` - // a dependency in generated projects. - // See https://github.com/facebookincubator/create-react-app/issues/255 - 'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator'), + // Support React Native Web + // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ 'react-native': 'react-native-web' } }, diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 48a37d04e61..e64758b8f51 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -63,15 +63,8 @@ module.exports = { // These are the reasonable defaults supported by the Node ecosystem. extensions: ['.js', '.json', ''], alias: { - // This `alias` section can be safely removed after ejection. - // We do this because `babel-runtime` may be inside `react-scripts`, - // so when `babel-plugin-transform-runtime` imports it, it will not be - // available to the app directly. This is a temporary solution that lets - // us ship support for generators. However it is far from ideal, and - // if we don't have a good solution, we should just make `babel-runtime` - // a dependency in generated projects. - // See https://github.com/facebookincubator/create-react-app/issues/255 - 'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator'), + // Support React Native Web + // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ 'react-native': 'react-native-web' } }, diff --git a/package.json b/package.json index 1899f89b5cb..5dbf4b918d0 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "babel-plugin-transform-object-rest-spread": "6.8.0", "babel-plugin-transform-react-constant-elements": "6.9.1", "babel-plugin-transform-regenerator": "6.14.0", - "babel-plugin-transform-runtime": "6.12.0", + "babel-plugin-transform-runtime": "6.15.0", "babel-preset-latest": "6.14.0", "babel-preset-react": "6.11.1", "babel-runtime": "6.11.6", From 452dd28da6cbc9f307d298aa9c13c17a43737239 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 1 Sep 2016 18:26:07 +0100 Subject: [PATCH 046/248] Remove unnecessary describe() --- template/src/App.test.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/template/src/App.test.js b/template/src/App.test.js index 55dbf38ce2c..b84af98d720 100644 --- a/template/src/App.test.js +++ b/template/src/App.test.js @@ -2,9 +2,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; -describe('App', () => { - it('renders without crashing', () => { - const div = document.createElement('div'); - ReactDOM.render(, div); - }); +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); }); From 365d99056e486e3b1ae206d4dac0676009676538 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 1 Sep 2016 20:40:15 +0100 Subject: [PATCH 047/248] Update deps --- config/eslint.js | 1 + package.json | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/config/eslint.js b/config/eslint.js index 8eaeacbd73d..e42a2a5e2b4 100644 --- a/config/eslint.js +++ b/config/eslint.js @@ -121,6 +121,7 @@ module.exports = { 'no-sequences': 'warn', 'no-shadow-restricted-names': 'warn', 'no-sparse-arrays': 'warn', + 'no-template-curly-in-string': 'warn', 'no-this-before-super': 'warn', 'no-throw-literal': 'warn', 'no-undef': 'warn', diff --git a/package.json b/package.json index 5dbf4b918d0..3a09697203a 100644 --- a/package.json +++ b/package.json @@ -45,13 +45,13 @@ "chalk": "1.1.3", "connect-history-api-fallback": "1.3.0", "cross-spawn": "4.0.0", - "css-loader": "0.23.1", + "css-loader": "0.24.0", "detect-port": "1.0.0", - "eslint": "3.2.2", - "eslint-loader": "1.4.1", - "eslint-plugin-flowtype": "2.4.0", + "eslint": "3.4.0", + "eslint-loader": "1.5.0", + "eslint-plugin-flowtype": "2.11.4", "eslint-plugin-import": "1.12.0", - "eslint-plugin-jsx-a11y": "2.0.1", + "eslint-plugin-jsx-a11y": "2.2.1", "eslint-plugin-react": "5.2.2", "extract-text-webpack-plugin": "1.0.1", "file-loader": "0.9.0", @@ -60,21 +60,21 @@ "gzip-size": "3.0.0", "html-loader": "0.4.3", "html-webpack-plugin": "2.22.0", - "http-proxy-middleware": "0.17.0", - "jest": "15.0.1", + "http-proxy-middleware": "0.17.1", + "jest": "15.1.0", "json-loader": "0.5.4", "object-assign": "4.1.0", "opn": "4.0.2", "path-exists": "3.0.0", - "postcss-loader": "0.9.1", + "postcss-loader": "0.11.1", "promise": "7.1.1", "recursive-readdir": "2.0.0", "rimraf": "2.5.4", "strip-ansi": "3.0.1", "style-loader": "0.13.1", "url-loader": "0.5.7", - "webpack": "1.13.1", - "webpack-dev-server": "1.14.1", + "webpack": "1.13.2", + "webpack-dev-server": "1.15.1", "whatwg-fetch": "1.0.0" }, "devDependencies": { From 7c2d2143415af23365fec453b2127248f816ee74 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 2 Sep 2016 00:37:37 +0100 Subject: [PATCH 048/248] Document testing (#538) * Document testing * Update README.md * Update README.md * Clarify our recommendations on testing * Okay, that was too much. :-) * Add a few more things --- README.md | 14 ++- template/README.md | 216 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 225 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2fa9f43d158..0541db4b8d5 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ my-app/ src/ App.css App.js + App.test.js index.css index.js logo.svg @@ -76,6 +77,13 @@ You will see the build errors and lint warnings in the console. Build errors +### `npm test` + +Runs the test watcher in an interactive mode. +By default, runs tests related to files changes since the last commit. + +[Read more about testing.](template/README.md#running-tests) + ### `npm run build` Builds the app for production to the `build` folder.
@@ -108,7 +116,7 @@ You can also read its latest version [here](https://github.com/facebookincubator * Autoprefixed CSS, so you don’t need `-webkit` or other prefixes. * A `build` script to bundle JS, CSS, and images for production, with sourcemaps. -**The feature set is intentionally limited**. It doesn’t support advanced features such as server rendering or CSS modules. Currently, it doesn’t support testing either. The tool is also **non-configurable** because it is hard to provide a cohesive experience and easy updates across a set of tools when the user can tweak anything. +**The feature set is intentionally limited**. It doesn’t support advanced features such as server rendering or CSS modules. The tool is also **non-configurable** because it is hard to provide a cohesive experience and easy updates across a set of tools when the user can tweak anything. **You don’t have to use this.** Historically it has been easy to [gradually adopt](https://www.youtube.com/watch?v=BF58ZJ1ZQxY) React. However many people create new single-page React apps from scratch every day. We’ve heard [loud](https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4) and [clear](https://twitter.com/thomasfuchs/status/708675139253174273) that this process can be error-prone and tedious, especially if this is your first JavaScript build stack. This project is an attempt to figure out a good way to start developing React apps. @@ -127,7 +135,6 @@ You don’t have to ever use `eject`. The curated feature set is suitable for sm Some features are currently **not supported**: * Server rendering. -* Testing. * Some experimental syntax extensions (e.g. decorators). * CSS Modules. * LESS or Sass. @@ -144,7 +151,8 @@ Currently it is a thin layer on top of many amazing community projects, such as: * [Babel](http://babeljs.io/) with ES6 and extensions used by Facebook (JSX, [object spread](https://github.com/sebmarkbage/ecmascript-rest-spread/commits/master), [class properties](https://github.com/jeffmo/es-class-public-fields)) * [Autoprefixer](https://github.com/postcss/autoprefixer) * [ESLint](http://eslint.org/) -* and more. +* [Jest](http://facebook.github.io/jest) +* and others. All of them are transitive dependencies of the provided npm package. diff --git a/template/README.md b/template/README.md index 31c2802d041..d4134eb23b8 100644 --- a/template/README.md +++ b/template/README.md @@ -10,6 +10,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [Folder Structure](#folder-structure) - [Available Scripts](#available-scripts) - [npm start](#npm-start) + - [npm test](#npm-test) - [npm run build](#npm-run-build) - [npm run eject](#npm-run-eject) - [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor) @@ -24,6 +25,17 @@ You can find the most recent version of this guide [here](https://github.com/fac - [Integrating with a Node Backend](#integrating-with-a-node-backend) - [Proxying API Requests in Development](#proxying-api-requests-in-development) - [Adding `` Tags](#adding-meta-tags) +- [Running Tests](#running-tests) + - [Filename Conventions](#filename-conventions) + - [Command Line Interface](#command-line-interface) + - [Version Control Integration](#version-control-integration) + - [Writing Tests](#writing-tests) + - [Testing Components](#testing-components) + - [Using Third Party Assertion Libraries](#using-third-party-assertion-libraries) + - [Coverage Reporting](#coverage-reporting) + - [Continuous Integration](#continuous-integration) + - [Disabling jsdom](#disabling-jsdom) + - [Experimental Snapshot Testing](#experimental-snapshot-testing) - [Deployment](#deployment) - [Now](#now) - [Heroku](#heroku) @@ -97,6 +109,11 @@ Open [http://localhost:3000](http://localhost:3000) to view it in the browser. The page will reload if you make edits.
You will also see any lint errors in the console. +### `npm test` + +Launches the test runner in the interactive watch mode. +See the section about [running tests](#running-tests) for more information. + ### `npm run build` Builds the app for production to the `build` folder.
@@ -425,7 +442,7 @@ render() { The above form is looking for a variable called `REACT_APP_SECRET_CODE` from the environment. In order to consume this value, we need to have it defined in the environment: -### Windows (cmd.exe) +#### Windows (cmd.exe) ```cmd set REACT_APP_SECRET_CODE=abcdef&&npm start @@ -433,7 +450,7 @@ set REACT_APP_SECRET_CODE=abcdef&&npm start (Note: the lack of whitespace is intentional.) -### Linux, OS X (Bash) +#### Linux, OS X (Bash) ```bash REACT_APP_SECRET_CODE=abcdef npm start @@ -522,6 +539,201 @@ Then, on the server, regardless of the backend you use, you can read `index.html If you use a Node server, you can even share the route matching logic between the client and the server. However duplicating it also works fine in simple cases. +## Running Tests + +>Note: this feature is available with `react-scripts@0.3.0` and higher. +>[Read the migration guide to learn how to enable it in older projects!](https://github.com/facebookincubator/create-react-app/blob/master/CHANGELOG.md#migrating-from-023-to-030) + +Create React App uses [Jest](https://facebook.github.io/jest/) as its test runner. To prepare for this integration, we did a [major revamp](https://facebook.github.io/jest/blog/2016/09/01/jest-15.html) of Jest so if you heard bad things about it, give it another try. + +Jest is a Node-based runner. This means that the tests always run in a Node environment and not in a real browser. This lets us enable fast iteration speed and prevent flakiness. + +While Jest provides browser globals such as `window` thanks to [jsdom](https://github.com/tmpvar/jsdom), they are only approximations of the real browser behavior. Jest is intended to be used for unit tests of your logic and your components rather than the DOM quirks. + +We recommend that you use a separate tool for browser end-to-end tests if you need them. They are beyond the scope of Create React App. + +### Filename Conventions + +Jest will look for test files with any of the following popular naming conventions: + +* Files with `.js` suffix in `__tests__` folders. +* Files with `.test.js` suffix. +* Files with `.spec.js` suffix. + +The `.test.js` / `.spec.js` files (or the `__tests__` folders) can be located at any depth under the `src` top level folder. + +We recommend to put the test files (or `__tests__` folders) next to the code they are testing so that relative imports appear shorter. For example, if `App.test.js` and `App.js` are in the same folder, the test just needs to `import App from './App'` instead of a long relative path. + +### Command Line Interface + +When you run `npm test`, Jest will launch in the watch mode. Every time you save a file, it will re-run the tests, just like `npm start` recompiles the code. + +The watcher includes an interactive command-line interface with the ability to run all tests, or focus on a search pattern. It is designed this way so that you could keep it open and enjoy fast re-runs. You can learn the commands from the “Watch Usage” note that the watcher prints after every run: + +![Jest watch mode](http://facebook.github.io/jest/img/blog/15-watch.gif) + +### Version Control Integration + +By default, when you run `npm test`, Jest will only run the tests related to files changed since last commit. This is an optimization designed to make your tests runs fast regardless of how many tests you have. However it assumes that you don’t often commit the code that doesn’t pass the tests. + +Jest will always explicitly mention that it only ran tests related to the files changed since the last commit. You can also press `a` in the watch mode to force Jest to run all tests. + +Jest will always run all tests on a [continuous integration](#continuous-integration) server or if the project is not inside a Git or Mercurial repository. + +### Writing Tests + +To create tests, add `it()` blocks with the name of the test and its code. You may optionally wrap them in `describe()` blocks for logical grouping but this is neither required nor recommended. + +Jest provides a built-in `expect()` global function for making assertions. A basic test could look like this: + +```js +import sum from './sum'; + +it('sums numbers', () => { + expect(sum(1, 2)).toEqual(3); + expect(sum(2, 2)).toEqual(4); +}); +``` + +All `expect()` matchers supported by Jest are [extensively documented here](http://facebook.github.io/jest/docs/api.html#expect-value). +You can also use [`jest.fn()` and `expect(fn).toBeCalled()`](http://facebook.github.io/jest/docs/api.html#tobecalled) to create “spies” or mock functions. + +### Testing Components + +There is a broad spectrum of component testing techniques. They range from a “smoke test” verifying that a component renders without throwing, to shallow rendering and testing some of the output, to full rendering and testing component lifecycle and state changes. + +Different projects choose different testing tradeoffs based on how often components change, and how much logic they contain. If you haven’t decided on a testing strategy yet, we recommend that you start with creating simple smoke tests for your components: + +```js +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); +}); +``` + +This test mounts a component and makes sure that it didn’t throw during rendering. Tests like this provide a lot value with very little effort so they are great as a starting point, and this is the test you will find in `src/App.test.js`. + +When you encounter bugs caused by changing components, you will gain a deeper insight into which parts of them are worth testing in your application. This might be a good time to introduce more specific tests asserting specific expected output or behavior. + +If you’d like to test components in isolation from the child components they render, we recommend using [`shallow()` rendering API](http://airbnb.io/enzyme/docs/api/shallow.html) from [Enzyme](http://airbnb.io/enzyme/). You can write a smoke test with it too: + +```sh +npm install --save-dev enzyme react-addons-test-utils +``` + +```js +import React from 'react'; +import { shallow } from 'enzyme'; +import App from './App'; + +it('renders without crashing', () => { + shallow(); +}); +``` + +Unlike the previous smoke test using `ReactDOM.render()`, this test only renders `` and doesn’t go deeper. For example, even if `` itself renders a `