From 9e4589f48eb30f356a71912a4786d8624650da9f Mon Sep 17 00:00:00 2001 From: Will Monk Date: Mon, 27 Nov 2017 17:10:02 +0000 Subject: [PATCH 1/5] Merge pull request #165 from johnnyreilly/master Add support for fork-ts-checker-webpack-plugin --- packages/react-scripts/config/paths.js | 10 ++-- .../config/webpack.config.dev.js | 26 +++++---- .../config/webpack.config.prod.js | 20 +++++-- packages/react-scripts/package.json | 54 +++++++++++-------- 4 files changed, 71 insertions(+), 39 deletions(-) diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index e860d9b04..76c165ba4 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -43,8 +43,8 @@ const getPublicUrl = appPackageJson => // like /todos/42/static/js/bundle.7289d.js. We have to know the root. function getServedPath(appPackageJson) { const publicUrl = getPublicUrl(appPackageJson); - const servedUrl = - envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/'); + const servedUrl = envPublicUrl || + (publicUrl ? url.parse(publicUrl).pathname : '/'); return ensureSlash(servedUrl, true); } @@ -61,6 +61,7 @@ module.exports = { testsSetup: resolveApp('src/setupTests.ts'), appNodeModules: resolveApp('node_modules'), appTsConfig: resolveApp('tsconfig.json'), + appTsLint: resolveApp('tslint.json'), publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')), }; @@ -83,6 +84,7 @@ module.exports = { appNodeModules: resolveApp('node_modules'), appTsConfig: resolveApp('tsconfig.json'), appTsTestConfig: resolveApp('tsconfig.test.json'), + appTsLint: resolveApp('tslint.json'), publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')), // These properties only exist before ejecting: @@ -92,8 +94,7 @@ module.exports = { const ownPackageJson = require('../package.json'); const reactScriptsPath = resolveApp(`node_modules/${ownPackageJson.name}`); -const reactScriptsLinked = - fs.existsSync(reactScriptsPath) && +const reactScriptsLinked = fs.existsSync(reactScriptsPath) && fs.lstatSync(reactScriptsPath).isSymbolicLink(); // config before publish: we're in ./packages/react-scripts/config/ @@ -114,6 +115,7 @@ if ( testsSetup: resolveOwn('template/src/setupTests.ts'), appNodeModules: resolveOwn('node_modules'), appTsConfig: resolveOwn('template/tsconfig.json'), + appTsLint: resolveOwn('template/tslint.json'), appTsTestConfig: resolveOwn('template/tsconfig.test.json'), publicUrl: getPublicUrl(resolveOwn('package.json')), servedPath: getServedPath(resolveOwn('package.json')), diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 07c0a3adf..6c619f4f4 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -18,6 +18,7 @@ const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const getClientEnvironment = require('./env'); const paths = require('./paths'); @@ -134,14 +135,6 @@ module.exports = { // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176. // { parser: { requireEnsure: false } }, - // First, run the linter. - // It's important to do this before Babel processes the JS. - { - test: /\.(ts|tsx)$/, - loader: require.resolve('tslint-loader'), - enforce: 'pre', - include: paths.appSrc, - }, { test: /\.js$/, loader: require.resolve('source-map-loader'), @@ -168,7 +161,15 @@ module.exports = { { test: /\.(ts|tsx)$/, include: paths.appSrc, - loader: require.resolve('ts-loader'), + use: [ + { + loader: require.resolve('ts-loader'), + options: { + // disable type checker - we will use it in fork plugin + transpileOnly: true, + }, + }, + ], }, // "postcss" loader applies autoprefixer to our CSS. // "css" loader resolves paths in CSS and adds assets as dependencies. @@ -262,6 +263,13 @@ module.exports = { // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack // You can remove this if you don't use Moment.js: new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // Perform type checking and linting in a separate process to speed up compilation + new ForkTsCheckerWebpackPlugin({ + async: false, + watch: paths.appSrc, + tsconfig: paths.appTsConfig, + tslint: paths.appTsLint, + }), ], // 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/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 9582ee731..366dcd108 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -19,6 +19,7 @@ const ManifestPlugin = require('webpack-manifest-plugin'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const paths = require('./paths'); const getClientEnvironment = require('./env'); @@ -137,7 +138,6 @@ module.exports = { // TODO: Disable require.ensure as it's not a standard language feature. // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176. // { parser: { requireEnsure: false } }, - // First, run the linter. // It's important to do this before Typescript runs. { @@ -167,11 +167,19 @@ module.exports = { name: 'static/media/[name].[hash:8].[ext]', }, }, - //Compile .tsx? + // Compile .tsx? { test: /\.(ts|tsx)$/, include: paths.appSrc, - loader: require.resolve('ts-loader') + use: [ + { + loader: require.resolve('ts-loader'), + options: { + // disable type checker - we will use it in fork plugin + transpileOnly: true, + }, + }, + ], }, // The notation here is somewhat confusing. // "postcss" loader applies autoprefixer to our CSS. @@ -341,6 +349,12 @@ module.exports = { // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack // You can remove this if you don't use Moment.js: new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + // Perform type checking and linting in a separate process to speed up compilation + new ForkTsCheckerWebpackPlugin({ + async: false, + tsconfig: paths.appTsConfig, + tslint: paths.appTsLint, + }), ], // 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/package.json b/packages/react-scripts/package.json index 01bb852f5..e299a11b7 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,9 +1,9 @@ { "name": "react-scripts-ts", - "version": "2.8.0", + "version": "2.9.0", "description": "Configuration and scripts for Create React App.", "repository": "wmonk/create-react-app", - "license": "BSD-3-Clause", + "license": "MIT", "engines": { "node": ">=6" }, @@ -21,41 +21,49 @@ "react-scripts-ts": "./bin/react-scripts-ts.js" }, "dependencies": { - "autoprefixer": "7.1.2", + "autoprefixer": "7.1.6", + "babel-core": "6.26.0", + "babel-eslint": "7.2.3", + "babel-jest": "20.0.3", + "babel-loader": "7.1.2", + "babel-preset-react-app": "^3.1.0", + "babel-runtime": "6.26.0", "case-sensitive-paths-webpack-plugin": "2.1.1", "chalk": "1.1.3", - "css-loader": "0.28.4", + "css-loader": "0.28.7", "dotenv": "4.0.0", - "extract-text-webpack-plugin": "3.0.0", - "file-loader": "0.11.2", + "extract-text-webpack-plugin": "3.0.2", + "file-loader": "1.1.5", + "fork-ts-checker-webpack-plugin": "^0.2.8", "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", "jest": "20.0.4", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", - "postcss-loader": "2.0.6", + "postcss-loader": "2.0.8", "promise": "8.0.1", - "react-dev-utils": "^4.0.1", - "style-loader": "0.18.2", - "ts-jest": "^20.0.7", - "ts-loader": "^2.3.7", - "tslint": "^5.7.0", - "tslint-loader": "^3.5.3", - "tslint-react": "^3.2.0", - "typescript": "~2.5.3", - "source-map-loader": "^0.2.1", + "raf": "3.4.0", + "react-dev-utils": "^4.2.1", + "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", - "url-loader": "0.5.9", - "webpack": "3.5.1", - "webpack-dev-server": "2.7.1", - "webpack-manifest-plugin": "1.2.1", - "whatwg-fetch": "2.0.3" + "url-loader": "0.6.2", + "webpack": "3.8.1", + "webpack-dev-server": "2.9.4", + "webpack-manifest-plugin": "1.3.2", + "whatwg-fetch": "2.0.3", + "ts-jest": "^21.1.4", + "ts-loader": "^3.1.1", + "tslint": "^5.8.0", + "tslint-react": "^3.2.0", + "typescript": "~2.6.1", + "source-map-loader": "^0.2.3" }, "devDependencies": { - "react": "^15.5.4", - "react-dom": "^15.5.4" + "react": "^16.0.0", + "react-dom": "^16.0.0" }, "optionalDependencies": { "fsevents": "1.1.2" } } + From 05d5a6cbbb2f60a3547ff581c4aa647844883612 Mon Sep 17 00:00:00 2001 From: Christian Linne Date: Thu, 30 Nov 2017 19:48:42 +0100 Subject: [PATCH 2/5] Merge pull request #199 from DorianGrey/master Adjust 'Testing components' section to use the correct TS versions. --- packages/react-scripts/template/README.md | 36 ++++++++++++++--------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index c55ccdf94..36dcb1c40 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -1244,9 +1244,9 @@ There is a broad spectrum of component testing techniques. They range from a “ Different projects choose different testing tradeoffs based on how often components change, and how much logic they contain. If you haven’t decided on a testing strategy yet, we recommend that you start with creating simple smoke tests for your components: -```js -import React from 'react'; -import ReactDOM from 'react-dom'; +```ts +import * as React from 'react'; +import * asReactDOM from 'react-dom'; import App from './App'; it('renders without crashing', () => { @@ -1255,26 +1255,34 @@ it('renders without crashing', () => { }); ``` -This test mounts a component and makes sure that it didn’t throw during rendering. Tests like this provide a lot value with very little effort so they are great as a starting point, and this is the test you will find in `src/App.test.js`. +This test mounts a component and makes sure that it didn’t throw during rendering. Tests like this provide a lot value with very little effort so they are great as a starting point, and this is the test you will find in `src/App.test.tsx`. When you encounter bugs caused by changing components, you will gain a deeper insight into which parts of them are worth testing in your application. This might be a good time to introduce more specific tests asserting specific expected output or behavior. If you’d like to test components in isolation from the child components they render, we recommend using [`shallow()` rendering API](http://airbnb.io/enzyme/docs/api/shallow.html) from [Enzyme](http://airbnb.io/enzyme/). To install it, run: ```sh -npm install --save enzyme react-test-renderer +npm install --save enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16 react-test-renderer @types/react-test-renderer ``` Alternatively you may use `yarn`: ```sh -yarn add enzyme react-test-renderer +yarn add enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16 react-test-renderer @types/react-test-renderer +``` + +#### `src/setupTests.ts` +```ts +import * as Enzyme from 'enzyme'; +import * as Adapter from 'enzyme-adapter-react-16'; + +Enzyme.configure({ adapter: new Adapter() }); ``` You can write a smoke test with it too: -```js -import React from 'react'; +```ts +import * as React from 'react'; import { shallow } from 'enzyme'; import App from './App'; @@ -1289,8 +1297,8 @@ You can read the [Enzyme documentation](http://airbnb.io/enzyme/) for more testi Here is an example from Enzyme documentation that asserts specific output, rewritten to use Jest matchers: -```js -import React from 'react'; +```ts +import * as React from 'react'; import { shallow } from 'enzyme'; import App from './App'; @@ -1323,7 +1331,7 @@ Alternatively you may use `yarn`: yarn add jest-enzyme ``` -Import it in [`src/setupTests.js`](#initializing-test-environment) to make its matchers available in every test: +Import it in [`src/setupTests.ts`](#initializing-test-environment) to make its matchers available in every test: ```js import 'jest-enzyme'; @@ -1346,12 +1354,12 @@ and then use them in your tests like you normally do. >Note: this feature is available with `react-scripts@0.4.0` and higher. -If your app uses a browser API that you need to mock in your tests or if you just need a global setup before running your tests, add a `src/setupTests.js` to your project. It will be automatically executed before running your tests. +If your app uses a browser API that you need to mock in your tests or if you just need a global setup before running your tests, add a `src/setupTests.ts` to your project. It will be automatically executed before running your tests. For example: -#### `src/setupTests.js` -```js +#### `src/setupTests.ts` +```ts const localStorageMock = { getItem: jest.fn(), setItem: jest.fn(), From 586a50fb207fedd02b3a4d1552e46dd4e8cbe348 Mon Sep 17 00:00:00 2001 From: Christian Linne Date: Wed, 6 Dec 2017 12:40:58 +0100 Subject: [PATCH 3/5] Merge pull request #201 from StefanSchoof/patch-1 Add link to typescript User Guide --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index fddffcbdd..038ab1233 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ Create React apps (with Typescript) with no build configuration. + * [Getting Started](#tldr) – How to create a new app. + * [User Guide](https://github.com/wmonk/create-react-app-typescript/blob/master/packages/react-scripts/template/README.md) – How to develop apps bootstrapped with react scripts ts. + _Do you know react and want to try out typescript? Or do you know typescript and want to try out react?_ Get all the benefits from `create-react-app` but you use typescript! 🚀 ## tl;dr From 10d283eae30c2bce148286bba1688de19af6fd51 Mon Sep 17 00:00:00 2001 From: Christian Linne Date: Wed, 6 Dec 2017 18:48:28 +0100 Subject: [PATCH 4/5] Merge pull request #204 from StefanSchoof/patch-1 @types into devDependencies --- packages/react-scripts/template/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index 36dcb1c40..c57a0ebd7 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -1262,13 +1262,13 @@ When you encounter bugs caused by changing components, you will gain a deeper in If you’d like to test components in isolation from the child components they render, we recommend using [`shallow()` rendering API](http://airbnb.io/enzyme/docs/api/shallow.html) from [Enzyme](http://airbnb.io/enzyme/). To install it, run: ```sh -npm install --save enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16 react-test-renderer @types/react-test-renderer +npm install --save-dev enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16 react-test-renderer @types/react-test-renderer ``` Alternatively you may use `yarn`: ```sh -yarn add enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16 react-test-renderer @types/react-test-renderer +yarn add --dev enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16 react-test-renderer @types/react-test-renderer ``` #### `src/setupTests.ts` From cc52d217b48f7f958b161e2e95ce61c8d71260b3 Mon Sep 17 00:00:00 2001 From: William Monk Date: Thu, 11 Jan 2018 08:44:27 +0000 Subject: [PATCH 5/5] Fix package.json --- packages/react-scripts/package.json | 52 +++++++++++++---------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index e299a11b7..cc3a6f9d1 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -1,9 +1,9 @@ { "name": "react-scripts-ts", - "version": "2.9.0", + "version": "2.8.0", "description": "Configuration and scripts for Create React App.", "repository": "wmonk/create-react-app", - "license": "MIT", + "license": "BSD-3-Clause", "engines": { "node": ">=6" }, @@ -21,46 +21,40 @@ "react-scripts-ts": "./bin/react-scripts-ts.js" }, "dependencies": { - "autoprefixer": "7.1.6", - "babel-core": "6.26.0", - "babel-eslint": "7.2.3", - "babel-jest": "20.0.3", - "babel-loader": "7.1.2", - "babel-preset-react-app": "^3.1.0", - "babel-runtime": "6.26.0", + "autoprefixer": "7.1.2", "case-sensitive-paths-webpack-plugin": "2.1.1", "chalk": "1.1.3", - "css-loader": "0.28.7", + "css-loader": "0.28.4", "dotenv": "4.0.0", - "extract-text-webpack-plugin": "3.0.2", - "file-loader": "1.1.5", + "extract-text-webpack-plugin": "3.0.0", + "file-loader": "0.11.2", "fork-ts-checker-webpack-plugin": "^0.2.8", "fs-extra": "3.0.1", "html-webpack-plugin": "2.29.0", "jest": "20.0.4", "object-assign": "4.1.1", "postcss-flexbugs-fixes": "3.2.0", - "postcss-loader": "2.0.8", + "postcss-loader": "2.0.6", "promise": "8.0.1", - "raf": "3.4.0", - "react-dev-utils": "^4.2.1", - "style-loader": "0.19.0", - "sw-precache-webpack-plugin": "0.11.4", - "url-loader": "0.6.2", - "webpack": "3.8.1", - "webpack-dev-server": "2.9.4", - "webpack-manifest-plugin": "1.3.2", - "whatwg-fetch": "2.0.3", - "ts-jest": "^21.1.4", - "ts-loader": "^3.1.1", - "tslint": "^5.8.0", + "react-dev-utils": "^4.0.1", + "style-loader": "0.18.2", + "ts-jest": "^20.0.7", + "ts-loader": "^2.3.7", + "tslint": "^5.7.0", + "tslint-loader": "^3.5.3", "tslint-react": "^3.2.0", - "typescript": "~2.6.1", - "source-map-loader": "^0.2.3" + "typescript": "~2.5.3", + "source-map-loader": "^0.2.1", + "sw-precache-webpack-plugin": "0.11.4", + "url-loader": "0.5.9", + "webpack": "3.5.1", + "webpack-dev-server": "2.7.1", + "webpack-manifest-plugin": "1.2.1", + "whatwg-fetch": "2.0.3" }, "devDependencies": { - "react": "^16.0.0", - "react-dom": "^16.0.0" + "react": "^15.5.4", + "react-dom": "^15.5.4" }, "optionalDependencies": { "fsevents": "1.1.2"