From 12288836e16c45541f03cd1af44c53f92c2c6cce Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Sat, 11 Feb 2017 14:11:00 -0500 Subject: [PATCH 001/163] Upgrade webpack (#1291) * Upgrade webpack * Address more webpack v2 ... * Update html-webpack-plugin * Remove LoaderOptionsPlugin from dev config * ExtractTextPlugin still uses webpack 1 syntax ... and doesn't support complex options (yet) * Grammar nit * Update extract text webpack plugin * - Remove webpack.LoaderOptionsPlugin - Update deps * Lerna hoists packages * Update extract-text-webpack-plugin * Update webpack-dev-server * Remove imports for the tests * stop removing babelrc --- packages/babel-preset-react-app/index.js | 6 +- .../config/webpack.config.dev.js | 109 ++++++++------- .../config/webpack.config.prod.js | 127 +++++++++--------- .../fixtures/kitchensink/.babelrc | 3 +- .../kitchensink/.template.dependencies.json | 1 + packages/react-scripts/package.json | 11 +- packages/react-scripts/scripts/start.js | 3 +- tasks/e2e-kitchensink.sh | 3 - 8 files changed, 144 insertions(+), 119 deletions(-) diff --git a/packages/babel-preset-react-app/index.js b/packages/babel-preset-react-app/index.js index a028babc06c..8a42f885e31 100644 --- a/packages/babel-preset-react-app/index.js +++ b/packages/babel-preset-react-app/index.js @@ -88,7 +88,11 @@ if (env === 'test') { module.exports = { presets: [ // Latest stable ECMAScript features - require.resolve('babel-preset-latest'), + [require.resolve('babel-preset-latest'), { + 'es2015': { + modules: false + } + }], // JSX, Flow require.resolve('babel-preset-react') ], diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 0109eb6e4ac..e26a5a25d81 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -78,15 +78,15 @@ module.exports = { resolve: { // This allows you to set a fallback for where Webpack should look for modules. // We read `NODE_PATH` environment variable in `paths.js` and pass paths here. - // We use `fallback` instead of `root` because we want `node_modules` to "win" - // if there any conflicts. This matches Node resolution mechanism. + // We placed these paths second because we want `node_modules` to "win" + // if there are any conflicts. This matches Node resolution mechanism. // https://github.com/facebookincubator/create-react-app/issues/253 - fallback: paths.nodePaths, + modules: ['node_modules'].concat(paths.nodePaths), // These are the reasonable defaults supported by the Node ecosystem. // We also include JSX as a common component filename extension to support // some tools, although we do not recommend using it, see: // https://github.com/facebookincubator/create-react-app/issues/290 - extensions: ['.js', '.json', '.jsx', ''], + extensions: ['.js', '.json', '.jsx'], alias: { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ @@ -97,21 +97,32 @@ module.exports = { // Resolve loaders (webpack plugins for CSS, images, transpilation) from the // directory of `react-scripts` itself rather than the project directory. resolveLoader: { - root: paths.ownNodeModules, - moduleTemplates: ['*-loader'] + modules: [ + paths.ownNodeModules, + // Lerna hoists everything, so we need to look in our app directory + paths.appNodeModules + ] }, // @remove-on-eject-end module: { - // First, run the linter. - // It's important to do this before Babel processes the JS. - preLoaders: [ + rules: [ + // First, run the linter. + // It's important to do this before Babel processes the JS. { test: /\.(js|jsx)$/, - loader: 'eslint', - include: paths.appSrc, - } - ], - loaders: [ + enforce: 'pre', + use: [{ + // @remove-on-eject-begin + // Point ESLint to our predefined config. + options: { + configFile: path.join(__dirname, '../.eslintrc'), + useEslintrc: false + }, + // @remove-on-eject-end + loader: 'eslint-loader' + }], + include: paths.appSrc + }, // ** ADDING/UPDATING LOADERS ** // The "url" loader handles all assets unless explicitly excluded. // The `exclude` list *must* be updated with every change to loader extensions. @@ -128,8 +139,8 @@ module.exports = { /\.json$/, /\.svg$/ ], - loader: 'url', - query: { + loader: 'url-loader', + options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' } @@ -138,8 +149,8 @@ module.exports = { { test: /\.(js|jsx)$/, include: paths.appSrc, - loader: 'babel', - query: { + loader: 'babel-loader', + options: { // @remove-on-eject-begin babelrc: false, presets: [require.resolve('babel-preset-react-app')], @@ -157,19 +168,37 @@ module.exports = { // in development "style" loader enables hot editing of CSS. { test: /\.css$/, - loader: 'style!css?importLoaders=1!postcss' - }, - // JSON is not enabled by default in Webpack but both Node and Browserify - // allow it implicitly so we also enable it. - { - test: /\.json$/, - loader: 'json' + use: [ + 'style-loader', { + loader: 'css-loader', + options: { + importLoaders: 1 + } + }, { + loader: 'postcss-loader', + options: { + ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options + plugins: function () { + return [ + autoprefixer({ + browsers: [ + '>1%', + 'last 4 versions', + 'Firefox ESR', + 'not ie < 9', // React doesn't support IE8 anyway + ] + }) + ] + } + } + } + ] }, // "file" loader for svg { test: /\.svg$/, - loader: 'file', - query: { + loader: 'file-loader', + options: { name: 'static/media/[name].[hash:8].[ext]' } } @@ -177,26 +206,6 @@ module.exports = { // Remember to add the new extension(s) to the "url" loader exclusion list. ] }, - // @remove-on-eject-begin - // Point ESLint to our predefined config. - eslint: { - configFile: path.join(__dirname, '../.eslintrc'), - useEslintrc: false - }, - // @remove-on-eject-end - // We use PostCSS for autoprefixing only. - postcss: function() { - return [ - autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ] - }), - ]; - }, plugins: [ // Makes some environment variables available in index.html. // The public URL is available as %PUBLIC_URL% in index.html, e.g.: @@ -229,5 +238,11 @@ module.exports = { fs: 'empty', net: 'empty', tls: 'empty' + }, + // Turn off performance hints during development because we don't do any + // splitting or minification in interest of speed. These warnings become + // cumbersome. + performance: { + hints: false } }; diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 4e75be521bb..86d87d39211 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -52,8 +52,8 @@ const cssFilename = 'static/css/[name].[contenthash:8].css'; // To have this structure working with relative paths, we have to use custom options. const extractTextPluginOptions = shouldUseRelativeAssetPaths // Making sure that the publicPath goes back to to build folder. - ? { publicPath: Array(cssFilename.split('/').length).join('../') } - : undefined; + ? {publicPath: Array(cssFilename.split('/').length).join('../')} + : {}; // This is the production configuration. // It compiles slowly and is focused on producing a fast and minimal bundle. @@ -83,15 +83,15 @@ module.exports = { resolve: { // This allows you to set a fallback for where Webpack should look for modules. // We read `NODE_PATH` environment variable in `paths.js` and pass paths here. - // We use `fallback` instead of `root` because we want `node_modules` to "win" - // if there any conflicts. This matches Node resolution mechanism. + // We placed these paths second because we want `node_modules` to "win" + // if there are any conflicts. This matches Node resolution mechanism. // https://github.com/facebookincubator/create-react-app/issues/253 - fallback: paths.nodePaths, + modules: ['node_modules'].concat(paths.nodePaths), // These are the reasonable defaults supported by the Node ecosystem. // We also include JSX as a common component filename extension to support // some tools, although we do not recommend using it, see: // https://github.com/facebookincubator/create-react-app/issues/290 - extensions: ['.js', '.json', '.jsx', ''], + extensions: ['.js', '.json', '.jsx'], alias: { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ @@ -102,21 +102,34 @@ module.exports = { // Resolve loaders (webpack plugins for CSS, images, transpilation) from the // directory of `react-scripts` itself rather than the project directory. resolveLoader: { - root: paths.ownNodeModules, - moduleTemplates: ['*-loader'] + modules: [ + paths.ownNodeModules, + // Lerna hoists everything, so we need to look in our app directory + paths.appNodeModules + ] }, // @remove-on-eject-end module: { - // First, run the linter. - // It's important to do this before Babel processes the JS. - preLoaders: [ + rules: [ + // First, run the linter. + // It's important to do this before Babel processes the JS. { test: /\.(js|jsx)$/, - loader: 'eslint', + enforce: 'pre', + use: [{ + // @remove-on-eject-begin + // Point ESLint to our predefined config. + options: { + // TODO: consider separate config for production, + // e.g. to enable no-console and no-debugger only in production. + configFile: path.join(__dirname, '../.eslintrc'), + useEslintrc: false + }, + // @remove-on-eject-end + loader: 'eslint-loader' + }], include: paths.appSrc - } - ], - loaders: [ + }, // ** ADDING/UPDATING LOADERS ** // The "url" loader handles all assets unless explicitly excluded. // The `exclude` list *must* be updated with every change to loader extensions. @@ -133,8 +146,8 @@ module.exports = { /\.json$/, /\.svg$/ ], - loader: 'url', - query: { + loader: 'url-loader', + options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' } @@ -143,9 +156,9 @@ module.exports = { { test: /\.(js|jsx)$/, include: paths.appSrc, - loader: 'babel', + loader: 'babel-loader', // @remove-on-eject-begin - query: { + options: { babelrc: false, presets: [require.resolve('babel-preset-react-app')], }, @@ -165,24 +178,41 @@ module.exports = { // in the main CSS file. { test: /\.css$/, - loader: ExtractTextPlugin.extract( - 'style', - 'css?importLoaders=1!postcss', - extractTextPluginOptions - ) + loader: ExtractTextPlugin.extract(Object.assign({ + fallback: 'style-loader', + use: [ + { + loader: 'css-loader', + options: { + importLoaders: 1 + } + }, { + loader: 'postcss-loader', + options: { + ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options + plugins: function () { + return [ + autoprefixer({ + browsers: [ + '>1%', + 'last 4 versions', + 'Firefox ESR', + 'not ie < 9', // React doesn't support IE8 anyway + ] + }) + ] + } + } + } + ] + }, extractTextPluginOptions)) // 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. - { - test: /\.json$/, - loader: 'json' - }, // "file" loader for svg { test: /\.svg$/, - loader: 'file', - query: { + loader: 'file-loader', + options: { name: 'static/media/[name].[hash:8].[ext]' } } @@ -190,28 +220,6 @@ module.exports = { // Remember to add the new extension(s) to the "url" loader exclusion list. ] }, - // @remove-on-eject-begin - // Point ESLint to our predefined config. - eslint: { - // TODO: consider separate config for production, - // e.g. to enable no-console and no-debugger only in production. - configFile: path.join(__dirname, '../.eslintrc'), - useEslintrc: false - }, - // @remove-on-eject-end - // We use PostCSS for autoprefixing only. - postcss: function() { - return [ - autoprefixer({ - browsers: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie < 9', // React doesn't support IE8 anyway - ] - }), - ]; - }, plugins: [ // Makes some environment variables available in index.html. // The public URL is available as %PUBLIC_URL% in index.html, e.g.: @@ -241,10 +249,6 @@ module.exports = { // It is absolutely essential that NODE_ENV was set to production here. // Otherwise React will be compiled in the very slow development mode. new webpack.DefinePlugin(env.stringified), - // This helps ensure the builds are consistent if source hasn't changed: - new webpack.optimize.OccurrenceOrderPlugin(), - // Try to dedupe duplicated modules, if any: - new webpack.optimize.DedupePlugin(), // Minify the code. new webpack.optimize.UglifyJsPlugin({ compress: { @@ -257,10 +261,13 @@ module.exports = { output: { comments: false, screw_ie8: true - } + }, + sourceMap: true }), // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`. - new ExtractTextPlugin(cssFilename), + new ExtractTextPlugin({ + filename: cssFilename + }), // Generate a manifest file which contains a mapping of all asset filenames // to their corresponding output file so that tools can pick it up without // having to parse `index.html`. diff --git a/packages/react-scripts/fixtures/kitchensink/.babelrc b/packages/react-scripts/fixtures/kitchensink/.babelrc index c14b2828d16..14397221e3b 100644 --- a/packages/react-scripts/fixtures/kitchensink/.babelrc +++ b/packages/react-scripts/fixtures/kitchensink/.babelrc @@ -1,3 +1,4 @@ { - "presets": ["react-app"] + "presets": ["react-app"], + "plugins": ["babel-plugin-transform-es2015-modules-commonjs"] } diff --git a/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json b/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json index 50511b3d16a..a20139318c1 100644 --- a/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json +++ b/packages/react-scripts/fixtures/kitchensink/.template.dependencies.json @@ -1,6 +1,7 @@ { "dependencies": { "babel-register": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.22.0", "babel-polyfill": "6.20.0", "chai": "3.5.0", "jsdom": "9.8.3", diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index b774b88d941..371b952c8c5 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -39,20 +39,19 @@ "dotenv": "2.0.0", "eslint": "3.8.1", "eslint-config-react-app": "^0.5.1", - "eslint-loader": "1.6.0", + "eslint-loader": "1.6.1", "eslint-plugin-flowtype": "2.21.0", "eslint-plugin-import": "2.0.1", "eslint-plugin-jsx-a11y": "2.2.3", "eslint-plugin-react": "6.4.1", - "extract-text-webpack-plugin": "1.0.1", + "extract-text-webpack-plugin": "2.0.0-rc.3", "file-loader": "0.10.0", "filesize": "3.3.0", "fs-extra": "0.30.0", "gzip-size": "3.0.0", - "html-webpack-plugin": "2.24.0", + "html-webpack-plugin": "2.28.0", "http-proxy-middleware": "0.17.3", "jest": "18.1.0", - "json-loader": "0.5.4", "object-assign": "4.1.1", "postcss-loader": "1.2.2", "promise": "7.1.1", @@ -61,8 +60,8 @@ "strip-ansi": "3.0.1", "style-loader": "0.13.1", "url-loader": "0.5.7", - "webpack": "1.14.0", - "webpack-dev-server": "1.16.2", + "webpack": "2.2.1", + "webpack-dev-server": "2.3.0", "webpack-manifest-plugin": "1.1.0", "whatwg-fetch": "2.0.2" }, diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index c326b9b94d9..6943f6bb95b 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -268,7 +268,8 @@ function runDevServer(host, port, protocol) { }, // Enable HTTPS if the HTTPS environment variable is set to 'true' https: protocol === "https", - host: host + host: host, + overlay: false, }); // Our custom middleware proxies requests to /index.html or a remote API. diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh index 3c750feca53..4bb45d72853 100755 --- a/tasks/e2e-kitchensink.sh +++ b/tasks/e2e-kitchensink.sh @@ -167,9 +167,6 @@ npm link $root_path/packages/eslint-config-react-app npm link $root_path/packages/react-dev-utils npm link $root_path/packages/react-scripts -# ...and we need to remove template's .babelrc -rm .babelrc - # Test the build REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \ NODE_PATH=src \ From 8ec99b6fffcadfd865788f84e41bf51152073fa1 Mon Sep 17 00:00:00 2001 From: Blaine Kasten Date: Sat, 11 Feb 2017 17:05:54 -0600 Subject: [PATCH 002/163] Suggest jest-enzyme for simplifying test matchers (#994) * Suggest jest-enzyme for simplifying test matchers * Update README.md * Update README.md --- packages/react-scripts/template/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index c49da3e8d34..c30fb9d13ee 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -867,6 +867,20 @@ it('renders welcome message', () => { All Jest matchers are [extensively documented here](http://facebook.github.io/jest/docs/api.html#expect-value).
Nevertheless you can use a third-party assertion library like [Chai](http://chaijs.com/) if you want to, as described below. +Additionally, you might find [jest-enzyme](https://github.com/blainekasten/enzyme-matchers) helpful to simplify your tests with readable matchers. The above `contains` code can be written simpler with jest-enzyme. + +```js +expect(wrapper).toContainReact(welcome) +``` + +To setup jest-enzyme with Create React App, follow the instructions for [initializing your test environment](#initializing-test-environment) to import `jest-enzyme`. + +```js +// src/setupTests.js +import 'jest-enzyme'; +``` + + ### Using Third Party Assertion Libraries We recommend that you use `expect()` for assertions and `jest.fn()` for spies. If you are having issues with them please [file those against Jest](https://github.com/facebook/jest/issues/new), and we’ll fix them. We intend to keep making them better for React, supporting, for example, [pretty-printing React elements as JSX](https://github.com/facebook/jest/pull/1566). From 1fe6f5502c1d8d96e943f2a2e537e02cf6977c6b Mon Sep 17 00:00:00 2001 From: Dimitris Tsironis Date: Sun, 12 Feb 2017 02:38:59 +0200 Subject: [PATCH 003/163] Add SASS support documentation #1007 (#1008) * Add SASS support documentation #1007 * Change SASS section title to more generic label * Fix link in Table of Contents * Chain build-css with watch-css script, fix typos * Update Sass and Less naming style * Fix wording, remove offensive words * Slightly rewite --- packages/react-scripts/template/README.md | 47 +++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index c30fb9d13ee..00e4f248131 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -20,6 +20,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [Importing a Component](#importing-a-component) - [Adding a Stylesheet](#adding-a-stylesheet) - [Post-Processing CSS](#post-processing-css) +- [Adding a CSS Preprocessor (Sass, Less etc.)](#adding-a-css-preprocessor-sass-less-etc) - [Adding Images and Fonts](#adding-images-and-fonts) - [Using the `public` Folder](#using-the-public-folder) - [Changing the HTML](#changing-the-html) @@ -353,6 +354,52 @@ becomes this: There is currently no support for preprocessors such as Less, or for sharing variables across CSS files. +## Adding a CSS Preprocessor (Sass, Less etc.) + +Generally, we recommend that you don’t reuse the same CSS classes across different components. For example, instead of using a `.Button` CSS class in `` and `` components, we recommend creating a `