Skip to content

Commit 415a7b1

Browse files
authored
feat: support create-react-app v5 (#19434)
1 parent 7453c1d commit 415a7b1

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

npm/react/plugins/react-scripts/findReactScriptsWebpackConfig.js

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const { allowModuleSourceInPlace } = require('../utils/webpack-helpers')
55
const { addCypressToWebpackEslintRulesInPlace } = require('../utils/eslint-helpers')
66
const { getTranspileFolders } = require('../utils/get-transpile-folders')
77
const { addFolderToBabelLoaderTranspileInPlace } = require('../utils/babel-helpers')
8+
const { reactScriptsFiveModifications, isReactScripts5 } = require('../../dist/react-scripts/reactScriptsFive')
89

910
module.exports = function findReactScriptsWebpackConfig (config, {
1011
webpackConfigPath,
@@ -28,6 +29,12 @@ module.exports = function findReactScriptsWebpackConfig (config, {
2829
addFolderToBabelLoaderTranspileInPlace(cypressFolder, webpackConfig)
2930
})
3031

32+
if (isReactScripts5) {
33+
debug('Modifying configuration for react-scripts@5')
34+
35+
reactScriptsFiveModifications(webpackConfig)
36+
}
37+
3138
debug('resolved webpack config: %o', webpackConfig)
3239

3340
return webpackConfig
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import _debug from 'debug'
2+
import type { Configuration } from 'webpack'
3+
import reactScriptsPackageJson from 'react-scripts/package.json'
4+
5+
const debug = _debug('@cypress/react:react-scripts')
6+
7+
type DefinePlugin =
8+
| { definitions: Record<string, Record<string, any>> }
9+
| undefined;
10+
type ESLintWebpackPlugin =
11+
| { options: { baseConfig?: { globals?: Record<string, any> } } }
12+
| undefined;
13+
14+
export function reactScriptsFiveModifications (webpackConfig: Configuration) {
15+
// React-Scripts sets the webpack target to ["browserslist"] which tells
16+
// webpack to target the browsers found within the browserslist config
17+
// depending on the environment (process.env.NODE_ENV). Since we set
18+
// process.env.NODE_ENV = "test", webpack is unable to find any browsers and errors.
19+
// We set BROWSERSLIST_ENV = "development" to override the default NODE_ENV search of browsers.
20+
if (!process.env.BROWSERSLIST_ENV) {
21+
process.env.BROWSERSLIST_ENV = 'development'
22+
}
23+
24+
// We use the "development" configuration of the react-scripts webpack config.
25+
// There is a conflict when settings process.env.NODE_ENV = "test" since DefinePlugin
26+
// uses the "development" configuration and expects process.env.NODE_ENV = "development".
27+
const definePlugin: DefinePlugin = webpackConfig.plugins?.find(
28+
(plugin) => plugin.constructor.name === 'DefinePlugin'
29+
) as unknown as DefinePlugin
30+
31+
if (definePlugin) {
32+
const processEnv = definePlugin.definitions['process.env']
33+
34+
processEnv.NODE_ENV = JSON.stringify('development')
35+
36+
debug('Found "DefinePlugin", modified "process.env" definition %o', processEnv)
37+
}
38+
39+
// React-Scripts v5 no longers uses a loader to configure eslint, so we add globals
40+
// to the plugin.
41+
const eslintPlugin = webpackConfig.plugins?.find(
42+
(plugin) => plugin.constructor.name === 'ESLintWebpackPlugin'
43+
) as unknown as ESLintWebpackPlugin
44+
45+
if (eslintPlugin) {
46+
const cypressGlobals = ['cy', 'Cypress', 'before', 'after', 'context']
47+
.reduce((acc, global) => ({ ...acc, [global]: 'writable' }), {})
48+
49+
eslintPlugin.options.baseConfig = {
50+
...eslintPlugin.options.baseConfig,
51+
globals: {
52+
...eslintPlugin.options.baseConfig?.globals,
53+
...cypressGlobals,
54+
},
55+
}
56+
57+
debug('Found ESLintWebpackPlugin, modified eslint config %o', eslintPlugin.options.baseConfig)
58+
}
59+
}
60+
61+
export const isReactScripts5 = Number(reactScriptsPackageJson.version[0]) >= 5

npm/react/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"cypress"
2020
] /* Type declaration files to be included in compilation. */,
2121
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */,
22-
"esModuleInterop": true
22+
"esModuleInterop": true,
23+
"resolveJsonModule": true
2324
},
2425
"include": ["src/**/*.ts"],
2526
}

0 commit comments

Comments
 (0)