From a55798ef79c01c45dd85b30c58f065d98896daa7 Mon Sep 17 00:00:00 2001 From: Ian Sutherland Date: Sun, 2 Aug 2020 11:24:30 -0600 Subject: [PATCH] Add Fast Refresh warning when using React < 16.10 (#9350) --- docusaurus/docs/advanced-configuration.md | 2 +- packages/react-dev-utils/webpackHotDevClient.js | 2 +- packages/react-scripts/config/env.js | 2 +- packages/react-scripts/scripts/start.js | 13 +++++++++++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docusaurus/docs/advanced-configuration.md b/docusaurus/docs/advanced-configuration.md index 958f9ac3168..a4073a24b31 100644 --- a/docusaurus/docs/advanced-configuration.md +++ b/docusaurus/docs/advanced-configuration.md @@ -25,5 +25,5 @@ You can adjust various development and production settings by setting environmen | INLINE_RUNTIME_CHUNK | 🚫 Ignored | ✅ Used | By default, Create React App will embed the runtime script into `index.html` during the production build. When set to `false`, the script will not be embedded and will be imported as usual. This is normally required when dealing with CSP. | | IMAGE_INLINE_SIZE_LIMIT | 🚫 Ignored | ✅ Used | By default, images smaller than 10,000 bytes are encoded as a data URI in base64 and inlined in the CSS or JS build artifact. Set this to control the size limit in bytes. Setting it to 0 will disable the inlining of images. | | EXTEND_ESLINT | ✅ Used | ✅ Used | When set to `true`, user provided ESLint configs will be used by `eslint-loader`. Note that any rules set to `"error"` will stop the application from building. | -| FAST_REFRESH | ✅ Used | 🚫 Ignored | When set to `true`, enables experimental support for fast refresh to allow you to tweak your components in real time without reloading the page. | +| FAST_REFRESH | ✅ Used | 🚫 Ignored | When set to `false`, disables experimental support for Fast Refresh to allow you to tweak your components in real time without reloading the page. | | TSC_COMPILE_ON_ERROR | ✅ Used | ✅ Used | When set to `true`, you can run and properly build TypeScript projects even if there are TypeScript type check errors. These errors are printed as warnings in the terminal and/or browser console. | diff --git a/packages/react-dev-utils/webpackHotDevClient.js b/packages/react-dev-utils/webpackHotDevClient.js index f9d814fdd11..16198d3374a 100644 --- a/packages/react-dev-utils/webpackHotDevClient.js +++ b/packages/react-dev-utils/webpackHotDevClient.js @@ -243,7 +243,7 @@ function tryApplyUpdates(onHotUpdateSuccess) { } function handleApplyUpdates(err, updatedModules) { - const hasReactRefresh = process.env.FAST_REFRESH; + const hasReactRefresh = process.env.FAST_REFRESH !== 'false'; const wantsForcedReload = err || !updatedModules || hadRuntimeError; // React refresh can handle hot-reloading over errors. if (!hasReactRefresh && wantsForcedReload) { diff --git a/packages/react-scripts/config/env.js b/packages/react-scripts/config/env.js index 99d7b56ec72..7fd6f3b2e27 100644 --- a/packages/react-scripts/config/env.js +++ b/packages/react-scripts/config/env.js @@ -97,7 +97,7 @@ function getClientEnvironment(publicUrl) { // react-refresh is not 100% stable at this time, // which is why it's disabled by default. // It is defined here so it is available in the webpackHotDevClient. - FAST_REFRESH: process.env.FAST_REFRESH || false, + FAST_REFRESH: process.env.FAST_REFRESH !== 'false', } ); // Stringify all values so we can feed into webpack DefinePlugin diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index daa98423f1a..ffbb15d1204 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -44,10 +44,14 @@ const { prepareUrls, } = require('react-dev-utils/WebpackDevServerUtils'); const openBrowser = require('react-dev-utils/openBrowser'); +const semver = require('semver'); const paths = require('../config/paths'); const configFactory = require('../config/webpack.config'); const createDevServerConfig = require('../config/webpackDevServer.config'); +const getClientEnvironment = require('../config/env'); +const react = require(require.resolve('react', { paths: [paths.appPath] })); +const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); const useYarn = fs.existsSync(paths.yarnLockFile); const isInteractive = process.stdout.isTTY; @@ -95,6 +99,7 @@ checkBrowsers(paths.appPath, isInteractive) const config = configFactory('development'); const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; const appName = require(paths.appPackageJson).name; + const useTypeScript = fs.existsSync(paths.appTsConfig); const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true'; const urls = prepareUrls( @@ -142,6 +147,14 @@ checkBrowsers(paths.appPath, isInteractive) clearConsole(); } + if (env.raw.FAST_REFRESH && semver.lt(react.version, '16.10.0')) { + console.log( + chalk.yellow( + `Fast Refresh requires React 16.10 or higher. You are using React ${react.version}.` + ) + ); + } + console.log(chalk.cyan('Starting the development server...\n')); openBrowser(urls.localUrlForBrowser); });