From 2fa636fed34193d37b5bb5ce1d447feddabd95d7 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Tue, 23 Oct 2018 23:35:50 -0400 Subject: [PATCH 01/20] Add TypeScript app creation --- packages/create-react-app/createReactApp.js | 26 +++- packages/react-scripts/scripts/init.js | 36 +++++ .../template/src/serviceWorker.js | 2 +- .../template/src/serviceWorker.ts | 136 ++++++++++++++++++ 4 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 packages/react-scripts/template/src/serviceWorker.ts diff --git a/packages/create-react-app/createReactApp.js b/packages/create-react-app/createReactApp.js index a62f88589f0..6bc7464689f 100755 --- a/packages/create-react-app/createReactApp.js +++ b/packages/create-react-app/createReactApp.js @@ -77,6 +77,7 @@ const program = new commander.Command(packageJson.name) ) .option('--use-npm') .option('--use-pnp') + .option('--typescript') .allowUnknownOption() .on('--help', () => { console.log(` Only ${chalk.green('')} is required.`); @@ -180,10 +181,19 @@ createApp( program.scriptsVersion, program.useNpm, program.usePnp, + program.typescript, hiddenProgram.internalTestingTemplate ); -function createApp(name, verbose, version, useNpm, usePnp, template) { +function createApp( + name, + verbose, + version, + useNpm, + usePnp, + useTypescript, + template +) { const root = path.resolve(name); const appName = path.basename(root); @@ -273,7 +283,8 @@ function createApp(name, verbose, version, useNpm, usePnp, template) { originalDirectory, template, useYarn, - usePnp + usePnp, + useTypescript ); } @@ -356,10 +367,19 @@ function run( originalDirectory, template, useYarn, - usePnp + usePnp, + useTypescript ) { const packageToInstall = getInstallPackage(version, originalDirectory); const allDependencies = ['react', 'react-dom', packageToInstall]; + if (useTypescript) { + allDependencies.push( + '@types/react', + '@types/react-dom', + '@types/jest', + 'typescript' + ); + } console.log('Installing packages. This might take a couple of minutes.'); getPackageName(packageToInstall) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 8ec24967528..0109c7a048b 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -19,6 +19,7 @@ const path = require('path'); const chalk = require('chalk'); const execSync = require('child_process').execSync; const spawn = require('react-dev-utils/crossSpawn'); +const globby = require('react-dev-utils/globby').sync; const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); @@ -74,6 +75,12 @@ function tryGitInit(appPath) { } } +function replaceExtension(filePath, newExtension) { + const nFileName = + path.basename(filePath, path.extname(filePath)) + newExtension; + return path.join(path.dirname(filePath), nFileName); +} + module.exports = function( appPath, appName, @@ -90,6 +97,8 @@ module.exports = function( // Copy over some of the devDependencies appPackage.dependencies = appPackage.dependencies || {}; + const useTypeScript = appPackage.dependencies['typescript'] != null; + // Setup the script rules appPackage.scripts = { start: 'react-scripts start', @@ -132,6 +141,33 @@ module.exports = function( return; } + if (!template) { + const appSrc = path.join(appPath, 'src'); + if (useTypeScript) { + const jsFiles = globby('**/*.js', { cwd: appSrc }).map(f => + path.resolve(appSrc, f) + ); + for (const jsFile of jsFiles) { + const tsFile = replaceExtension(jsFile); + // If the TypeScript version already existed in the template, just + // remove the JavaScript version + if (fs.existsSync(tsFile)) { + fs.removeSync(jsFile); + } else { + fs.renameSync(jsFile, tsFile); + } + } + } else { + // Remove TypeScript files from template + const tsFiles = globby('**/*.(ts|tsx)', { cwd: appSrc }).map(f => + path.resolve(appSrc, f) + ); + for (const tsFile of tsFiles) { + fs.removeSync(tsFile); + } + } + } + // Rename gitignore after the fact to prevent npm from renaming it to .npmignore // See: https://github.com/npm/npm/issues/1862 try { diff --git a/packages/react-scripts/template/src/serviceWorker.js b/packages/react-scripts/template/src/serviceWorker.js index 0bece46ae65..ae4fc947fa9 100644 --- a/packages/react-scripts/template/src/serviceWorker.js +++ b/packages/react-scripts/template/src/serviceWorker.js @@ -23,7 +23,7 @@ const isLocalhost = Boolean( export function register(config) { if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL, window.location); + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); if (publicUrl.origin !== window.location.origin) { // Our service worker won't work if PUBLIC_URL is on a different origin // from what our page is served on. This might happen if a CDN is used to diff --git a/packages/react-scripts/template/src/serviceWorker.ts b/packages/react-scripts/template/src/serviceWorker.ts new file mode 100644 index 00000000000..731d3acd294 --- /dev/null +++ b/packages/react-scripts/template/src/serviceWorker.ts @@ -0,0 +1,136 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read http://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +type Config = { + onSuccess?: (registration: ServiceWorkerRegistration) => void; + onUpdate?: (registration: ServiceWorkerRegistration) => void; +}; + +export function register(config: Config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit http://bit.ly/CRA-PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl, config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl, config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + if ( + response.status === 404 || + response.headers.get('content-type').indexOf('javascript') === -1 + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then(registration => { + registration.unregister(); + }); + } +} From 49c163819041e455d84c90dfd1ecc3dde6e40c1b Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Tue, 23 Oct 2018 23:37:29 -0400 Subject: [PATCH 02/20] Actually specify new extension --- packages/react-scripts/scripts/init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 0109c7a048b..61c39dc1a95 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -148,7 +148,7 @@ module.exports = function( path.resolve(appSrc, f) ); for (const jsFile of jsFiles) { - const tsFile = replaceExtension(jsFile); + const tsFile = replaceExtension(jsFile, '.tsx'); // If the TypeScript version already existed in the template, just // remove the JavaScript version if (fs.existsSync(tsFile)) { From 88e7d42a4fbe48361762108b22f04b1a5ddf6dce Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Tue, 23 Oct 2018 23:40:12 -0400 Subject: [PATCH 03/20] Check for ts and tsx --- packages/react-scripts/scripts/init.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 61c39dc1a95..e4b75ca63d7 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -148,13 +148,14 @@ module.exports = function( path.resolve(appSrc, f) ); for (const jsFile of jsFiles) { - const tsFile = replaceExtension(jsFile, '.tsx'); + const tsFile = replaceExtension(jsFile, '.ts'); + const tsxFile = replaceExtension(jsFile, '.tsx'); // If the TypeScript version already existed in the template, just // remove the JavaScript version - if (fs.existsSync(tsFile)) { + if (fs.existsSync(tsFile) || fs.existsSync(tsxFile)) { fs.removeSync(jsFile); } else { - fs.renameSync(jsFile, tsFile); + fs.renameSync(jsFile, tsxFile); } } } else { From 9e8e99587c7b93e3098df2db8d1882f160ce92e8 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Tue, 23 Oct 2018 23:50:03 -0400 Subject: [PATCH 04/20] Fix types in default service worker file --- .../react-scripts/template/src/serviceWorker.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/react-scripts/template/src/serviceWorker.ts b/packages/react-scripts/template/src/serviceWorker.ts index 731d3acd294..7c316eac71c 100644 --- a/packages/react-scripts/template/src/serviceWorker.ts +++ b/packages/react-scripts/template/src/serviceWorker.ts @@ -28,7 +28,10 @@ type Config = { export function register(config: Config) { if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + const publicUrl = new URL( + (process as { env: { [key: string]: string } }).env.PUBLIC_URL, + window.location.href + ); if (publicUrl.origin !== window.location.origin) { // Our service worker won't work if PUBLIC_URL is on a different origin // from what our page is served on. This might happen if a CDN is used to @@ -59,12 +62,15 @@ export function register(config: Config) { } } -function registerValidSW(swUrl, config) { +function registerValidSW(swUrl: string, config: Config) { navigator.serviceWorker .register(swUrl) .then(registration => { registration.onupdatefound = () => { const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { @@ -100,14 +106,15 @@ function registerValidSW(swUrl, config) { }); } -function checkValidServiceWorker(swUrl, config) { +function checkValidServiceWorker(swUrl: string, config: Config) { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl) .then(response => { // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); if ( response.status === 404 || - response.headers.get('content-type').indexOf('javascript') === -1 + (contentType != null && contentType.indexOf('javascript') === -1) ) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then(registration => { From 9782cb966ed834e94b17b57b8e18416f1f737f56 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Tue, 23 Oct 2018 23:51:06 -0400 Subject: [PATCH 05/20] Mirror changes in JS version of SW --- packages/react-scripts/template/src/serviceWorker.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/template/src/serviceWorker.js b/packages/react-scripts/template/src/serviceWorker.js index ae4fc947fa9..2283ff9ced1 100644 --- a/packages/react-scripts/template/src/serviceWorker.js +++ b/packages/react-scripts/template/src/serviceWorker.js @@ -60,6 +60,9 @@ function registerValidSW(swUrl, config) { .then(registration => { registration.onupdatefound = () => { const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { @@ -100,9 +103,10 @@ function checkValidServiceWorker(swUrl, config) { fetch(swUrl) .then(response => { // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); if ( response.status === 404 || - response.headers.get('content-type').indexOf('javascript') === -1 + (contentType != null && contentType.indexOf('javascript') === -1) ) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then(registration => { From 16ff63d7bcf15bbd6f83fabf0fd50b3d2b054198 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 10:40:27 -0400 Subject: [PATCH 06/20] Separate templates --- .../template-typescript/README.md | 44 ++++++++++++++++++ .../template-typescript/gitignore | 23 +++++++++ .../template-typescript/public/favicon.ico | Bin 0 -> 3870 bytes .../template-typescript/public/index.html | 40 ++++++++++++++++ .../template-typescript/public/manifest.json | 15 ++++++ .../template-typescript/src/App.css | 32 +++++++++++++ .../template-typescript/src/App.test.tsx | 9 ++++ .../template-typescript/src/App.tsx | 28 +++++++++++ .../template-typescript/src/index.css | 14 ++++++ .../template-typescript/src/index.tsx | 12 +++++ .../template-typescript/src/logo.svg | 7 +++ .../src/serviceWorker.ts | 0 12 files changed, 224 insertions(+) create mode 100644 packages/react-scripts/template-typescript/README.md create mode 100644 packages/react-scripts/template-typescript/gitignore create mode 100644 packages/react-scripts/template-typescript/public/favicon.ico create mode 100644 packages/react-scripts/template-typescript/public/index.html create mode 100644 packages/react-scripts/template-typescript/public/manifest.json create mode 100644 packages/react-scripts/template-typescript/src/App.css create mode 100644 packages/react-scripts/template-typescript/src/App.test.tsx create mode 100644 packages/react-scripts/template-typescript/src/App.tsx create mode 100644 packages/react-scripts/template-typescript/src/index.css create mode 100644 packages/react-scripts/template-typescript/src/index.tsx create mode 100644 packages/react-scripts/template-typescript/src/logo.svg rename packages/react-scripts/{template => template-typescript}/src/serviceWorker.ts (100%) diff --git a/packages/react-scripts/template-typescript/README.md b/packages/react-scripts/template-typescript/README.md new file mode 100644 index 00000000000..897dc836601 --- /dev/null +++ b/packages/react-scripts/template-typescript/README.md @@ -0,0 +1,44 @@ +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Available Scripts + +In the project directory, you can run: + +### `npm start` + +Runs the app in the development mode.
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.
+You will also see any lint errors in the console. + +### `npm test` + +Launches the test runner in the interactive watch mode.
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `npm run build` + +Builds the app for production to the `build` folder.
+It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.
+Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `npm run eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). diff --git a/packages/react-scripts/template-typescript/gitignore b/packages/react-scripts/template-typescript/gitignore new file mode 100644 index 00000000000..4d29575de80 --- /dev/null +++ b/packages/react-scripts/template-typescript/gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/packages/react-scripts/template-typescript/public/favicon.ico b/packages/react-scripts/template-typescript/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/packages/react-scripts/template-typescript/public/index.html b/packages/react-scripts/template-typescript/public/index.html new file mode 100644 index 00000000000..4bfce95684f --- /dev/null +++ b/packages/react-scripts/template-typescript/public/index.html @@ -0,0 +1,40 @@ + + + + + + + + + + + React App + + + +
+ + + diff --git a/packages/react-scripts/template-typescript/public/manifest.json b/packages/react-scripts/template-typescript/public/manifest.json new file mode 100644 index 00000000000..1f2f141fafd --- /dev/null +++ b/packages/react-scripts/template-typescript/public/manifest.json @@ -0,0 +1,15 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/packages/react-scripts/template-typescript/src/App.css b/packages/react-scripts/template-typescript/src/App.css new file mode 100644 index 00000000000..92f956e8040 --- /dev/null +++ b/packages/react-scripts/template-typescript/src/App.css @@ -0,0 +1,32 @@ +.App { + text-align: center; +} + +.App-logo { + animation: App-logo-spin infinite 20s linear; + height: 40vmin; +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/packages/react-scripts/template-typescript/src/App.test.tsx b/packages/react-scripts/template-typescript/src/App.test.tsx new file mode 100644 index 00000000000..a754b201bf9 --- /dev/null +++ b/packages/react-scripts/template-typescript/src/App.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); +}); diff --git a/packages/react-scripts/template-typescript/src/App.tsx b/packages/react-scripts/template-typescript/src/App.tsx new file mode 100644 index 00000000000..7e261ca47e6 --- /dev/null +++ b/packages/react-scripts/template-typescript/src/App.tsx @@ -0,0 +1,28 @@ +import React, { Component } from 'react'; +import logo from './logo.svg'; +import './App.css'; + +class App extends Component { + render() { + return ( +
+ ); + } +} + +export default App; diff --git a/packages/react-scripts/template-typescript/src/index.css b/packages/react-scripts/template-typescript/src/index.css new file mode 100644 index 00000000000..e2bd8f36a01 --- /dev/null +++ b/packages/react-scripts/template-typescript/src/index.css @@ -0,0 +1,14 @@ +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/packages/react-scripts/template-typescript/src/index.tsx b/packages/react-scripts/template-typescript/src/index.tsx new file mode 100644 index 00000000000..0c5e75da1cd --- /dev/null +++ b/packages/react-scripts/template-typescript/src/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render(, document.getElementById('root')); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: http://bit.ly/CRA-PWA +serviceWorker.unregister(); diff --git a/packages/react-scripts/template-typescript/src/logo.svg b/packages/react-scripts/template-typescript/src/logo.svg new file mode 100644 index 00000000000..6b60c1042f5 --- /dev/null +++ b/packages/react-scripts/template-typescript/src/logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/react-scripts/template/src/serviceWorker.ts b/packages/react-scripts/template-typescript/src/serviceWorker.ts similarity index 100% rename from packages/react-scripts/template/src/serviceWorker.ts rename to packages/react-scripts/template-typescript/src/serviceWorker.ts From 15146b374c21e29e3817cfe0d54cbfd312ebcaaa Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 10:43:50 -0400 Subject: [PATCH 07/20] Use separate template directory --- packages/react-scripts/scripts/init.js | 31 +------------------------- 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index e4b75ca63d7..3212c6ebb82 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -19,7 +19,6 @@ const path = require('path'); const chalk = require('chalk'); const execSync = require('child_process').execSync; const spawn = require('react-dev-utils/crossSpawn'); -const globby = require('react-dev-utils/globby').sync; const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); @@ -131,7 +130,7 @@ module.exports = function( // Copy the files for the user const templatePath = template ? path.resolve(originalDirectory, template) - : path.join(ownPath, 'template'); + : path.join(ownPath, useTypeScript ? 'template-typescript' : 'template'); if (fs.existsSync(templatePath)) { fs.copySync(templatePath, appPath); } else { @@ -141,34 +140,6 @@ module.exports = function( return; } - if (!template) { - const appSrc = path.join(appPath, 'src'); - if (useTypeScript) { - const jsFiles = globby('**/*.js', { cwd: appSrc }).map(f => - path.resolve(appSrc, f) - ); - for (const jsFile of jsFiles) { - const tsFile = replaceExtension(jsFile, '.ts'); - const tsxFile = replaceExtension(jsFile, '.tsx'); - // If the TypeScript version already existed in the template, just - // remove the JavaScript version - if (fs.existsSync(tsFile) || fs.existsSync(tsxFile)) { - fs.removeSync(jsFile); - } else { - fs.renameSync(jsFile, tsxFile); - } - } - } else { - // Remove TypeScript files from template - const tsFiles = globby('**/*.(ts|tsx)', { cwd: appSrc }).map(f => - path.resolve(appSrc, f) - ); - for (const tsFile of tsFiles) { - fs.removeSync(tsFile); - } - } - } - // Rename gitignore after the fact to prevent npm from renaming it to .npmignore // See: https://github.com/npm/npm/issues/1862 try { From 8aa369b4aa9cf05045a515d18e4b8bb861b63aa7 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 10:44:35 -0400 Subject: [PATCH 08/20] Remove unused function --- packages/react-scripts/scripts/init.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 3212c6ebb82..af418f630ca 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -74,12 +74,6 @@ function tryGitInit(appPath) { } } -function replaceExtension(filePath, newExtension) { - const nFileName = - path.basename(filePath, path.extname(filePath)) + newExtension; - return path.join(path.dirname(filePath), nFileName); -} - module.exports = function( appPath, appName, From 9497925b5935e1fd16dbe0b7b69b497461f8973a Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 10:54:30 -0400 Subject: [PATCH 09/20] Add a tsconfig file to the template --- .../template-typescript/tsconfig.json | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 packages/react-scripts/template-typescript/tsconfig.json diff --git a/packages/react-scripts/template-typescript/tsconfig.json b/packages/react-scripts/template-typescript/tsconfig.json new file mode 100644 index 00000000000..bac1eb9c1cd --- /dev/null +++ b/packages/react-scripts/template-typescript/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es5", // This option has no effect on output, but can be useful for type checking. + "allowJs": true, // This allows TypeScript files to import JavaScript files. + "skipLibCheck": true, // Skips type checking of declaration files. + "esModuleInterop": true, // This option aligns with Babel's behavior. + "allowSyntheticDefaultImports": true, // This option aligns with Babel's behavior. + "strict": true, // `true` forces types to be present. Switch to `false` if you don't want to add types to entire files. + "module": "esnext", // webpack compatibility (required) + "moduleResolution": "node", // (required) + "resolveJsonModule": true, // webpack compatibility (required) + "isolatedModules": true, // This option prevents usage of namespaces and const enums. (required) + "noEmit": true, // (required) + "jsx": "preserve" // (required) + }, + "include": [ + "src" + ], + // Exclude test files from type checking + // If you'd like to type check tests, replace this with an empty array, i.e. "exclude": [] + "exclude": [ + "**/__tests__/**", + "**/?*test.*", + "**/?*spec.*" + ] +} From 753a5944d30f838fc3abdbf9220e9f9dad304713 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 11:10:12 -0400 Subject: [PATCH 10/20] Test install of typescript --- tasks/e2e-installs.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index e402ee5c88a..ef78b97e858 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -59,6 +59,17 @@ function checkDependencies { fi } +# Check for accidental dependencies in package.json +function checkTypeScriptDependencies { + if ! awk '/"dependencies": {/{y=1;next}/},/{y=0; next}y' package.json | \ + grep -v -q -E '^\s*"(@types\/.+)|typescript|(react(-dom|-scripts)?)"'; then + echo "Dependencies are correct" + else + echo "There are extraneous dependencies in package.json" + exit 1 + fi +} + # Exit the script with a helpful error message when any error is encountered trap 'set +x; handle_error $LINENO $BASH_COMMAND' ERR @@ -140,6 +151,18 @@ exists node_modules/react-scripts grep '"version": "1.0.17"' node_modules/react-scripts/package.json checkDependencies +# ****************************************************************************** +# Test --typescript flag +# ****************************************************************************** + +cd "$temp_app_path" +npx create-react-app --typescript test-app-typescript +cd test-app-typescript + +# Check corresponding scripts version is installed. +exists node_modules/react-scripts +checkTypeScriptDependencies + # ****************************************************************************** # Test --scripts-version with a tarball url # ****************************************************************************** From 9152c6a494432bd37090f6da7c94c66c38f54c36 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 11:13:03 -0400 Subject: [PATCH 11/20] Add e2e for TypeScript --- tasks/e2e-installs.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index ef78b97e858..5144fdad2b6 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -137,6 +137,11 @@ exists node_modules/react-scripts grep '"version": "1.0.17"' node_modules/react-scripts/package.json checkDependencies +# Check that the TypeScript template passes smoke tests, build, and normal tests +yarn start --smoke-test +yarn build +CI=true yarn test + # ****************************************************************************** # Test --use-npm flag # ****************************************************************************** From 9c8ee63b4e42b5024ceff745d01655cdd7fe5b0c Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 11:15:47 -0400 Subject: [PATCH 12/20] Check for index.tsx to make sure we're not in the JS template --- tasks/e2e-installs.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 5144fdad2b6..9b973bb6eb6 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -164,8 +164,10 @@ cd "$temp_app_path" npx create-react-app --typescript test-app-typescript cd test-app-typescript -# Check corresponding scripts version is installed. +# Check corresponding template is installed. exists node_modules/react-scripts +exists node_modules/typescript +exists src/index.tsx checkTypeScriptDependencies # ****************************************************************************** From d2817b943f40881bf9e4e457ecb1db6fed3301a0 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 11:22:15 -0400 Subject: [PATCH 13/20] Ensure TypeScript doesn't leak into normal installs --- tasks/e2e-installs.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 9b973bb6eb6..80339534e4a 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -120,8 +120,11 @@ cd "$temp_app_path" npx create-react-app --scripts-version=@latest test-app-dist-tag cd test-app-dist-tag -# Check corresponding scripts version is installed. +# Check corresponding scripts version is installed and no TypeScript is present. exists node_modules/react-scripts +! exists node_modules/typescript +! exists src/index.tsx +exists src/index.js checkDependencies # ****************************************************************************** From 8cc6e2600b060d64a0845a774a656e256417b895 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 11:56:52 -0400 Subject: [PATCH 14/20] Ignore some files --- .gitignore | 1 + tasks/.gitignore | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 tasks/.gitignore diff --git a/.gitignore b/.gitignore index 79ce88915d7..ffa71fafc6d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* /.changelog +.npm/ diff --git a/tasks/.gitignore b/tasks/.gitignore new file mode 100644 index 00000000000..c3c49e4c2e2 --- /dev/null +++ b/tasks/.gitignore @@ -0,0 +1,2 @@ +htpasswd +storage From 19048884042d6d2cde0210b03654bbe3d2048765 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 12:08:11 -0400 Subject: [PATCH 15/20] Print version of CRA --- tasks/e2e-installs.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 80339534e4a..60cc6213f6f 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -112,6 +112,9 @@ yarn config set registry "$custom_registry_url" git clean -df ./tasks/publish.sh --yes --force-publish=* --skip-git --cd-version=prerelease --exact --npm-tag=latest +echo "Create React App Version: " +npx create-react-app --version + # ****************************************************************************** # Test --scripts-version with a distribution tag # ****************************************************************************** From a8ec5dadc1f810ab0ad4b0266b7ece086cae7f5f Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 12:17:51 -0400 Subject: [PATCH 16/20] Fix script --- tasks/e2e-installs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 60cc6213f6f..b8f056a6b3f 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -167,7 +167,7 @@ checkDependencies # ****************************************************************************** cd "$temp_app_path" -npx create-react-app --typescript test-app-typescript +npx create-react-app test-app-typescript --typescript cd test-app-typescript # Check corresponding template is installed. From aac605b3110eeec615b5b1f94f9dc40bc8bf5d45 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 13:08:49 -0400 Subject: [PATCH 17/20] Add new template --- packages/react-scripts/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index ddf53102136..dd91e4372fa 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -15,6 +15,7 @@ "config", "scripts", "template", + "template-typescript", "utils" ], "bin": { From e068b89624ca0c503677cdc962d378631192474c Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 13:30:38 -0400 Subject: [PATCH 18/20] Move test to correct location --- tasks/e2e-installs.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index b8f056a6b3f..2f584ef31e1 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -143,11 +143,6 @@ exists node_modules/react-scripts grep '"version": "1.0.17"' node_modules/react-scripts/package.json checkDependencies -# Check that the TypeScript template passes smoke tests, build, and normal tests -yarn start --smoke-test -yarn build -CI=true yarn test - # ****************************************************************************** # Test --use-npm flag # ****************************************************************************** @@ -176,6 +171,11 @@ exists node_modules/typescript exists src/index.tsx checkTypeScriptDependencies +# Check that the TypeScript template passes smoke tests, build, and normal tests +yarn start --smoke-test +yarn build +CI=true yarn test + # ****************************************************************************** # Test --scripts-version with a tarball url # ****************************************************************************** From 8f454b17409120f06382d1ea0411285c312c7589 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 15:36:11 -0400 Subject: [PATCH 19/20] Use `verifyTypeScriptSetup` routine to populate files --- packages/react-scripts/scripts/init.js | 5 ++++ .../template-typescript/tsconfig.json | 26 ------------------- 2 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 packages/react-scripts/template-typescript/tsconfig.json diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index af418f630ca..771f6dbf490 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -21,6 +21,7 @@ const execSync = require('child_process').execSync; const spawn = require('react-dev-utils/crossSpawn'); const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); +const verifyTypeScriptSetup = require('./utils/verifyTypeScriptSetup'); function isInGitRepository() { try { @@ -194,6 +195,10 @@ module.exports = function( } } + if (useTypeScript) { + verifyTypeScriptSetup(); + } + if (tryGitInit(appPath)) { console.log(); console.log('Initialized a git repository.'); diff --git a/packages/react-scripts/template-typescript/tsconfig.json b/packages/react-scripts/template-typescript/tsconfig.json deleted file mode 100644 index bac1eb9c1cd..00000000000 --- a/packages/react-scripts/template-typescript/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", // This option has no effect on output, but can be useful for type checking. - "allowJs": true, // This allows TypeScript files to import JavaScript files. - "skipLibCheck": true, // Skips type checking of declaration files. - "esModuleInterop": true, // This option aligns with Babel's behavior. - "allowSyntheticDefaultImports": true, // This option aligns with Babel's behavior. - "strict": true, // `true` forces types to be present. Switch to `false` if you don't want to add types to entire files. - "module": "esnext", // webpack compatibility (required) - "moduleResolution": "node", // (required) - "resolveJsonModule": true, // webpack compatibility (required) - "isolatedModules": true, // This option prevents usage of namespaces and const enums. (required) - "noEmit": true, // (required) - "jsx": "preserve" // (required) - }, - "include": [ - "src" - ], - // Exclude test files from type checking - // If you'd like to type check tests, replace this with an empty array, i.e. "exclude": [] - "exclude": [ - "**/__tests__/**", - "**/?*test.*", - "**/?*spec.*" - ] -} From 6eda0d5ecd1fe001a534f5d307ab57a84a01c7c8 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 24 Oct 2018 15:44:52 -0400 Subject: [PATCH 20/20] Ensure tsconfig is created --- tasks/e2e-installs.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh index 2f584ef31e1..690a9cd04fd 100755 --- a/tasks/e2e-installs.sh +++ b/tasks/e2e-installs.sh @@ -169,6 +169,7 @@ cd test-app-typescript exists node_modules/react-scripts exists node_modules/typescript exists src/index.tsx +exists tsconfig.json checkTypeScriptDependencies # Check that the TypeScript template passes smoke tests, build, and normal tests