From 968afb7b88b4ae4a01c6f85a8b8b24874ba23c05 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 13:51:56 +0200 Subject: [PATCH 01/12] lerna -> changesets --- .changeset/README.md | 8 ++++++++ .changeset/config.json | 10 ++++++++++ lerna.json | 19 ------------------- package.json | 6 +++--- tasks/publish.sh | 3 ++- 5 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json delete mode 100644 lerna.json diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 000000000..4f3b76b09 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 000000000..4066833db --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@1.3.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "linked": [], + "access": "restricted", + "baseBranch": "master", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/lerna.json b/lerna.json deleted file mode 100644 index 8ea483cdb..000000000 --- a/lerna.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "lerna": "2.6.0", - "npmClient": "yarn", - "useWorkspaces": true, - "version": "independent", - "changelog": { - "repo": "facebook/create-react-app", - "labels": { - "tag: new feature": ":rocket: New Feature", - "tag: breaking change": ":boom: Breaking Change", - "tag: bug fix": ":bug: Bug Fix", - "tag: enhancement": ":nail_care: Enhancement", - "tag: documentation": ":memo: Documentation", - "tag: internal": ":house: Internal", - "tag: underlying tools": ":hammer: Underlying Tools" - }, - "cacheDir": ".changelog" - } -} diff --git a/package.json b/package.json index 816a11419..5aabcf443 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ ], "scripts": { "build": "cd packages/react-scripts && node bin/react-scripts.js build", - "changelog": "lerna-changelog", "create-react-app": "node tasks/cra.js", "e2e": "tasks/e2e-simple.sh", "e2e:docker": "tasks/local-test.sh", @@ -19,6 +18,9 @@ "format": "prettier --write 'packages/*/*.js' 'packages/*/!(node_modules)/**/*.js'", "compile:lockfile": "node tasks/compile-lockfile.js" }, + "dependencies": { + "@changesets/cli": "^2.10.2" + }, "devDependencies": { "@testing-library/jest-dom": "^5.11.0", "@testing-library/react": "^10.4.3", @@ -31,8 +33,6 @@ "globby": "^11.0.0", "husky": "^4.2.5", "jest": "26.3.0", - "lerna": "3.20.2", - "lerna-changelog": "~0.8.2", "lint-staged": "^10.2.2", "meow": "^6.1.1", "multimatch": "^4.0.0", diff --git a/tasks/publish.sh b/tasks/publish.sh index f5ed3838c..892c8dae1 100755 --- a/tasks/publish.sh +++ b/tasks/publish.sh @@ -27,6 +27,7 @@ cd .. root_path=$PWD if [ -z $CI ]; then + yarn changeset version yarn compile:lockfile fi @@ -48,4 +49,4 @@ if [ -z $CI ]; then fi # Go! -NPM_CONFIG_OTP="$otp" ./node_modules/.bin/lerna publish "$@" +NPM_CONFIG_OTP="$otp" yarn changeset publish "$@" -- GitLab From 03b6dfead162ca77b244d75c1ef2fd0b431a7798 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 14:15:43 +0200 Subject: [PATCH 02/12] Mark pkgs as private --- packages/babel-plugin-named-asset-import/package.json | 1 + packages/confusing-browser-globals/package.json | 1 + packages/cra-template-typescript/package.json | 1 + packages/cra-template/package.json | 1 + packages/create-react-app/package.json | 1 + packages/eslint-config-react-app/package.json | 1 + packages/react-app-polyfill/package.json | 1 + packages/react-dev-utils/package.json | 1 + packages/react-error-overlay/package.json | 1 + 9 files changed, 9 insertions(+) diff --git a/packages/babel-plugin-named-asset-import/package.json b/packages/babel-plugin-named-asset-import/package.json index 96db09678..305ef8b6a 100644 --- a/packages/babel-plugin-named-asset-import/package.json +++ b/packages/babel-plugin-named-asset-import/package.json @@ -1,5 +1,6 @@ { "name": "babel-plugin-named-asset-import", + "private": true, "version": "0.3.6", "description": "Babel plugin for named asset imports in Create React App", "repository": { diff --git a/packages/confusing-browser-globals/package.json b/packages/confusing-browser-globals/package.json index 2a30a3e2f..cf69bfb46 100644 --- a/packages/confusing-browser-globals/package.json +++ b/packages/confusing-browser-globals/package.json @@ -1,5 +1,6 @@ { "name": "confusing-browser-globals", + "private": true, "version": "1.0.9", "description": "A list of browser globals that are often used by mistake instead of local variables", "license": "MIT", diff --git a/packages/cra-template-typescript/package.json b/packages/cra-template-typescript/package.json index 5b3936acf..1ad3327bf 100644 --- a/packages/cra-template-typescript/package.json +++ b/packages/cra-template-typescript/package.json @@ -1,5 +1,6 @@ { "name": "cra-template-typescript", + "private": true, "version": "1.0.3", "keywords": [ "react", diff --git a/packages/cra-template/package.json b/packages/cra-template/package.json index d34d8229b..326759198 100644 --- a/packages/cra-template/package.json +++ b/packages/cra-template/package.json @@ -1,5 +1,6 @@ { "name": "cra-template", + "private": true, "version": "1.0.3", "keywords": [ "react", diff --git a/packages/create-react-app/package.json b/packages/create-react-app/package.json index 58f3f9d71..4af352a4a 100644 --- a/packages/create-react-app/package.json +++ b/packages/create-react-app/package.json @@ -1,5 +1,6 @@ { "name": "create-react-app", + "private": true, "version": "3.4.1", "keywords": [ "react" diff --git a/packages/eslint-config-react-app/package.json b/packages/eslint-config-react-app/package.json index 4f68416e9..772e022ee 100644 --- a/packages/eslint-config-react-app/package.json +++ b/packages/eslint-config-react-app/package.json @@ -1,5 +1,6 @@ { "name": "eslint-config-react-app", + "private": true, "version": "5.2.1", "description": "ESLint configuration used by Create React App", "repository": { diff --git a/packages/react-app-polyfill/package.json b/packages/react-app-polyfill/package.json index 7b65a9d2b..16794273d 100644 --- a/packages/react-app-polyfill/package.json +++ b/packages/react-app-polyfill/package.json @@ -1,5 +1,6 @@ { "name": "react-app-polyfill", + "private": true, "version": "1.0.6", "description": "Polyfills for various browsers including commonly used language features", "repository": { diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index d54b2264e..74600505b 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -1,5 +1,6 @@ { "name": "react-dev-utils", + "private": true, "version": "10.2.1", "description": "webpack utilities used by Create React App", "repository": { diff --git a/packages/react-error-overlay/package.json b/packages/react-error-overlay/package.json index 5b82b4493..c7c6f300e 100644 --- a/packages/react-error-overlay/package.json +++ b/packages/react-error-overlay/package.json @@ -1,5 +1,6 @@ { "name": "react-error-overlay", + "private": true, "version": "6.0.7", "description": "An overlay for displaying stack frames.", "main": "lib/index.js", -- GitLab From 37c0602887cab9edfc69584145a19506fb27da42 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 17:13:46 +0200 Subject: [PATCH 03/12] apply-previous-changes --- .../docs/adding-multiple-entry-points.md | 27 ++ docusaurus/docs/advanced-configuration.md | 5 + docusaurus/website/docusaurus.config.js | 11 +- docusaurus/website/package.json | 3 +- packages/babel-preset-react-app/README.md | 2 +- packages/babel-preset-react-app/create.js | 15 + .../babel-preset-react-app/dependencies.js | 15 + packages/babel-preset-react-app/package.json | 21 +- packages/react-scripts/README.md | 5 + .../config/jest/babelTransform.js | 2 +- packages/react-scripts/config/paths.js | 54 +++- .../react-scripts/config/webpack.config.js | 256 ++++++++++------ .../react-scripts/config/yarn-workspaces.js | 277 ++++++++++++++++++ .../kitchensink/template/jest.transform.js | 2 +- packages/react-scripts/package.json | 16 +- packages/react-scripts/scripts/build.js | 15 +- packages/react-scripts/scripts/start.js | 141 ++++++--- .../scripts/utils/createJestConfig.js | 7 + .../scripts/utils/verifyTypeScriptSetup.js | 7 +- packages/stylelint-config-react-app/index.js | 6 + .../stylelint-config-react-app/package.json | 26 ++ 21 files changed, 756 insertions(+), 157 deletions(-) create mode 100644 docusaurus/docs/adding-multiple-entry-points.md create mode 100644 packages/react-scripts/config/yarn-workspaces.js create mode 100644 packages/stylelint-config-react-app/index.js create mode 100644 packages/stylelint-config-react-app/package.json diff --git a/docusaurus/docs/adding-multiple-entry-points.md b/docusaurus/docs/adding-multiple-entry-points.md new file mode 100644 index 000000000..260831adb --- /dev/null +++ b/docusaurus/docs/adding-multiple-entry-points.md @@ -0,0 +1,27 @@ +--- +id: adding-multiple-entry-points +title: Adding multiple entry points +--- + +Create React App comes with an embedded `index.html` and `index.js` which is shown when you're running the `app` at `http://localhost:3000`. In case you decided to add new `apps` (pages/entry point), please, follow the steps: + +## Creating files + +Please, create your `.html` and `.js` (Or TypeScript file). The embedded files come inside `public` and `src` folder. + +## Add the new app in package.json + +After creating the `app` files, you must specify it into the `appPages` inside the `package.json`. It should shape the following structure: + +```json +{ + "name": "login", + "title": "login", + "appHtml": "public/login.html", + "appIndexJs": "src/login" +} +``` + +## Accessing the new app + +Run `npm start` or `yarn start` and change the URL by referencing the new page, like `http://localhost:3000/login.html` diff --git a/docusaurus/docs/advanced-configuration.md b/docusaurus/docs/advanced-configuration.md index 6da2ad174..3c2b92710 100644 --- a/docusaurus/docs/advanced-configuration.md +++ b/docusaurus/docs/advanced-configuration.md @@ -26,3 +26,8 @@ You can adjust various development and production settings by setting environmen | 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. | | 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. | +| OUTPUT | ✅ Used | ✅ Used | Relative build output path (defaults to `./build`) | +| DISABLE_ASSET_HASHING | ✅ Used | ✅ Used | Turns off asset hashing for emitted resources | +| BACKEND_PORT | ✅ Used | 🚫 Ignored | Specify to which backend ports requests needs to be proxied during development mode | +| EMIT | ✅ Used | 🚫 Ignored | Should assets be written to disc during development | +| PROXY_URL | ✅ Used | 🚫 Ignored | Where to proxy BrowserSync during development, by default this will be `localhost:${BACKEND_PORT}` | diff --git a/docusaurus/website/docusaurus.config.js b/docusaurus/website/docusaurus.config.js index 238495569..b516d4d67 100644 --- a/docusaurus/website/docusaurus.config.js +++ b/docusaurus/website/docusaurus.config.js @@ -1,3 +1,4 @@ +'use strict'; /** * Copyright (c) 2017-present, Facebook, Inc. * @@ -8,10 +9,10 @@ const siteConfig = { title: 'Create React App', tagline: 'Set up a modern web app by running one command.', - url: 'https://create-react-app.dev', - baseUrl: '/', + url: 'https://foreachos.github.io', + baseUrl: '/create-react-app/', projectName: 'create-react-app', - organizationName: 'facebook', + organizationName: 'foreachos', favicon: 'img/favicon/favicon.ico', presets: [ [ @@ -21,7 +22,7 @@ const siteConfig = { path: '../docs', sidebarPath: require.resolve('./sidebars.json'), editUrl: - 'https://github.com/facebook/create-react-app/edit/master/docusaurus/website', + 'https://github.com/foreachos/create-react-app/edit/master/docusaurus/docs/', showLastUpdateAuthor: true, showLastUpdateTime: true, }, @@ -51,7 +52,7 @@ const siteConfig = { position: 'right', }, { - href: 'https://www.github.com/facebook/create-react-app', + href: 'https://www.github.com/foreachos/create-react-app', label: 'GitHub', position: 'right', }, diff --git a/docusaurus/website/package.json b/docusaurus/website/package.json index 4a7af6913..110919a41 100644 --- a/docusaurus/website/package.json +++ b/docusaurus/website/package.json @@ -3,7 +3,8 @@ "start": "docusaurus start", "build": "docusaurus build", "swizzle": "docusaurus swizzle", - "deploy": "docusaurus deploy" + "deploy": "docusaurus deploy", + "deploy:gh": "GIT_USER=jarrku USE_SSH=true yarn deploy" }, "dependencies": { "@docusaurus/core": "^2.0.0-alpha.39", diff --git a/packages/babel-preset-react-app/README.md b/packages/babel-preset-react-app/README.md index 1fc517882..d80f7fe8e 100644 --- a/packages/babel-preset-react-app/README.md +++ b/packages/babel-preset-react-app/README.md @@ -1,4 +1,4 @@ -# babel-preset-react-app +# @foreachbe/eslint-config-react-app This package includes the Babel preset used by [Create React App](https://github.com/facebook/create-react-app).<br> Please refer to its documentation: diff --git a/packages/babel-preset-react-app/create.js b/packages/babel-preset-react-app/create.js index 7aacc8a23..c10e5e961 100644 --- a/packages/babel-preset-react-app/create.js +++ b/packages/babel-preset-react-app/create.js @@ -20,11 +20,22 @@ const validateBoolOption = (name, value, defaultValue) => { return value; }; +const hasDependency = dependency => { + try { + require.resolve(dependency); + return true; + } catch (err) { + return false; + } +}; + module.exports = function (api, opts, env) { if (!opts) { opts = {}; } + var hasEmotionDependency = hasDependency('@emotion/core'); + var isEnvDevelopment = env === 'development'; var isEnvProduction = env === 'production'; var isEnvTest = env === 'test'; @@ -99,6 +110,10 @@ module.exports = function (api, opts, env) { }, ], isTypeScriptEnabled && [require('@babel/preset-typescript').default], + // Emotion CSS in JS optimization + hasEmotionDependency && [ + require('@emotion/babel-preset-css-prop').default, + ], ].filter(Boolean), plugins: [ // Strip flow types before any other transform, emulating the behavior diff --git a/packages/babel-preset-react-app/dependencies.js b/packages/babel-preset-react-app/dependencies.js index acbd65aea..5d2a368de 100644 --- a/packages/babel-preset-react-app/dependencies.js +++ b/packages/babel-preset-react-app/dependencies.js @@ -20,11 +20,22 @@ const validateBoolOption = (name, value, defaultValue) => { return value; }; +const hasDependency = dependency => { + try { + require.resolve(dependency); + return true; + } catch (err) { + return false; + } +}; + module.exports = function (api, opts) { if (!opts) { opts = {}; } + var hasEmotionDependency = hasDependency('@emotion/core'); + // This is similar to how `env` works in Babel: // https://babeljs.io/docs/usage/babelrc/#env-option // We are not using `env` because it’s ignored in versions > babel-core@6.10.4: @@ -91,6 +102,10 @@ module.exports = function (api, opts) { exclude: ['transform-typeof-symbol'], }, ], + // Emotion CSS in JS optimization + hasEmotionDependency && [ + require('@emotion/babel-preset-css-prop').default, + ], ].filter(Boolean), plugins: [ // Disabled as it's handled automatically by preset-env, and `selectiveLoose` isn't diff --git a/packages/babel-preset-react-app/package.json b/packages/babel-preset-react-app/package.json index 7bcff4e13..733bb5d62 100644 --- a/packages/babel-preset-react-app/package.json +++ b/packages/babel-preset-react-app/package.json @@ -1,15 +1,19 @@ { - "name": "babel-preset-react-app", - "version": "9.1.2", + "name": "@foreachbe/babel-preset-react-app", + "version": "5.0.0", "description": "Babel preset used by Create React App", "repository": { "type": "git", - "url": "https://github.com/facebook/create-react-app.git", + "url": "https://github.com/foreachbe/create-react-app.git", "directory": "packages/babel-preset-react-app" }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, "license": "MIT", "bugs": { - "url": "https://github.com/facebook/create-react-app/issues" + "url": "https://github.com/foreachbe/create-react-app/issues" }, "files": [ "create.js", @@ -21,6 +25,7 @@ "test.js" ], "dependencies": { + "@emotion/babel-preset-css-prop": "10.0.27", "@babel/core": "7.10.5", "@babel/plugin-proposal-class-properties": "7.10.4", "@babel/plugin-proposal-decorators": "7.10.5", @@ -36,5 +41,13 @@ "@babel/runtime": "7.10.5", "babel-plugin-macros": "2.8.0", "babel-plugin-transform-react-remove-prop-types": "0.4.24" + }, + "peerDependencies": { + "@emotion/core": "^10.0.0" + }, + "peerDependenciesMeta": { + "@emotion/core": { + "optional": true + } } } diff --git a/packages/react-scripts/README.md b/packages/react-scripts/README.md index d6de290ff..e990a6bdb 100644 --- a/packages/react-scripts/README.md +++ b/packages/react-scripts/README.md @@ -5,3 +5,8 @@ Please refer to its documentation: - [Getting Started](https://facebook.github.io/create-react-app/docs/getting-started) – How to create a new app. - [User Guide](https://facebook.github.io/create-react-app/) – How to develop apps bootstrapped with Create React App. + +## Additional CLI flags: + +- `--output=relativeOutputPath` -> set a relative build path (default `/build`) +- `--noAssetHashing` -> turns off hashing of assets diff --git a/packages/react-scripts/config/jest/babelTransform.js b/packages/react-scripts/config/jest/babelTransform.js index 7feed94c5..84e22313c 100644 --- a/packages/react-scripts/config/jest/babelTransform.js +++ b/packages/react-scripts/config/jest/babelTransform.js @@ -10,7 +10,7 @@ const babelJest = require('babel-jest'); module.exports = babelJest.createTransformer({ - presets: [require.resolve('babel-preset-react-app')], + presets: [require.resolve('@foreachbe/babel-preset-react-app')], babelrc: false, configFile: false, }); diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index 516513081..a99782b4e 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -11,12 +11,35 @@ const path = require('path'); const fs = require('fs'); const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath'); +const findUp = require('find-up'); // Make sure any symlinks in the project folder are resolved: // https://github.com/facebook/create-react-app/issues/637 const appDirectory = fs.realpathSync(process.cwd()); const resolveApp = relativePath => path.resolve(appDirectory, relativePath); +function getAppPages() { + const appPages = require(resolveApp('package.json')).appPages || []; + // checks if there is at least one entry point specified + + if (appPages.length === 0) { + appPages.push({ + name: 'index', + title: 'index', + appHtml: 'public/index.html', + appIndexJs: 'src/index', + }); + } + + return appPages.map(p => ({ + ...p, + appHtml: p.appHtml && resolveApp(p.appHtml), + appIndexJs: resolveModule(resolveApp, p.appIndexJs), + })); +} + +const appPages = getAppPages(); + // We use `PUBLIC_URL` environment variable or "homepage" field to infer // "public path" at which the app is served. // webpack needs to know it to put the right <script> hrefs into HTML even in @@ -56,12 +79,18 @@ const resolveModule = (resolveFn, filePath) => { return resolveFn(`${filePath}.js`); }; +const outputPath = process.env.OUTPUT || 'build'; + +//TODO add appStylelintConfig + // config after eject: we're in ./config/ module.exports = { dotenv: resolveApp('.env'), appPath: resolveApp('.'), - appBuild: resolveApp('build'), + appBuild: resolveApp(outputPath), appPublic: resolveApp('public'), + appPages, + appStylelintConfig: resolveApp('.stylelintrc'), appHtml: resolveApp('public/index.html'), appIndexJs: resolveModule(resolveApp, 'src/index'), appPackageJson: resolveApp('package.json'), @@ -73,6 +102,7 @@ module.exports = { proxySetup: resolveApp('src/setupProxy.js'), appNodeModules: resolveApp('node_modules'), swSrc: resolveModule(resolveApp, 'src/service-worker'), + resolveApp, publicUrlOrPath, }; @@ -83,8 +113,10 @@ const resolveOwn = relativePath => path.resolve(__dirname, '..', relativePath); module.exports = { dotenv: resolveApp('.env'), appPath: resolveApp('.'), - appBuild: resolveApp('build'), + appBuild: resolveApp(outputPath), + appStylelintConfig: resolveApp('.stylelintrc'), appPublic: resolveApp('public'), + appPages, appHtml: resolveApp('public/index.html'), appIndexJs: resolveModule(resolveApp, 'src/index'), appPackageJson: resolveApp('package.json'), @@ -97,6 +129,7 @@ module.exports = { appNodeModules: resolveApp('node_modules'), swSrc: resolveModule(resolveApp, 'src/service-worker'), publicUrlOrPath, + resolveApp, // These properties only exist before ejecting: ownPath: resolveOwn('.'), ownNodeModules: resolveOwn('node_modules'), // This is empty on npm 3 @@ -105,7 +138,9 @@ module.exports = { }; const ownPackageJson = require('../package.json'); -const reactScriptsPath = resolveApp(`node_modules/${ownPackageJson.name}`); +const reactScriptsPath = findUp.sync(`node_modules/${ownPackageJson.name}`, { + cwd: resolveApp('.'), +}); const reactScriptsLinked = fs.existsSync(reactScriptsPath) && fs.lstatSync(reactScriptsPath).isSymbolicLink(); @@ -116,6 +151,16 @@ if ( __dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1 ) { const templatePath = '../cra-template/template'; + + const appPages = [ + { + name: 'index', + title: 'index', + appHtml: resolveOwn(`${templatePath}/public/index.html`), + appIndexJs: resolveModule(resolveOwn, `${templatePath}/src/index`), + }, + ]; + module.exports = { dotenv: resolveOwn(`${templatePath}/.env`), appPath: resolveApp('.'), @@ -123,6 +168,8 @@ if ( appPublic: resolveOwn(`${templatePath}/public`), appHtml: resolveOwn(`${templatePath}/public/index.html`), appIndexJs: resolveModule(resolveOwn, `${templatePath}/src/index`), + appPages, + appStylelintConfig: resolveOwn(`${templatePath}/.stylelintrc`), appPackageJson: resolveOwn('package.json'), appSrc: resolveOwn(`${templatePath}/src`), appTsConfig: resolveOwn(`${templatePath}/tsconfig.json`), @@ -133,6 +180,7 @@ if ( appNodeModules: resolveOwn('node_modules'), swSrc: resolveModule(resolveOwn, `${templatePath}/src/service-worker`), publicUrlOrPath, + resolveApp, // These properties only exist before ejecting: ownPath: resolveOwn('.'), ownNodeModules: resolveOwn('node_modules'), diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 0c8dbae85..510ae72fd 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -37,6 +37,10 @@ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin' const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // @remove-on-eject-end const postcssNormalize = require('postcss-normalize'); +const StyleLintPlugin = require('stylelint-webpack-plugin'); +const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') + .BundleAnalyzerPlugin; +const yarnWorkspaces = require('./yarn-workspaces'); const appPackageJson = require(paths.appPackageJson); @@ -49,7 +53,10 @@ const webpackDevClientEntry = require.resolve( // Some apps do not need the benefits of saving a web request, so not inlining the chunk // makes for a smoother build process. -const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false'; +const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK === 'true'; +const shouldDisableHasing = process.env.DISABLE_ASSET_HASHING === 'true'; +const shouldEmit = process.env.EMIT === 'true'; +const shouldAddAnalyzer = process.env.ANALYZE === 'true'; const imageInlineSizeLimit = parseInt( process.env.IMAGE_INLINE_SIZE_LIMIT || '10000' @@ -67,6 +74,77 @@ const cssModuleRegex = /\.module\.css$/; const sassRegex = /\.(scss|sass)$/; const sassModuleRegex = /\.module\.(scss|sass)$/; +const workspacesConfig = yarnWorkspaces.init(paths); + +function getHtmlPlugins(isEnvProduction) { + return paths.appPages + .map( + appPage => + appPage.appHtml && + new HtmlWebpackPlugin( + Object.assign( + {}, + { + inject: true, + template: appPage.appHtml, + filename: `${appPage.name}.html`, + title: appPage.title, + chunks: [appPage.name], + }, + isEnvProduction + ? { + minify: { + removeComments: true, + collapseWhitespace: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + removeStyleLinkTypeAttributes: true, + keepClosingSlash: true, + minifyJS: true, + minifyCSS: true, + minifyURLs: true, + }, + } + : undefined + ) + ) + ) + .filter(Boolean); +} + +function getEntries(isEnvDevelopment, shouldUseReactRefresh) { + return paths.appPages.reduce((entries, appPage) => { + entries[appPage.name] = + isEnvDevelopment && !shouldUseReactRefresh && !shouldEmit + ? [ + // Include an alternative client for WebpackDevServer. A client's job is to + // connect to WebpackDevServer by a socket and get notified about changes. + // When you save a file, the client will either apply hot updates (in case + // of CSS changes), or refresh the page (in case of JS changes). When you + // make a syntax error, this client will display a syntax error overlay. + // Note: instead of the default WebpackDevServer client, we use a custom one + // to bring better experience for Create React App users. You can replace + // the line below with these two lines if you prefer the stock client: + // + // require.resolve('webpack-dev-server/client') + '?/', + // require.resolve('webpack/hot/dev-server'), + // + // When using the experimental react-refresh integration, + // the webpack plugin takes care of injecting the dev client for us. + webpackDevClientEntry, + // Finally, this is your app's code: + appPage.appIndexJs, + // We include the app code last so that if there is a runtime error during + // initialization, it doesn't blow up the WebpackDevServer client, and + // changing JS code would still trigger a refresh. + ] + : [appPage.appIndexJs]; + + return entries; + }, {}); +} + // This is the production and development configuration. // It is focused on developer experience, fast rebuilds, and a minimal bundle. module.exports = function (webpackEnv) { @@ -78,6 +156,30 @@ module.exports = function (webpackEnv) { const isEnvProductionProfile = isEnvProduction && process.argv.includes('--profile'); + const workspacesMainFields = [ + workspacesConfig.packageEntry, + 'browser', + 'module', + 'main', + ]; + + const mainFields = + isEnvDevelopment && workspacesConfig.development + ? workspacesMainFields + : isEnvProduction && workspacesConfig.production + ? workspacesMainFields + : undefined; + + const includePaths = + isEnvDevelopment && workspacesConfig.development + ? [paths.appSrc, ...workspacesConfig.paths] + : isEnvProduction && workspacesConfig.production + ? [paths.appSrc, ...workspacesConfig.paths] + : paths.appSrc; + + const htmlPlugins = getHtmlPlugins(isEnvProduction); + const entries = getEntries(isEnvDevelopment, shouldUseReactRefresh); + // We will provide `paths.publicUrlOrPath` to our app // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz. @@ -159,59 +261,39 @@ module.exports = function (webpackEnv) { : isEnvDevelopment && 'cheap-module-source-map', // These are the "entry points" to our application. // This means they will be the "root" imports that are included in JS bundle. - entry: - isEnvDevelopment && !shouldUseReactRefresh - ? [ - // Include an alternative client for WebpackDevServer. A client's job is to - // connect to WebpackDevServer by a socket and get notified about changes. - // When you save a file, the client will either apply hot updates (in case - // of CSS changes), or refresh the page (in case of JS changes). When you - // make a syntax error, this client will display a syntax error overlay. - // Note: instead of the default WebpackDevServer client, we use a custom one - // to bring better experience for Create React App users. You can replace - // the line below with these two lines if you prefer the stock client: - // - // require.resolve('webpack-dev-server/client') + '?/', - // require.resolve('webpack/hot/dev-server'), - // - // When using the experimental react-refresh integration, - // the webpack plugin takes care of injecting the dev client for us. - webpackDevClientEntry, - // Finally, this is your app's code: - paths.appIndexJs, - // We include the app code last so that if there is a runtime error during - // initialization, it doesn't blow up the WebpackDevServer client, and - // changing JS code would still trigger a refresh. - ] - : paths.appIndexJs, + entry: entries, output: { // The build folder. - path: isEnvProduction ? paths.appBuild : undefined, + path: isEnvProduction || shouldEmit ? paths.appBuild : undefined, // Add /* filename */ comments to generated require()s in the output. pathinfo: isEnvDevelopment, // There will be one main bundle, and one file per asynchronous chunk. // In development, it does not produce real files. filename: isEnvProduction - ? 'static/js/[name].[contenthash:8].js' - : isEnvDevelopment && 'static/js/bundle.js', + ? shouldDisableHasing + ? '[name].js' + : '[name].[contenthash:8].js' + : isEnvDevelopment && '[name].js', // TODO: remove this when upgrading to webpack 5 futureEmitAssets: true, // There are also additional JS chunk files if you use code splitting. chunkFilename: isEnvProduction - ? 'static/js/[name].[contenthash:8].chunk.js' - : isEnvDevelopment && 'static/js/[name].chunk.js', + ? '[name].[contenthash:8].chunk.js' + : isEnvDevelopment && '[name].chunk.js', // webpack uses `publicPath` to determine where the app is being served from. // It requires a trailing slash, or the file assets will get an incorrect path. // We inferred the "public path" (such as / or /my-project) from homepage. publicPath: paths.publicUrlOrPath, // Point sourcemap entries to original disk location (format as URL on Windows) - devtoolModuleFilenameTemplate: isEnvProduction - ? info => - path - .relative(paths.appSrc, info.absoluteResourcePath) - .replace(/\\/g, '/') - : isEnvDevelopment && - (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')), + devtoolModuleFilenameTemplate: + isEnvProduction || shouldEmit + ? info => + path + .relative(paths.appSrc, info.absoluteResourcePath) + .replace(/\\/g, '/') + : isEnvDevelopment && + (info => + path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')), // Prevents conflicts when multiple webpack runtimes (from different apps) // are used on the same page. jsonpFunction: `webpackJsonp${appPackageJson.name}`, @@ -286,16 +368,20 @@ module.exports = function (webpackEnv) { // Automatically split vendor and commons // https://twitter.com/wSokra/status/969633336732905474 // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 - splitChunks: { - chunks: 'all', - name: false, - }, + splitChunks: shouldDisableHasing + ? undefined + : { + chunks: 'all', + name: false, + }, // Keep the runtime chunk separated to enable long term caching // https://twitter.com/wSokra/status/969679223278505985 // https://github.com/facebook/create-react-app/issues/5358 - runtimeChunk: { - name: entrypoint => `runtime-${entrypoint.name}`, - }, + runtimeChunk: shouldDisableHasing + ? false + : { + name: entrypoint => `runtime-${entrypoint.name}`, + }, }, resolve: { // This allows you to set a fallback for where webpack should look for modules. @@ -314,6 +400,7 @@ module.exports = function (webpackEnv) { extensions: paths.moduleFileExtensions .map(ext => `.${ext}`) .filter(ext => useTypeScript || !ext.includes('ts')), + mainFields, alias: { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ @@ -334,7 +421,10 @@ module.exports = function (webpackEnv) { // To fix this, we prevent you from importing files out of src/ -- if you'd like to, // please link the files into your node_modules/ and let module-resolution kick in. // Make sure your source files are compiled, as they will not be processed in any way. - new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), + new ModuleScopePlugin( + [paths.appSrc, paths.appPublic], + [paths.appPackageJson] + ), ], }, resolveLoader: { @@ -366,7 +456,13 @@ module.exports = function (webpackEnv) { loader: require.resolve('eslint-loader'), }, ], - include: paths.appSrc, + include: includePaths, + // Don't lint typescript files outside the main package because it has problems with some syntax rules, e.g. abstract + exclude: useTypeScript + ? file => + /\.tsx?/.test(path.extname(file)) && + !file.startsWith(paths.appSrc) + : undefined, }, { // "oneOf" will traverse all following loaders until one will @@ -381,23 +477,23 @@ module.exports = function (webpackEnv) { loader: require.resolve('url-loader'), options: { limit: imageInlineSizeLimit, - name: 'static/media/[name].[hash:8].[ext]', + name: '[name].[hash:8].[ext]', }, }, // Process application JS with Babel. // The preset includes JSX, Flow, TypeScript, and some ESnext features. { test: /\.(js|mjs|jsx|ts|tsx)$/, - include: paths.appSrc, + include: includePaths, loader: require.resolve('babel-loader'), options: { customize: require.resolve( - 'babel-preset-react-app/webpack-overrides' + '@foreachbe/babel-preset-react-app/webpack-overrides' ), // @remove-on-eject-begin babelrc: false, configFile: false, - presets: [require.resolve('babel-preset-react-app')], + presets: [require.resolve('@foreachbe/babel-preset-react-app')], // Make sure we have a unique cache identifier, erring on the // side of caution. // We remove this when the user ejects because the default @@ -452,7 +548,9 @@ module.exports = function (webpackEnv) { compact: false, presets: [ [ - require.resolve('babel-preset-react-app/dependencies'), + require.resolve( + '@foreachbe/babel-preset-react-app/dependencies' + ), { helpers: true }, ], ], @@ -566,7 +664,7 @@ module.exports = function (webpackEnv) { // by webpacks internal loaders. exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/], options: { - name: 'static/media/[name].[hash:8].[ext]', + name: '[name].[hash:8].[ext]', }, }, // ** STOP ** Are you adding a new loader? @@ -577,31 +675,13 @@ module.exports = function (webpackEnv) { }, plugins: [ // Generates an `index.html` file with the <script> injected. - new HtmlWebpackPlugin( - Object.assign( - {}, - { - inject: true, - template: paths.appHtml, - }, - isEnvProduction - ? { - minify: { - removeComments: true, - collapseWhitespace: true, - removeRedundantAttributes: true, - useShortDoctype: true, - removeEmptyAttributes: true, - removeStyleLinkTypeAttributes: true, - keepClosingSlash: true, - minifyJS: true, - minifyCSS: true, - minifyURLs: true, - }, - } - : undefined - ) - ), + ...htmlPlugins, + fs.existsSync(paths.appStylelintConfig) && + new StyleLintPlugin({ + files: '**/*.(s(c|a)ss|css)', + configFile: paths.appStylelintConfig, + emitErrors: isEnvProduction, + }), // Inlines the webpack runtime script. This script is too small to warrant // a network request. // https://github.com/facebook/create-react-app/issues/5358 @@ -654,8 +734,10 @@ module.exports = function (webpackEnv) { new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional - filename: 'static/css/[name].[contenthash:8].css', - chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', + filename: shouldDisableHasing + ? '[name].css' + : '[name].[contenthash:8].css', + chunkFilename: '[name].[contenthash:8].chunk.css', }), // Generate an asset manifest file with the following content: // - "files" key: Mapping of all asset filenames to their corresponding @@ -671,9 +753,15 @@ module.exports = function (webpackEnv) { manifest[file.name] = file.path; return manifest; }, seed); - const entrypointFiles = entrypoints.main.filter( - fileName => !fileName.endsWith('.map') - ); + + let entrypointFiles = []; + + for (let [, fileName] of Object.entries(entrypoints)) { + let notMapFiles = fileName.filter( + fileName => !fileName.endsWith('.map') + ); + entrypointFiles = entrypointFiles.concat(notMapFiles); + } return { files: manifestFiles, @@ -723,10 +811,12 @@ module.exports = function (webpackEnv) { '!**/src/setupProxy.*', '!**/src/setupTests.*', ], + watch: includePaths, silent: true, // The formatter is invoked directly in WebpackDevServerUtils during development formatter: isEnvProduction ? typescriptFormatter : undefined, }), + shouldAddAnalyzer && new BundleAnalyzerPlugin(), ].filter(Boolean), // Some libraries import Node modules but don't use them in the browser. // Tell webpack to provide empty mocks for them so importing them works. diff --git a/packages/react-scripts/config/yarn-workspaces.js b/packages/react-scripts/config/yarn-workspaces.js new file mode 100644 index 000000000..32b5746f8 --- /dev/null +++ b/packages/react-scripts/config/yarn-workspaces.js @@ -0,0 +1,277 @@ +'use strict'; + +const fse = require('fs-extra'); +const path = require('path'); +const findUp = require('find-up'); +const glob = require('glob'); + +const loadPackageJson = packagePath => { + const packageObj = fse.readJsonSync(packagePath); + return packageObj; +}; + +const getWorkspacesRootConfig = dir => { + const packageJsonUp = findUp.sync('package.json', { cwd: dir }); + + if (packageJsonUp === null) { + return false; + } + + const packageObj = loadPackageJson(packageJsonUp); + + if ( + packageObj.workspaces && + (Array.isArray(packageObj.workspaces) || + Reflect.has(packageObj.workspaces, 'packages')) + ) { + const workspacesRootConfig = { + root: path.dirname(packageJsonUp), + workspaces: packageObj.workspaces, + }; + return workspacesRootConfig; + } + + const dirUp = path.dirname(dir); + return getWorkspacesRootConfig(dirUp); +}; + +const getPackagePaths = (root, workspacesList) => { + const packageList = []; + + workspacesList.forEach(workspace => { + const workspaceDir = path.dirname(workspace); + const workspaceAbsDir = path.join(root, workspaceDir); + const packageJsonGlob = path.join('**!(node_modules)', 'package.json'); + const packageJsonAbsPaths = glob + .sync(packageJsonGlob, { cwd: workspaceAbsDir }) + .map(pkgPath => path.join(workspaceAbsDir, pkgPath)); + + packageList.push(...packageJsonAbsPaths); + }); + + return packageList; +}; + +const getDeep = (obj, keyChain) => { + const nextKey = keyChain.shift(); + const has = Reflect.has(obj, nextKey); + const val = obj[nextKey]; + + if (keyChain.length === 0) { + return val; + } + + if (has) { + return getDeep(val, keyChain); + } + + return false; +}; + +const resolveBabelLoaderPaths = ({ root, workspacesList }, packageEntry) => { + const packageJsonPaths = getPackagePaths(root, workspacesList); + const babelLoaderPaths = []; + + packageJsonPaths.map(absPkgPath => { + const packageJson = loadPackageJson(absPkgPath); + const mainSrcFile = getDeep(packageJson, [packageEntry]); + + if (mainSrcFile) { + const mainSrcPath = path.dirname(mainSrcFile); + const packageAbsDir = path.dirname(absPkgPath); + const absSrcPath = path.join(packageAbsDir, mainSrcPath); + babelLoaderPaths.push(absSrcPath); + } + }); + + return babelLoaderPaths; +}; + +const loadAppSettings = appPackageJson => { + const result = { workspaces: {}, dependencies: {} }; + + const appPackageObj = loadPackageJson(appPackageJson); + + const dependencies = getDeep(appPackageObj, ['dependencies']); + const devDependencies = getDeep(appPackageObj, ['devDependencies']); + + if (!dependencies && !devDependencies) { + return result; + } + + if (dependencies) { + result.dependencies = Object.assign(result.dependencies, dependencies); + } + + if (devDependencies) { + result.dependencies = Object.assign(result.dependencies, devDependencies); + } + + const reactScripts = getDeep(appPackageObj, ['react-scripts']); + if (!reactScripts) { + return result; + } + + const workspaces = getDeep(reactScripts, ['workspaces']); + result.workspaces = workspaces; + if (!workspaces) { + return result; + } + + return workspaces; +}; + +const guard = (appDirectory, appPackageJson) => { + if (!appDirectory) { + throw new Error('appDirectory not provided'); + } + + if (typeof appDirectory !== 'string') { + throw new Error('appDirectory should be a string'); + } + + if (!appPackageJson) { + throw new Error('appPackageJson not provided'); + } + + if (typeof appPackageJson !== 'string') { + throw new Error('appPackageJson should be a string'); + } +}; + +const getPkg = path => { + const pkgPath = findUp.sync('package.json', { cwd: path }); + const pkg = loadPackageJson(pkgPath); + return pkg; +}; + +const getDeps = pkg => { + const deps = getDeep(pkg, ['dependencies']); + const devDeps = getDeep(pkg, ['devDependencies']); + + let dependencies = {}; + + if (deps) { + dependencies = Object.assign(dependencies, deps); + } + + if (devDeps) { + dependencies = Object.assign(dependencies, devDeps); + } + + return dependencies; +}; + +const depsTable = {}; + +const buildDepsTable = srcPaths => { + srcPaths.forEach(path => { + const pkg = getPkg(path); + const name = pkg.name; + const deps = getDeps(pkg); + depsTable[name] = { path, deps }; + }); +}; + +const filterSrcPaths = (srcPaths, dependencies) => { + const filteredPaths = []; + + srcPaths.forEach(path => { + const pkg = getPkg(path); + + if (dependencies && Reflect.has(dependencies, pkg.name)) { + filteredPaths.push(path); + + const subDeps = depsTable[pkg.name].deps; + const subPaths = filterSrcPaths(srcPaths, subDeps); + filteredPaths.push(...subPaths); + } + }); + + return filteredPaths; +}; + +const init = paths => { + guard(paths.appPath, paths.appPackageJson); + + const config = { + root: null, + paths: [], + packageEntry: 'main:src', + development: true, + production: true, + }; + + try { + const { root, workspaces } = getWorkspacesRootConfig(paths.appPath); + + const workspacesList = []; + + // Normally "workspaces" in package.json is an array + if (Array.isArray(workspaces)) { + workspacesList.push(...workspaces); + } + + // Sometimes "workspaces" in package.json is an object + // with a ".packages" sub-array, eg: when used with "nohoist" + // See: https://yarnpkg.com/blog/2018/02/15/nohoist + if ( + workspaces && + !Array.isArray(workspaces) && + Reflect.has(workspaces, 'packages') + ) { + workspacesList.push(...workspaces.packages); + } + + if (workspacesList.length === 0) { + return config; + } + console.log('Yarn Workspaces paths detected.'); + config.root = root; + + const appSettings = loadAppSettings(paths.appPackageJson); + + if (Reflect.has(appSettings.workspaces, 'development')) { + config.development = appSettings.workspaces.development ? true : false; + } + + if (Reflect.has(appSettings.workspaces, 'production')) { + config.production = appSettings.workspaces.production ? true : false; + } + + if (Reflect.has(appSettings.workspaces, 'package-entry')) { + config.packageEntry = appSettings.workspaces['package-entry']; + } + + const babelSrcPaths = resolveBabelLoaderPaths( + { root, workspacesList }, + config.packageEntry + ); + + buildDepsTable(babelSrcPaths); + + const applicableSrcPaths = [ + ...new Set(filterSrcPaths(babelSrcPaths, appSettings.dependencies)), + ]; + + console.log( + `Found ${babelSrcPaths.length} path(s) with "${config.packageEntry}" entry.` + ); + + if (applicableSrcPaths.length > 0) { + config.paths.push(...applicableSrcPaths); + } + + console.log('Exporting Workspaces config to Webpack.'); + console.log(config); + return config; + } catch (err) { + config.development = false; + config.production = false; + return config; + } +}; + +module.exports = { + init, +}; diff --git a/packages/react-scripts/fixtures/kitchensink/template/jest.transform.js b/packages/react-scripts/fixtures/kitchensink/template/jest.transform.js index 247f1081b..3e982bf3f 100644 --- a/packages/react-scripts/fixtures/kitchensink/template/jest.transform.js +++ b/packages/react-scripts/fixtures/kitchensink/template/jest.transform.js @@ -1,3 +1,3 @@ -const babelOptions = { presets: ['react-app'] }; +const babelOptions = { presets: ['@foreachbe/babel-preset-react-app'] }; module.exports = require('babel-jest').createTransformer(babelOptions); diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 8f696c01a..14282d4b8 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,10 +1,10 @@ { - "name": "react-scripts", - "version": "3.4.1", + "name": "@foreachbe/react-scripts", + "version": "6.1.0", "description": "Configuration and scripts for Create React App.", "repository": { "type": "git", - "url": "https://github.com/facebook/create-react-app.git", + "url": "https://github.com/foreachos/create-react-app.git", "directory": "packages/react-scripts" }, "license": "MIT", @@ -12,7 +12,7 @@ "node": "^10.12.0 || >=12.0.0" }, "bugs": { - "url": "https://github.com/facebook/create-react-app/issues" + "url": "https://github.com/foreachos/create-react-app/issues" }, "files": [ "bin", @@ -29,6 +29,8 @@ "types": "./lib/react-app.d.ts", "dependencies": { "@babel/core": "7.10.5", + "@foreachbe/babel-preset-react-app": "^5.0.0", + "@foreachbe/stylelint-config-react-app": "^4.0.0", "@pmmmwh/react-refresh-webpack-plugin": "0.4.1", "@svgr/webpack": "5.4.0", "@typescript-eslint/eslint-plugin": "^4.1.0", @@ -39,6 +41,7 @@ "babel-plugin-named-asset-import": "^0.3.6", "babel-preset-react-app": "^9.1.2", "bfj": "^7.0.2", + "browser-sync": "2.26.12", "camelcase": "^6.0.0", "case-sensitive-paths-webpack-plugin": "2.3.0", "css-loader": "3.6.0", @@ -54,10 +57,12 @@ "eslint-plugin-react": "^7.20.6", "eslint-plugin-react-hooks": "^4.1.2", "file-loader": "6.0.0", + "find-up": "5.0.0", "fs-extra": "^9.0.0", "html-webpack-plugin": "4.3.0", "identity-obj-proxy": "3.0.0", "jest": "26.3.0", + "jest-bamboo-reporter": "^1.2.1", "jest-circus": "26.3.0", "jest-resolve": "26.3.0", "jest-watch-typeahead": "0.6.0", @@ -77,10 +82,13 @@ "sass-loader": "8.0.2", "semver": "7.3.2", "style-loader": "1.2.1", + "stylelint": "^13.7.1", + "stylelint-webpack-plugin": "^2.1.0", "terser-webpack-plugin": "3.0.7", "ts-pnp": "1.2.0", "url-loader": "4.1.0", "webpack": "4.43.0", + "webpack-bundle-analyzer": "3.8.0", "webpack-dev-server": "3.11.0", "webpack-manifest-plugin": "2.2.0", "workbox-webpack-plugin": "5.1.3" diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js index de2ff505e..5b213372a 100644 --- a/packages/react-scripts/scripts/build.js +++ b/packages/react-scripts/scripts/build.js @@ -56,9 +56,14 @@ const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024; const isInteractive = process.stdout.isTTY; // Warn and crash if required files are missing -if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { - process.exit(1); -} + +paths.appPages.forEach(appPage => { + if ( + !checkRequiredFiles([appPage.appHtml, appPage.appIndexJs].filter(Boolean)) + ) { + process.exit(1); + } +}); const argv = process.argv.slice(2); const writeStatsJson = argv.indexOf('--stats') !== -1; @@ -221,8 +226,10 @@ function build(previousFileSizes) { } function copyPublicFolder() { + const htmlPages = paths.appPages.map(a => a.appHtml); + fs.copySync(paths.appPublic, paths.appBuild, { dereference: true, - filter: file => file !== paths.appHtml, + filter: file => !htmlPages.includes(file), }); } diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index ffbb15d12..899f6c1fa 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -37,6 +37,9 @@ const webpack = require('webpack'); const WebpackDevServer = require('webpack-dev-server'); const clearConsole = require('react-dev-utils/clearConsole'); const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); +const ignoredFiles = require('react-dev-utils/ignoredFiles'); +const browserSync = require('browser-sync').create(); + const { choosePort, createCompiler, @@ -55,14 +58,20 @@ const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); const useYarn = fs.existsSync(paths.yarnLockFile); const isInteractive = process.stdout.isTTY; -// Warn and crash if required files are missing -if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { - process.exit(1); -} +paths.appPages.forEach(appPage => { + if ( + !checkRequiredFiles([appPage.appHtml, appPage.appIndexJs].filter(Boolean)) + ) { + process.exit(1); + } +}); // Tools like Cloud9 rely on this. const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; const HOST = process.env.HOST || '0.0.0.0'; +const PROXY_URL = process.env.PROXY_URL; +const BACKEND_PORT = process.env.BACKEND_PORT || 8099; +const EMIT = process.env.EMIT === 'true'; if (process.env.HOST) { console.log( @@ -110,9 +119,11 @@ checkBrowsers(paths.appPath, isInteractive) ); const devSocket = { warnings: warnings => - devServer.sockWrite(devServer.sockets, 'warnings', warnings), + EMIT + ? {} + : devServer.sockWrite(devServer.sockets, 'warnings', warnings), errors: errors => - devServer.sockWrite(devServer.sockets, 'errors', errors), + EMIT ? {} : devServer.sockWrite(devServer.sockets, 'errors', errors), }; // Create a webpack compiler that is configured with custom messages. const compiler = createCompiler({ @@ -125,54 +136,90 @@ checkBrowsers(paths.appPath, isInteractive) tscCompileOnError, webpack, }); - // Load proxy config - const proxySetting = require(paths.appPackageJson).proxy; - const proxyConfig = prepareProxy( - proxySetting, - paths.appPublic, - paths.publicUrlOrPath - ); - // Serve webpack assets generated by the compiler over a web server. - const serverConfig = createDevServerConfig( - proxyConfig, - urls.lanUrlForConfig - ); - const devServer = new WebpackDevServer(compiler, serverConfig); - // Launch WebpackDevServer. - devServer.listen(port, HOST, err => { - if (err) { - return console.log(err); - } - if (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}.` - ) - ); - } + + let devServer; + + if (EMIT) { + const proxy = PROXY_URL ? PROXY_URL : `localhost:${BACKEND_PORT}`; + browserSync.init({ port, proxy: { target: proxy, ws: true } }); + + const watching = compiler.watch( + { + ignored: ignoredFiles(paths.appSrc), + }, + err => { + if (err) { + return console.log(err); + } + if (isInteractive) { + clearConsole(); + } + + browserSync.reload(); + } + ); console.log(chalk.cyan('Starting the development server...\n')); - openBrowser(urls.localUrlForBrowser); - }); - ['SIGINT', 'SIGTERM'].forEach(function (sig) { - process.on(sig, function () { - devServer.close(); - process.exit(); + ['SIGINT', 'SIGTERM'].forEach(function (sig) { + process.on(sig, function () { + watching.close(); + browserSync.exit(); + process.exit(); + }); }); - }); + } else { + // Load proxy config + const proxySetting = require(paths.appPackageJson).proxy; + const proxyConfig = prepareProxy( + proxySetting, + paths.appPublic, + paths.publicUrlOrPath + ); + // Serve webpack assets generated by the compiler over a web server. + const serverConfig = createDevServerConfig( + proxyConfig, + urls.lanUrlForConfig + ); + devServer = new WebpackDevServer(compiler, serverConfig); + // Launch WebpackDevServer. + devServer.listen(port, HOST, err => { + if (err) { + return console.log(err); + } + if (isInteractive) { + clearConsole(); + } - if (process.env.CI !== 'true') { - // Gracefully exit when stdin ends - process.stdin.on('end', function () { - devServer.close(); - process.exit(); + 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); + + ['SIGINT', 'SIGTERM'].forEach(function (sig) { + process.on(sig, function () { + devServer.close(); + process.exit(); + }); + }); + + if (process.env.CI !== 'true') { + // Gracefully exit when stdin ends + process.stdin.on('end', function () { + devServer.close(); + process.exit(); + }); + } }); } + + process.stdin.resume(); }) .catch(err => { if (err && err.message) { diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js index 78a63571b..dd505fd00 100644 --- a/packages/react-scripts/scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -53,6 +53,7 @@ module.exports = (resolve, rootDir, isEjecting) => { '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$', '^.+\\.module\\.(css|sass|scss)$', ], + testResultsProcessor: require.resolve('jest-bamboo-reporter'), modulePaths: modules.additionalModulePaths || [], moduleNameMapper: { '^react-native$': 'react-native-web', @@ -66,6 +67,10 @@ module.exports = (resolve, rootDir, isEjecting) => { 'jest-watch-typeahead/filename', 'jest-watch-typeahead/testname', ], + watchPathIgnorePatterns: [ + '<rootDir>/test-report.json', + '<rootDir>/test-output/test-report.json', + ], resetMocks: true, }; if (rootDir) { @@ -91,6 +96,8 @@ module.exports = (resolve, rootDir, isEjecting) => { 'transform', 'transformIgnorePatterns', 'watchPathIgnorePatterns', + 'testResultsProcessor', + 'roots', ]; if (overrides) { supportedKeys.forEach(key => { diff --git a/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js b/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js index 6a1f2c625..51626d09f 100644 --- a/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js +++ b/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js @@ -103,6 +103,7 @@ function verifyTypeScriptSetup() { // These are suggested values and will be set when not present in the // tsconfig.json // 'parsedValue' matches the output value from ts.parseJsonConfigFileContent() + baseUrl: { suggested: 'src' }, target: { parsedValue: ts.ScriptTarget.ES5, suggested: 'es5', @@ -130,12 +131,12 @@ function verifyTypeScriptSetup() { }, resolveJsonModule: { value: true, reason: 'to match webpack loader' }, isolatedModules: { value: true, reason: 'implementation limitation' }, - noEmit: { value: true }, + // noEmit: { value: true }, jsx: { parsedValue: ts.JsxEmit.React, suggested: 'react', }, - paths: { value: undefined, reason: 'aliased imports are not supported' }, + // paths: { value: undefined, reason: 'aliased imports are not supported' }, }; const formatDiagnosticHost = { @@ -263,7 +264,7 @@ function verifyTypeScriptSetup() { if (!fs.existsSync(paths.appTypeDeclarations)) { fs.writeFileSync( paths.appTypeDeclarations, - `/// <reference types="react-scripts" />${os.EOL}` + `/// <reference types="@foreachbe/react-scripts" />${os.EOL}` ); } } diff --git a/packages/stylelint-config-react-app/index.js b/packages/stylelint-config-react-app/index.js new file mode 100644 index 000000000..fd4a4a8a7 --- /dev/null +++ b/packages/stylelint-config-react-app/index.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = { + plugins: ['stylelint-scss'], + extends: ['stylelint-config-recommended-scss', 'stylelint-config-prettier'], +}; diff --git a/packages/stylelint-config-react-app/package.json b/packages/stylelint-config-react-app/package.json new file mode 100644 index 000000000..21ecab1f3 --- /dev/null +++ b/packages/stylelint-config-react-app/package.json @@ -0,0 +1,26 @@ +{ + "name": "@foreachbe/stylelint-config-react-app", + "version": "4.0.0", + "description": "Stylint configuration used by Foreach", + "main": "index.js", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, + "files": [ + "index.js" + ], + "dependencies": { + "stylelint-config-prettier": "^8.0.2", + "stylelint-config-recommended-scss": "4.2.0", + "stylelint-scss": "^3.18.0" + }, + "peerDependencies": { + "stylelint": "13.x" + }, + "devDependencies": { + "stylelint": "13.7.1" + }, + "author": "Simon Van den Broeck", + "license": "MIT" +} -- GitLab From 61dab8672c92065c1c97b10e8572c7b3f12660c6 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 17:46:50 +0200 Subject: [PATCH 04/12] Enter prerelease mode and version packages --- .changeset/pre.json | 19 +++++++++++++++++++ .changeset/quick-rabbits-wash.md | 7 +++++++ packages/babel-preset-react-app/CHANGELOG.md | 7 +++++++ packages/babel-preset-react-app/package.json | 2 +- packages/react-scripts/CHANGELOG.md | 13 +++++++++++++ packages/react-scripts/package.json | 6 +++--- .../stylelint-config-react-app/CHANGELOG.md | 7 +++++++ .../stylelint-config-react-app/package.json | 2 +- 8 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 .changeset/pre.json create mode 100644 .changeset/quick-rabbits-wash.md create mode 100644 packages/babel-preset-react-app/CHANGELOG.md create mode 100644 packages/react-scripts/CHANGELOG.md create mode 100644 packages/stylelint-config-react-app/CHANGELOG.md diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..dfa874daa --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,19 @@ +{ + "mode": "pre", + "tag": "beta", + "initialVersions": { + "babel-plugin-named-asset-import": "0.3.6", + "@foreachbe/babel-preset-react-app": "5.0.0", + "confusing-browser-globals": "1.0.9", + "cra-template": "1.0.3", + "cra-template-typescript": "1.0.3", + "create-react-app": "3.4.1", + "eslint-config-react-app": "5.2.1", + "react-app-polyfill": "1.0.6", + "react-dev-utils": "10.2.1", + "react-error-overlay": "6.0.7", + "@foreachbe/react-scripts": "6.1.0", + "@foreachbe/stylelint-config-react-app": "4.0.0" + }, + "changesets": ["quick-rabbits-wash"] +} diff --git a/.changeset/quick-rabbits-wash.md b/.changeset/quick-rabbits-wash.md new file mode 100644 index 000000000..ef19b016e --- /dev/null +++ b/.changeset/quick-rabbits-wash.md @@ -0,0 +1,7 @@ +--- +'@foreachbe/babel-preset-react-app': minor +'@foreachbe/react-scripts': minor +'@foreachbe/stylelint-config-react-app': minor +--- + +Genesis diff --git a/packages/babel-preset-react-app/CHANGELOG.md b/packages/babel-preset-react-app/CHANGELOG.md new file mode 100644 index 000000000..457cd3ff3 --- /dev/null +++ b/packages/babel-preset-react-app/CHANGELOG.md @@ -0,0 +1,7 @@ +# @foreachbe/babel-preset-react-app + +## 5.1.0-beta.0 + +### Minor Changes + +- Genesis diff --git a/packages/babel-preset-react-app/package.json b/packages/babel-preset-react-app/package.json index 733bb5d62..25d5fd770 100644 --- a/packages/babel-preset-react-app/package.json +++ b/packages/babel-preset-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/babel-preset-react-app", - "version": "5.0.0", + "version": "5.1.0-beta.0", "description": "Babel preset used by Create React App", "repository": { "type": "git", diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md new file mode 100644 index 000000000..12d76b7a5 --- /dev/null +++ b/packages/react-scripts/CHANGELOG.md @@ -0,0 +1,13 @@ +# @foreachbe/react-scripts + +## 6.2.0-beta.0 + +### Minor Changes + +- Genesis + +### Patch Changes + +- Updated dependencies [undefined] + - @foreachbe/babel-preset-react-app@5.1.0-beta.0 + - @foreachbe/stylelint-config-react-app@4.1.0-beta.0 diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 14282d4b8..98b97fe1e 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/react-scripts", - "version": "6.1.0", + "version": "6.2.0-beta.0", "description": "Configuration and scripts for Create React App.", "repository": { "type": "git", @@ -29,8 +29,8 @@ "types": "./lib/react-app.d.ts", "dependencies": { "@babel/core": "7.10.5", - "@foreachbe/babel-preset-react-app": "^5.0.0", - "@foreachbe/stylelint-config-react-app": "^4.0.0", + "@foreachbe/babel-preset-react-app": "^5.1.0-beta.0", + "@foreachbe/stylelint-config-react-app": "^4.1.0-beta.0", "@pmmmwh/react-refresh-webpack-plugin": "0.4.1", "@svgr/webpack": "5.4.0", "@typescript-eslint/eslint-plugin": "^4.1.0", diff --git a/packages/stylelint-config-react-app/CHANGELOG.md b/packages/stylelint-config-react-app/CHANGELOG.md new file mode 100644 index 000000000..0d2f202bc --- /dev/null +++ b/packages/stylelint-config-react-app/CHANGELOG.md @@ -0,0 +1,7 @@ +# @foreachbe/stylelint-config-react-app + +## 4.1.0-beta.0 + +### Minor Changes + +- Genesis diff --git a/packages/stylelint-config-react-app/package.json b/packages/stylelint-config-react-app/package.json index 21ecab1f3..0be47e7a4 100644 --- a/packages/stylelint-config-react-app/package.json +++ b/packages/stylelint-config-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/stylelint-config-react-app", - "version": "4.0.0", + "version": "4.1.0-beta.0", "description": "Stylint configuration used by Foreach", "main": "index.js", "publishConfig": { -- GitLab From 32633bc20465af27dc93fa8ff91ab776599598fd Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 17:48:05 +0200 Subject: [PATCH 05/12] fix npm publish --- packages/react-scripts/package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 98b97fe1e..3f1662263 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -7,6 +7,10 @@ "url": "https://github.com/foreachos/create-react-app.git", "directory": "packages/react-scripts" }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, "license": "MIT", "engines": { "node": "^10.12.0 || >=12.0.0" -- GitLab From dfa106018e804ba2947aee29b45ea0d941f3dfd1 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 17:50:11 +0200 Subject: [PATCH 06/12] "Enter prerelease mode and version packages" --- .changeset/pre.json | 2 +- .changeset/rotten-guests-deliver.md | 5 +++++ packages/react-scripts/CHANGELOG.md | 6 ++++++ packages/react-scripts/package.json | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .changeset/rotten-guests-deliver.md diff --git a/.changeset/pre.json b/.changeset/pre.json index dfa874daa..5f6a01279 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -15,5 +15,5 @@ "@foreachbe/react-scripts": "6.1.0", "@foreachbe/stylelint-config-react-app": "4.0.0" }, - "changesets": ["quick-rabbits-wash"] + "changesets": ["quick-rabbits-wash", "rotten-guests-deliver"] } diff --git a/.changeset/rotten-guests-deliver.md b/.changeset/rotten-guests-deliver.md new file mode 100644 index 000000000..7923fc334 --- /dev/null +++ b/.changeset/rotten-guests-deliver.md @@ -0,0 +1,5 @@ +--- +'@foreachbe/react-scripts': patch +--- + +Fix NPM publish diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 12d76b7a5..1ca6391a9 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,11 @@ # @foreachbe/react-scripts +## 6.2.0-beta.1 + +### Patch Changes + +- Fix NPM publish + ## 6.2.0-beta.0 ### Minor Changes diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 3f1662263..1703fce7e 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/react-scripts", - "version": "6.2.0-beta.0", + "version": "6.2.0-beta.1", "description": "Configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From 7b197c4966e26dcbf8aa99041c4ee7820938ea48 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 18:09:54 +0200 Subject: [PATCH 07/12] fix eslint config --- packages/babel-preset-react-app/README.md | 2 +- packages/eslint-config-react-app/README.md | 13 ++++++++----- packages/eslint-config-react-app/index.js | 16 +++++++++++++++- packages/eslint-config-react-app/package.json | 13 ++++++++----- packages/react-scripts/package.json | 2 +- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/packages/babel-preset-react-app/README.md b/packages/babel-preset-react-app/README.md index d80f7fe8e..7a5556450 100644 --- a/packages/babel-preset-react-app/README.md +++ b/packages/babel-preset-react-app/README.md @@ -1,4 +1,4 @@ -# @foreachbe/eslint-config-react-app +# @foreachbe/babel-preset-react-app This package includes the Babel preset used by [Create React App](https://github.com/facebook/create-react-app).<br> Please refer to its documentation: diff --git a/packages/eslint-config-react-app/README.md b/packages/eslint-config-react-app/README.md index ac49d2b73..6e881cd3f 100644 --- a/packages/eslint-config-react-app/README.md +++ b/packages/eslint-config-react-app/README.md @@ -1,4 +1,4 @@ -# eslint-config-react-app +# @foreachbe/eslint-config-react-app This package includes the shareable ESLint configuration used by [Create React App](https://github.com/facebook/create-react-app).<br> Please refer to its documentation: @@ -19,18 +19,18 @@ If you want to use this ESLint configuration in a project not built with Create First, install this package, ESLint and the necessary plugins. ```sh -npm install --save-dev eslint-config-react-app @typescript-eslint/eslint-plugin@^4.0.0 @typescript-eslint/parser@^4.0.0 babel-eslint@^10.0.0 eslint@^7.5.0 eslint-plugin-flowtype@^5.2.0 eslint-plugin-import@^2.22.0 eslint-plugin-jest@^24.0.0 eslint-plugin-jsx-a11y@^6.3.1 eslint-plugin-react@^7.20.3 eslint-plugin-react-hooks@^4.0.8 +npm install --save-dev @foreachbe/eslint-config-react-app @typescript-eslint/eslint-plugin@^4.0.0 @typescript-eslint/parser@^4.0.0 babel-eslint@^10.0.0 eslint@^7.5.0 eslint-plugin-flowtype@^5.2.0 eslint-plugin-import@^2.22.0 eslint-plugin-jest@^24.0.0 eslint-plugin-jsx-a11y@^6.3.1 eslint-plugin-react@^7.20.3 eslint-plugin-react-hooks@^4.0.8 ``` Then create a file named `.eslintrc.json` with following contents in the root folder of your project: ```json { - "extends": "react-app" + "extends": "@foreachbe/eslint-config-react-app" } ``` -That's it! You can override the settings from `eslint-config-react-app` by editing the `.eslintrc.json` file. Learn more about [configuring ESLint](http://eslint.org/docs/user-guide/configuring) on the ESLint website. +That's it! You can override the settings from `@foreachbe/eslint-config-react-app` by editing the `.eslintrc.json` file. Learn more about [configuring ESLint](http://eslint.org/docs/user-guide/configuring) on the ESLint website. ## Jest rules @@ -46,7 +46,10 @@ You can then enable these rules by adding the Jest config to the `extends` array ```json { - "extends": ["react-app", "react-app/jest"] + "extends": [ + "@foreachbe/eslint-config-react-app", + "@foreachbe/eslint-config-react-app/jest" + ] } ``` diff --git a/packages/eslint-config-react-app/index.js b/packages/eslint-config-react-app/index.js index 36538fb73..84d9fce22 100644 --- a/packages/eslint-config-react-app/index.js +++ b/packages/eslint-config-react-app/index.js @@ -106,6 +106,7 @@ module.exports = { { args: 'none', ignoreRestSiblings: true, + varsIgnorePattern: '(jsx|_)', }, ], 'no-useless-constructor': 'off', @@ -255,7 +256,20 @@ module.exports = { 'import/no-amd': 'error', 'import/no-anonymous-default-export': 'warn', 'import/no-webpack-loader-syntax': 'error', - + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: [ + '**/*.test.ts', + '**/*.spec.ts', + '**/*.test.tsx', + '**/*.spec.tsx', + '**/setupTests.ts', + '**/setupTests.tsx', + ], + optionalDependencies: false, + }, + ], // https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules 'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }], 'react/jsx-no-comment-textnodes': 'warn', diff --git a/packages/eslint-config-react-app/package.json b/packages/eslint-config-react-app/package.json index 772e022ee..b174b4578 100644 --- a/packages/eslint-config-react-app/package.json +++ b/packages/eslint-config-react-app/package.json @@ -1,16 +1,19 @@ { - "name": "eslint-config-react-app", - "private": true, - "version": "5.2.1", + "name": "@foreachbe/eslint-config-react-app", + "version": "6.0.0", "description": "ESLint configuration used by Create React App", "repository": { "type": "git", - "url": "https://github.com/facebook/create-react-app.git", + "url": "https://github.com/foreachos/create-react-app.git", "directory": "packages/eslint-config-react-app" }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, "license": "MIT", "bugs": { - "url": "https://github.com/facebook/create-react-app/issues" + "url": "https://github.com/foreachos/create-react-app/issues" }, "files": [ "index.js" diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 1703fce7e..7a2de44d2 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -33,6 +33,7 @@ "types": "./lib/react-app.d.ts", "dependencies": { "@babel/core": "7.10.5", + "@foreachbe/eslint-config-react-app": "^6.0.0", "@foreachbe/babel-preset-react-app": "^5.1.0-beta.0", "@foreachbe/stylelint-config-react-app": "^4.1.0-beta.0", "@pmmmwh/react-refresh-webpack-plugin": "0.4.1", @@ -52,7 +53,6 @@ "dotenv": "8.2.0", "dotenv-expand": "5.1.0", "eslint": "^7.9.0", - "eslint-config-react-app": "^5.2.1", "eslint-loader": "^4.0.2", "eslint-plugin-flowtype": "^5.2.0", "eslint-plugin-import": "^2.22.0", -- GitLab From 8023cbe7eb15440e0a872e70549efed9894e9976 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 18:12:19 +0200 Subject: [PATCH 08/12] Add release notes --- .changeset/great-dolphins-enjoy.md | 7 +++++++ .changeset/pre.json | 9 +++++++-- packages/babel-preset-react-app/CHANGELOG.md | 6 ++++++ packages/babel-preset-react-app/package.json | 2 +- packages/eslint-config-react-app/CHANGELOG.md | 7 +++++++ packages/eslint-config-react-app/package.json | 2 +- packages/react-scripts/CHANGELOG.md | 9 +++++++++ packages/react-scripts/package.json | 6 +++--- 8 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 .changeset/great-dolphins-enjoy.md create mode 100644 packages/eslint-config-react-app/CHANGELOG.md diff --git a/.changeset/great-dolphins-enjoy.md b/.changeset/great-dolphins-enjoy.md new file mode 100644 index 000000000..4878c39b4 --- /dev/null +++ b/.changeset/great-dolphins-enjoy.md @@ -0,0 +1,7 @@ +--- +'@foreachbe/babel-preset-react-app': patch +'@foreachbe/eslint-config-react-app': patch +'@foreachbe/react-scripts': patch +--- + +reuse custom eslint config diff --git a/.changeset/pre.json b/.changeset/pre.json index 5f6a01279..438af2da2 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -13,7 +13,12 @@ "react-dev-utils": "10.2.1", "react-error-overlay": "6.0.7", "@foreachbe/react-scripts": "6.1.0", - "@foreachbe/stylelint-config-react-app": "4.0.0" + "@foreachbe/stylelint-config-react-app": "4.0.0", + "@foreachbe/eslint-config-react-app": "6.0.0" }, - "changesets": ["quick-rabbits-wash", "rotten-guests-deliver"] + "changesets": [ + "great-dolphins-enjoy", + "quick-rabbits-wash", + "rotten-guests-deliver" + ] } diff --git a/packages/babel-preset-react-app/CHANGELOG.md b/packages/babel-preset-react-app/CHANGELOG.md index 457cd3ff3..02554c3df 100644 --- a/packages/babel-preset-react-app/CHANGELOG.md +++ b/packages/babel-preset-react-app/CHANGELOG.md @@ -1,5 +1,11 @@ # @foreachbe/babel-preset-react-app +## 5.1.0-beta.1 + +### Patch Changes + +- reuse custom eslint config + ## 5.1.0-beta.0 ### Minor Changes diff --git a/packages/babel-preset-react-app/package.json b/packages/babel-preset-react-app/package.json index 25d5fd770..e3fe0eadc 100644 --- a/packages/babel-preset-react-app/package.json +++ b/packages/babel-preset-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/babel-preset-react-app", - "version": "5.1.0-beta.0", + "version": "5.1.0-beta.1", "description": "Babel preset used by Create React App", "repository": { "type": "git", diff --git a/packages/eslint-config-react-app/CHANGELOG.md b/packages/eslint-config-react-app/CHANGELOG.md new file mode 100644 index 000000000..3ddceb0c8 --- /dev/null +++ b/packages/eslint-config-react-app/CHANGELOG.md @@ -0,0 +1,7 @@ +# @foreachbe/eslint-config-react-app + +## 6.0.1-beta.0 + +### Patch Changes + +- reuse custom eslint config diff --git a/packages/eslint-config-react-app/package.json b/packages/eslint-config-react-app/package.json index b174b4578..41a540d5d 100644 --- a/packages/eslint-config-react-app/package.json +++ b/packages/eslint-config-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/eslint-config-react-app", - "version": "6.0.0", + "version": "6.0.1-beta.0", "description": "ESLint configuration used by Create React App", "repository": { "type": "git", diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 1ca6391a9..9a2706792 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,14 @@ # @foreachbe/react-scripts +## 6.2.0-beta.2 + +### Patch Changes + +- reuse custom eslint config +- Updated dependencies [undefined] + - @foreachbe/babel-preset-react-app@5.1.0-beta.1 + - @foreachbe/eslint-config-react-app@6.0.1-beta.0 + ## 6.2.0-beta.1 ### Patch Changes diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 7a2de44d2..28c35a201 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/react-scripts", - "version": "6.2.0-beta.1", + "version": "6.2.0-beta.2", "description": "Configuration and scripts for Create React App.", "repository": { "type": "git", @@ -33,8 +33,8 @@ "types": "./lib/react-app.d.ts", "dependencies": { "@babel/core": "7.10.5", - "@foreachbe/eslint-config-react-app": "^6.0.0", - "@foreachbe/babel-preset-react-app": "^5.1.0-beta.0", + "@foreachbe/eslint-config-react-app": "^6.0.1-beta.0", + "@foreachbe/babel-preset-react-app": "^5.1.0-beta.1", "@foreachbe/stylelint-config-react-app": "^4.1.0-beta.0", "@pmmmwh/react-refresh-webpack-plugin": "0.4.1", "@svgr/webpack": "5.4.0", -- GitLab From b213e81c9f6ed49cd8aac269f70801568fcab4a2 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 18:27:31 +0200 Subject: [PATCH 09/12] fix compil error --- packages/react-scripts/config/paths.js | 44 ++++++++++++-------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index a99782b4e..14df1b25d 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -18,28 +18,6 @@ const findUp = require('find-up'); const appDirectory = fs.realpathSync(process.cwd()); const resolveApp = relativePath => path.resolve(appDirectory, relativePath); -function getAppPages() { - const appPages = require(resolveApp('package.json')).appPages || []; - // checks if there is at least one entry point specified - - if (appPages.length === 0) { - appPages.push({ - name: 'index', - title: 'index', - appHtml: 'public/index.html', - appIndexJs: 'src/index', - }); - } - - return appPages.map(p => ({ - ...p, - appHtml: p.appHtml && resolveApp(p.appHtml), - appIndexJs: resolveModule(resolveApp, p.appIndexJs), - })); -} - -const appPages = getAppPages(); - // We use `PUBLIC_URL` environment variable or "homepage" field to infer // "public path" at which the app is served. // webpack needs to know it to put the right <script> hrefs into HTML even in @@ -81,7 +59,27 @@ const resolveModule = (resolveFn, filePath) => { const outputPath = process.env.OUTPUT || 'build'; -//TODO add appStylelintConfig +function getAppPages() { + const appPages = require(resolveApp('package.json')).appPages || []; + // checks if there is at least one entry point specified + + if (appPages.length === 0) { + appPages.push({ + name: 'index', + title: 'index', + appHtml: 'public/index.html', + appIndexJs: 'src/index', + }); + } + + return appPages.map(p => ({ + ...p, + appHtml: p.appHtml && resolveApp(p.appHtml), + appIndexJs: resolveModule(resolveApp, p.appIndexJs), + })); +} + +const appPages = getAppPages(); // config after eject: we're in ./config/ module.exports = { -- GitLab From afef45e225e80cb1d6acbc5089317ab57d7e1ba5 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 18:28:09 +0200 Subject: [PATCH 10/12] add Changelog --- .changeset/twenty-roses-yell.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/twenty-roses-yell.md diff --git a/.changeset/twenty-roses-yell.md b/.changeset/twenty-roses-yell.md new file mode 100644 index 000000000..b07e020fd --- /dev/null +++ b/.changeset/twenty-roses-yell.md @@ -0,0 +1,5 @@ +--- +'@foreachbe/react-scripts': patch +--- + +Fix build error in react-scripts -- GitLab From 4a7de2911fdb0374c218e530ee2cd2cfecd32710 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 18:28:55 +0200 Subject: [PATCH 11/12] Run changeset version --- .changeset/pre.json | 3 ++- packages/react-scripts/CHANGELOG.md | 6 ++++++ packages/react-scripts/package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 438af2da2..cde0c4054 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -19,6 +19,7 @@ "changesets": [ "great-dolphins-enjoy", "quick-rabbits-wash", - "rotten-guests-deliver" + "rotten-guests-deliver", + "twenty-roses-yell" ] } diff --git a/packages/react-scripts/CHANGELOG.md b/packages/react-scripts/CHANGELOG.md index 9a2706792..72c5a00eb 100644 --- a/packages/react-scripts/CHANGELOG.md +++ b/packages/react-scripts/CHANGELOG.md @@ -1,5 +1,11 @@ # @foreachbe/react-scripts +## 6.2.0-beta.3 + +### Patch Changes + +- afef45e2: Fix build error in react-scripts + ## 6.2.0-beta.2 ### Patch Changes diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 28c35a201..03fc3795f 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@foreachbe/react-scripts", - "version": "6.2.0-beta.2", + "version": "6.2.0-beta.3", "description": "Configuration and scripts for Create React App.", "repository": { "type": "git", -- GitLab From dc18222ae762eb3cc85eeb1d29923db65d76a579 Mon Sep 17 00:00:00 2001 From: Simon VDB <simonvdbroeck@gmail.com> Date: Tue, 15 Sep 2020 18:34:56 +0200 Subject: [PATCH 12/12] add release github flow --- .github/workflows/release.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..8ad1baffe --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,30 @@ +name: Release + +on: + push: + branches: + - master + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@master + with: + # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits + fetch-depth: 0 + + - name: Setup Node.js 12.x + uses: actions/setup-node@master + with: + node-version: 12.x + + - name: Install Dependencies + run: yarn + + - name: Create Release Pull Request + uses: changesets/action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -- GitLab