Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG-FRONTIER.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 8.17.0

- Support ESLint flat config in the dev-server lint plugin; bump `eslint-webpack-plugin` to `^5.0.3` and `eslint` to `^8.57.1`
- Apps with an `eslint.config.{js,mjs,cjs}` are linted with that config directly; apps without one keep the legacy eslintrc behavior unchanged
- `ESLINT_USE_FLAT_CONFIG=false` forces the legacy path

## 8.16.3

- Migrate CI from Travis to GitHub Actions (`.github/workflows/ci.yml`); delete `.travis.yml`
Expand Down
37 changes: 37 additions & 0 deletions packages/react-scripts/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ const babelRuntimeRegenerator = require.resolve('@babel/runtime/regenerator', {
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false'

const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === 'true'
// Apps with an ESLint flat config file get linted with it directly; apps without one keep the
// legacy eslintrc behavior (baseConfig extending @fs/eslint-config-frontier-react).
const useFlatEslintConfig =
process.env.ESLINT_USE_FLAT_CONFIG !== 'false' &&
['eslint.config.js', 'eslint.config.mjs', 'eslint.config.cjs'].some(configFile =>
fs.existsSync(path.join(paths.appPath, configFile))
)
const needsWci18nSupport = process.env.NEEDS_WCI18N_SUPPORT === 'true'

const imageInlineSizeLimit = parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || '10000')
Expand Down Expand Up @@ -878,11 +885,41 @@ module.exports = function (webpackEnv) {
},
}),
!disableESLintPlugin &&
useFlatEslintConfig &&
new ESLintPlugin({
// Plugin options
extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
formatter: require.resolve('react-dev-utils/eslintFormatter'),
// 'use-at-your-own-risk' exposes FlatESLint on ESLint 8.57, which configType 'flat'
// needs; the app's eslint.config.* is auto-loaded from cwd. On ESLint 9+ the plugin
// uses loadESLint() and this path still resolves the right class.
eslintPath: require.resolve('eslint/use-at-your-own-risk'),
configType: 'flat',
failOnError: false,
context: paths.appSrc,
cache: true,
cacheLocation: path.resolve(paths.appNodeModules, '.cache/.eslintcache'),
// ESLint class options
cwd: paths.appPath,
baseConfig: [
{
rules: {
...(!hasJsxRuntime && {
'react/react-in-jsx-scope': 'error',
}),
},
},
],
}),
!disableESLintPlugin &&
!useFlatEslintConfig &&
new ESLintPlugin({
// Plugin options
extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
// eslint-webpack-plugin@5 defaults to 'flat'; keep legacy apps on eslintrc.
configType: 'eslintrc',
failOnError: false,
context: paths.appSrc,
cache: true,
Expand Down
6 changes: 3 additions & 3 deletions packages/react-scripts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fs/react-scripts",
"version": "8.16.3",
"version": "8.17.0",
"upstreamVersion": "5.0.1",
"description": "Configuration and scripts for Create React App.",
"repository": {
Expand Down Expand Up @@ -80,8 +80,8 @@
"filing-cabinet": "^5.2.0",
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"eslint": "^8.3.0",
"eslint-webpack-plugin": "^3.1.1",
"eslint": "^8.57.1",
"eslint-webpack-plugin": "^5.0.3",
"file-loader": "^6.2.0",
"fs-extra": "^10.0.0",
"html-webpack-plugin": "^5.5.0",
Expand Down
69 changes: 41 additions & 28 deletions publishPrReleaseAndCreateFreshCraTemplate.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,49 @@
'use strict'
'use strict';

const fs = require('fs')
const path = require('path')
const fs = require('fs');
const path = require('path');

const reactScriptPath = path.join(__dirname, 'packages/react-scripts')
const reactScriptPath = path.join(__dirname, 'packages/react-scripts');

const { alterPackageJsonFile, getCiPrereleaseVersion } = require(path.join(
reactScriptPath,
'scripts/utils/frontierInit'
))
const { runExternalCommandSync } = require(path.join(reactScriptPath, 'scripts/utils/osUtils'))
));
const { runExternalCommandSync } = require(path.join(
reactScriptPath,
'scripts/utils/osUtils'
));

let originalVersion
let newVersion
let originalVersion;
let newVersion;

alterPackageJsonFile(reactScriptPath, packageJson => {
originalVersion = packageJson.version
newVersion = getCiPrereleaseVersion(packageJson.version)
console.log(`setting @fs/react-scripts version to "${newVersion}" temporarily to get published`)
packageJson.version = newVersion
return packageJson
})
originalVersion = packageJson.version;
newVersion = getCiPrereleaseVersion(packageJson.version);
console.log(
`setting @fs/react-scripts version to "${newVersion}" temporarily to get published`
);
packageJson.version = newVersion;
return packageJson;
});

runExternalCommandSync('npm', ['run', 'fs-publish', '--', '--allow-earlier-version'], { cwd: reactScriptPath })
runExternalCommandSync(
'npm',
['run', 'fs-publish', '--', '--allow-earlier-version'],
{ cwd: reactScriptPath }
);

alterPackageJsonFile(reactScriptPath, packageJson => {
packageJson.version = originalVersion
console.log(`setting @fs/react-scripts version back to "${originalVersion}"`)
return packageJson
})
packageJson.version = originalVersion;
console.log(`setting @fs/react-scripts version back to "${originalVersion}"`);
return packageJson;
});

const tmpDir = `${process.env.HOME}/tmp`
const tmpDir = `${process.env.HOME}/tmp`;

const appDir = path.join(tmpDir, 'fresh-cra-template')
const appDir = path.join(tmpDir, 'fresh-cra-template');

runExternalCommandSync('mkdir', ['-p', tmpDir])
runExternalCommandSync('mkdir', ['-p', tmpDir]);
runExternalCommandSync(
'npx',
[
Expand All @@ -47,20 +56,24 @@ runExternalCommandSync(
'@fs/cra-template',
],
{ cwd: tmpDir }
)
);

// create-react-app does not fail when the template's dependency install fails: init.js logs
// "`npm install ...` failed" and returns, so the process still exits 0. That is deliberate
// upstream behavior — exiting non-zero makes create-react-app delete the app's package.json and
// node_modules — so assert here instead. Without this, the real failure surfaces two steps later
// as `react-scripts: not found`, which reads like a react-scripts packaging bug.
const scriptsBin = path.join(appDir, 'node_modules', '.bin', 'react-scripts')
const scriptsBin = path.join(appDir, 'node_modules', '.bin', 'react-scripts');

if (!fs.existsSync(scriptsBin)) {
console.error(`\nTemplate dependency install did not complete: ${scriptsBin} is missing.`)
console.error(
`\nTemplate dependency install did not complete: ${scriptsBin} is missing.`
);
console.error(
'Check the npm output above. A tarball blocked by jfrog curation shows up as `npm error code E403`,'
)
console.error('and is usually a transitive dependency of the template rather than of react-scripts.')
process.exit(1)
);
console.error(
'and is usually a transitive dependency of the template rather than of react-scripts.'
);
process.exit(1);
}
Loading