From e2d71111ff68231c320b81d6c570d8e109f65857 Mon Sep 17 00:00:00 2001 From: Tom Valorsa Date: Sun, 22 Dec 2019 09:25:19 +0000 Subject: [PATCH 1/4] Add template support for any package.json keys (#8082) --- docusaurus/docs/custom-templates.md | 24 +++++++++---- .../cra-template-typescript/template.json | 20 ++++++----- packages/cra-template/template.json | 10 +++--- .../fixtures/kitchensink/template.json | 16 +++++---- packages/react-scripts/scripts/init.js | 36 +++++++++++++++++-- 5 files changed, 77 insertions(+), 29 deletions(-) diff --git a/docusaurus/docs/custom-templates.md b/docusaurus/docs/custom-templates.md index 98acb9b1a75..58af9b0ec1c 100644 --- a/docusaurus/docs/custom-templates.md +++ b/docusaurus/docs/custom-templates.md @@ -58,18 +58,28 @@ You can add whatever files you want in here, but you must have at least the file ### The `template.json` file -This is where you can define dependencies (only dependencies are supported for now), as well as any custom scripts that your template relies on. +This is the configuration file for your template. It allows you to define information that should become a part of the generated project's `package.json` file, such as dependencies (only dependencies are supported for now) and any custom scripts that your template relies on. It should be structured as follows: ```json { - "dependencies": { - "serve": "^11.2.0" - }, - "scripts": { - "serve": "serve -s build", - "build-and-serve": "npm run build && npm run serve" + "package": { + "dependencies": { + "serve": "^11.2.0" + }, + "scripts": { + "serve": "serve -s build", + "build-and-serve": "npm run build && npm run serve" + }, + "browserslist": [ + "defaults", + "not IE 11", + "not IE_Mob 11", + "maintained node versions", + ] } } ``` +Any values you add for `"dependencies"` and `"scripts"` will be merged with the values used in the initialisation process of `react-scripts`. Any other information you add to `"package"` will be added to the generated project's `package.json` file, replacing any existing values associated with those keys. + For convenience, we always replace `npm run` with `yarn` in your custom `"scripts"`, as well as in your `README` when projects are initialized with yarn. diff --git a/packages/cra-template-typescript/template.json b/packages/cra-template-typescript/template.json index 06d73b74130..1bb882699f6 100644 --- a/packages/cra-template-typescript/template.json +++ b/packages/cra-template-typescript/template.json @@ -1,12 +1,14 @@ { - "dependencies": { - "@testing-library/react": "^9.3.2", - "@testing-library/jest-dom": "^4.2.4", - "@testing-library/user-event": "^7.1.2", - "@types/node": "^12.0.0", - "@types/react": "^16.9.0", - "@types/react-dom": "^16.9.0", - "@types/jest": "^24.0.0", - "typescript": "~3.7.2" + "package": { + "dependencies": { + "@testing-library/react": "^9.3.2", + "@testing-library/jest-dom": "^4.2.4", + "@testing-library/user-event": "^7.1.2", + "@types/node": "^12.0.0", + "@types/react": "^16.9.0", + "@types/react-dom": "^16.9.0", + "@types/jest": "^24.0.0", + "typescript": "~3.7.2" + } } } diff --git a/packages/cra-template/template.json b/packages/cra-template/template.json index 0cc6ba23920..4c6861dc1f0 100644 --- a/packages/cra-template/template.json +++ b/packages/cra-template/template.json @@ -1,7 +1,9 @@ { - "dependencies": { - "@testing-library/react": "^9.3.2", - "@testing-library/jest-dom": "^4.2.4", - "@testing-library/user-event": "^7.1.2" + "package": { + "dependencies": { + "@testing-library/react": "^9.3.2", + "@testing-library/jest-dom": "^4.2.4", + "@testing-library/user-event": "^7.1.2" + } } } diff --git a/packages/react-scripts/fixtures/kitchensink/template.json b/packages/react-scripts/fixtures/kitchensink/template.json index 3ba93127c8b..954cb3b2d73 100644 --- a/packages/react-scripts/fixtures/kitchensink/template.json +++ b/packages/react-scripts/fixtures/kitchensink/template.json @@ -1,10 +1,12 @@ { - "dependencies": { - "bootstrap": "4.3.1", - "jest": "24.9.0", - "node-sass": "4.12.0", - "normalize.css": "7.0.0", - "prop-types": "15.7.2", - "test-integrity": "2.0.1" + "package": { + "dependencies": { + "bootstrap": "4.3.1", + "jest": "24.9.0", + "node-sass": "4.12.0", + "normalize.css": "7.0.0", + "prop-types": "15.7.2", + "test-integrity": "2.0.1" + } } } diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 74d607b105d..4f9f205e411 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -118,11 +118,37 @@ module.exports = function( templateJson = require(templateJsonPath); } + const templatePackage = templateJson.package || {}; + + // Keys to ignore in templatePackage + const templatePackageBlacklist = [ + 'devDependencies', + 'peerDependencies', + 'name', + ]; + + // Keys from templatePackage that will be merged with appPackage + const templatePackageToMerge = [ + 'dependencies', + 'scripts', + ]; + + // Keys from templatePackage that will be added to appPackage, + // replacing any existing entries. + const templatePackageToReplace = Object.keys(templatePackage) + .filter(key => { + return ( + templatePackageBlacklist.indexOf(key) === -1 && + templatePackageToMerge.indexOf(key) === -1 + ); + }); + // Copy over some of the devDependencies appPackage.dependencies = appPackage.dependencies || {}; // Setup the script rules - const templateScripts = templateJson.scripts || {}; + // TODO: deprecate 'scripts' key directly on templateJson + const templateScripts = templatePackage.scripts || templateJson.scripts || {}; appPackage.scripts = Object.assign( { start: 'react-scripts start', @@ -152,6 +178,11 @@ module.exports = function( // Setup the browsers list appPackage.browserslist = defaultBrowsers; + // Add templatePackage keys/values to appPackage, replacing existing entries + templatePackageToReplace.forEach(key => { + appPackage[key] = templatePackage[key]; + }); + fs.writeFileSync( path.join(appPath, 'package.json'), JSON.stringify(appPackage, null, 2) + os.EOL @@ -221,7 +252,8 @@ module.exports = function( } // Install additional template dependencies, if present - const templateDependencies = templateJson.dependencies; + // TODO: deprecate 'dependencies' key directly on templateJson + const templateDependencies = templatePackage.dependencies || templateJson.dependencies; if (templateDependencies) { args = args.concat( Object.keys(templateDependencies).map(key => { From 3b821b039079b651baa5602b547608e2a8e4b673 Mon Sep 17 00:00:00 2001 From: Tom Valorsa Date: Fri, 3 Jan 2020 00:43:13 +0000 Subject: [PATCH 2/4] Update custom template documentation, extend template package blacklist (#8082) --- docusaurus/docs/custom-templates.md | 19 ++++++----- packages/react-scripts/scripts/init.js | 46 ++++++++++++++++++-------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/docusaurus/docs/custom-templates.md b/docusaurus/docs/custom-templates.md index 58af9b0ec1c..bab1c54a00d 100644 --- a/docusaurus/docs/custom-templates.md +++ b/docusaurus/docs/custom-templates.md @@ -58,28 +58,31 @@ You can add whatever files you want in here, but you must have at least the file ### The `template.json` file -This is the configuration file for your template. It allows you to define information that should become a part of the generated project's `package.json` file, such as dependencies (only dependencies are supported for now) and any custom scripts that your template relies on. It should be structured as follows: +This is the configuration file for your template. As this is a new feature, more options will be added over time. For now, only a `package` key is supported. + +The `package` key lets you provide any keys/values that you want added to the new project's `package.json`, such as dependencies (only dependencies are supported for now) and any custom scripts that your template relies on. + +Below is an example `template.json` file: ```json { "package": { "dependencies": { + "eslint-plugin-jsx-a11y": "^6.2.3", "serve": "^11.2.0" }, "scripts": { "serve": "serve -s build", "build-and-serve": "npm run build && npm run serve" }, - "browserslist": [ - "defaults", - "not IE 11", - "not IE_Mob 11", - "maintained node versions", - ] + "eslintConfig": { + "extends": ["react-app", "plugin:jsx-a11y/recommended"], + "plugins": ["jsx-a11y"] + } } } ``` -Any values you add for `"dependencies"` and `"scripts"` will be merged with the values used in the initialisation process of `react-scripts`. Any other information you add to `"package"` will be added to the generated project's `package.json` file, replacing any existing values associated with those keys. +Any values you add for `"dependencies"` and `"scripts"` will be merged with the Create React App defaults. Values for any other keys will be used as-is, replacing any matching Create React App defaults. For convenience, we always replace `npm run` with `yarn` in your custom `"scripts"`, as well as in your `README` when projects are initialized with yarn. diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 4f9f205e411..45646820d5d 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -122,26 +122,45 @@ module.exports = function( // Keys to ignore in templatePackage const templatePackageBlacklist = [ + 'name', + 'version', + 'description', + 'keywords', + 'homepage', + 'bugs', + 'license', + 'author', + 'contributors', + 'files', + 'main', + 'browser', + 'bin', + 'man', + 'directories', + 'repository', 'devDependencies', 'peerDependencies', - 'name', + 'bundledDependencies', + 'optionalDependencies', + 'engineStrict', + 'os', + 'cpu', + 'preferGlobal', + 'private', + 'publishConfig', ]; // Keys from templatePackage that will be merged with appPackage - const templatePackageToMerge = [ - 'dependencies', - 'scripts', - ]; + const templatePackageToMerge = ['dependencies', 'scripts']; // Keys from templatePackage that will be added to appPackage, // replacing any existing entries. - const templatePackageToReplace = Object.keys(templatePackage) - .filter(key => { - return ( - templatePackageBlacklist.indexOf(key) === -1 && - templatePackageToMerge.indexOf(key) === -1 - ); - }); + const templatePackageToReplace = Object.keys(templatePackage).filter(key => { + return ( + templatePackageBlacklist.indexOf(key) === -1 && + templatePackageToMerge.indexOf(key) === -1 + ); + }); // Copy over some of the devDependencies appPackage.dependencies = appPackage.dependencies || {}; @@ -253,7 +272,8 @@ module.exports = function( // Install additional template dependencies, if present // TODO: deprecate 'dependencies' key directly on templateJson - const templateDependencies = templatePackage.dependencies || templateJson.dependencies; + const templateDependencies = + templatePackage.dependencies || templateJson.dependencies; if (templateDependencies) { args = args.concat( Object.keys(templateDependencies).map(key => { From 9bfa838910836bb1f26c1159e752a7a37f5a073e Mon Sep 17 00:00:00 2001 From: Tom Valorsa Date: Sat, 4 Jan 2020 10:15:03 +0000 Subject: [PATCH 3/4] Remove 'homepage' from template blacklist (#8082) --- packages/react-scripts/scripts/init.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 45646820d5d..6116ce081ba 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -126,7 +126,6 @@ module.exports = function( 'version', 'description', 'keywords', - 'homepage', 'bugs', 'license', 'author', From 000d230f24a28b3802a4adf00267d931fe3cf9b2 Mon Sep 17 00:00:00 2001 From: Tom Valorsa Date: Thu, 9 Jan 2020 20:11:51 +0000 Subject: [PATCH 4/4] Change indexOf() to includes() --- packages/react-scripts/scripts/init.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 6116ce081ba..9c78fcfbfb5 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -156,8 +156,8 @@ module.exports = function( // replacing any existing entries. const templatePackageToReplace = Object.keys(templatePackage).filter(key => { return ( - templatePackageBlacklist.indexOf(key) === -1 && - templatePackageToMerge.indexOf(key) === -1 + !templatePackageBlacklist.includes(key) && + !templatePackageToMerge.includes(key) ); });