Skip to content

Commit 0d4d7f4

Browse files
committed
ctco-dev: add typescript
1 parent 2578712 commit 0d4d7f4

17 files changed

+295
-33
lines changed

packages/react-scripts/config/paths.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@ module.exports = {
5252
appBuild: resolveApp('build'),
5353
appPublic: resolveApp('public'),
5454
appHtml: resolveApp('public/index.html'),
55-
appIndexJs: resolveApp('src/index.js'),
55+
appIndexJs: resolveApp('src/index.tsx'),
5656
appPackageJson: resolveApp('package.json'),
5757
appSrc: resolveApp('src'),
5858
yarnLockFile: resolveApp('yarn.lock'),
59-
testsSetup: resolveApp('src/setupTests.js'),
59+
testsSetup: resolveApp('src/setupTests.ts'),
6060
appNodeModules: resolveApp('node_modules'),
61+
appTsConfig: resolveApp('tsconfig.json'),
62+
appTsProdConfig: resolveApp('tsconfig.prod.json'),
63+
appTsLint: resolveApp('tslint.json'),
6164
publicUrl: getPublicUrl(resolveApp('package.json')),
6265
servedPath: getServedPath(resolveApp('package.json')),
6366
};
@@ -72,12 +75,16 @@ module.exports = {
7275
appBuild: resolveApp('build'),
7376
appPublic: resolveApp('public'),
7477
appHtml: resolveApp('public/index.html'),
75-
appIndexJs: resolveApp('src/index.js'),
78+
appIndexJs: resolveApp('src/index.tsx'),
7679
appPackageJson: resolveApp('package.json'),
7780
appSrc: resolveApp('src'),
7881
yarnLockFile: resolveApp('yarn.lock'),
79-
testsSetup: resolveApp('src/setupTests.js'),
82+
testsSetup: resolveApp('src/setupTests.ts'),
8083
appNodeModules: resolveApp('node_modules'),
84+
appTsConfig: resolveApp('tsconfig.json'),
85+
appTsProdConfig: resolveApp('tsconfig.prod.json'),
86+
appTsTestConfig: resolveApp('tsconfig.test.json'),
87+
appTsLint: resolveApp('tslint.json'),
8188
publicUrl: getPublicUrl(resolveApp('package.json')),
8289
servedPath: getServedPath(resolveApp('package.json')),
8390
// These properties only exist before ejecting:
@@ -102,12 +109,16 @@ if (
102109
appBuild: resolveOwn('../../build'),
103110
appPublic: resolveOwn('template/public'),
104111
appHtml: resolveOwn('template/public/index.html'),
105-
appIndexJs: resolveOwn('template/src/index.js'),
112+
appIndexJs: resolveOwn('template/src/index.tsx'),
106113
appPackageJson: resolveOwn('package.json'),
107114
appSrc: resolveOwn('template/src'),
108115
yarnLockFile: resolveOwn('template/yarn.lock'),
109-
testsSetup: resolveOwn('template/src/setupTests.js'),
116+
testsSetup: resolveOwn('template/src/setupTests.ts'),
110117
appNodeModules: resolveOwn('node_modules'),
118+
appTsConfig: resolveOwn('template/tsconfig.json'),
119+
appTsProdConfig: resolveOwn('template/tsconfig.prod.json'),
120+
appTsLint: resolveOwn('template/tslint.json'),
121+
appTsTestConfig: resolveOwn('template/tsconfig.test.json'),
111122
publicUrl: getPublicUrl(resolveOwn('package.json')),
112123
servedPath: getServedPath(resolveOwn('package.json')),
113124
// These properties only exist before ejecting:

packages/react-scripts/config/webpack.config.dev.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const eslintFormatter = require('react-dev-utils/eslintFormatter');
1919
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
2020
const getClientEnvironment = require('./env');
2121
const paths = require('./paths');
22+
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
2223

2324
// Webpack uses `publicPath` to determine where the app is being served from.
2425
// In development, we always serve from the root. This makes config easier.
@@ -90,7 +91,18 @@ module.exports = {
9091
// https://github.com/facebookincubator/create-react-app/issues/290
9192
// `web` extension prefixes have been added for better support
9293
// for React Native Web.
93-
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
94+
extensions: [
95+
'.web.js',
96+
'.mjs',
97+
'.js',
98+
'.json',
99+
'.web.jsx',
100+
'.jsx',
101+
'.web.ts',
102+
'.ts',
103+
'.web.tsx',
104+
'.tsx',
105+
],
94106
alias: {
95107
// @remove-on-eject-begin
96108
// Resolve Babel runtime relative to react-scripts.
@@ -176,6 +188,21 @@ module.exports = {
176188
cacheDirectory: true,
177189
},
178190
},
191+
192+
// Process Typescript files
193+
{
194+
test: /\.tsx?$/,
195+
include: paths.appSrc,
196+
use: [
197+
{
198+
loader: require.resolve('ts-loader'),
199+
options: {
200+
// disable type checker - we will use it in fork plugin
201+
transpileOnly: true,
202+
},
203+
},
204+
],
205+
},
179206
// "postcss" loader applies autoprefixer to our CSS.
180207
// "css" loader resolves paths in CSS and adds assets as dependencies.
181208
// "style" loader turns CSS into JS modules that inject <style> tags.
@@ -268,6 +295,13 @@ module.exports = {
268295
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
269296
// You can remove this if you don't use Moment.js:
270297
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
298+
// Perform type checking and linting in a separate process to speed up compilation
299+
new ForkTsCheckerWebpackPlugin({
300+
async: false,
301+
watch: paths.appSrc, // optional but improves performance (less stat calls)
302+
tsconfig: paths.appTsConfig,
303+
tslint: paths.appTsLint,
304+
}),
271305
],
272306
// Some libraries import Node modules but don't use them in the browser.
273307
// Tell Webpack to provide empty mocks for them so importing them works.

packages/react-scripts/config/webpack.config.prod.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const eslintFormatter = require('react-dev-utils/eslintFormatter');
2020
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
2121
const paths = require('./paths');
2222
const getClientEnvironment = require('./env');
23+
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
2324

2425
// Webpack uses `publicPath` to determine where the app is being served from.
2526
// It requires a trailing slash, or the file assets will get an incorrect path.
@@ -96,7 +97,18 @@ module.exports = {
9697
// https://github.com/facebookincubator/create-react-app/issues/290
9798
// `web` extension prefixes have been added for better support
9899
// for React Native Web.
99-
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
100+
extensions: [
101+
'.web.js',
102+
'.mjs',
103+
'.js',
104+
'.json',
105+
'.web.jsx',
106+
'.jsx',
107+
'.web.ts',
108+
'.ts',
109+
'.web.tsx',
110+
'.tsx',
111+
],
100112
alias: {
101113
// @remove-on-eject-begin
102114
// Resolve Babel runtime relative to react-scripts.
@@ -180,6 +192,21 @@ module.exports = {
180192
compact: true,
181193
},
182194
},
195+
// Process Typescript files
196+
{
197+
test: /\.tsx?$/,
198+
include: paths.appSrc,
199+
use: [
200+
{
201+
loader: require.resolve('ts-loader'),
202+
options: {
203+
// disable type checker - we will use it in fork plugin
204+
transpileOnly: true,
205+
configFile: paths.appTsProdConfig,
206+
},
207+
},
208+
],
209+
},
183210
// The notation here is somewhat confusing.
184211
// "postcss" loader applies autoprefixer to our CSS.
185212
// "css" loader resolves paths in CSS and adds assets as dependencies.
@@ -350,6 +377,13 @@ module.exports = {
350377
// Don't precache sourcemaps (they're large) and build asset manifest:
351378
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
352379
}),
380+
// Perform type checking and linting in a separate process to speed up compilation
381+
new ForkTsCheckerWebpackPlugin({
382+
async: false,
383+
watch: paths.appSrc, // optional but improves performance (less stat calls)
384+
tsconfig: paths.appTsProdConfig,
385+
tslint: paths.appTsLint,
386+
}),
353387
// Moment.js is an extremely popular library that bundles large locale files
354388
// by default due to how Webpack interprets its code. This is a practical
355389
// solution that requires the user to opt into importing specific locales.

packages/react-scripts/package.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@aeldar/react-scripts",
3-
"version": "1.1.4-3",
3+
"version": "1.1.4-6",
44
"description": "Configuration and scripts for Create React App. Modified by @aeldar",
55
"repository": "aeldar/create-react-app",
66
"license": "MIT",
@@ -42,9 +42,10 @@
4242
"eslint-plugin-react": "7.4.0",
4343
"extract-text-webpack-plugin": "3.0.2",
4444
"file-loader": "1.1.5",
45+
"fork-ts-checker-webpack-plugin": "0.4.4",
4546
"fs-extra": "3.0.1",
4647
"html-webpack-plugin": "2.29.0",
47-
"jest": "20.0.4",
48+
"jest": "^23.4.2",
4849
"object-assign": "4.1.1",
4950
"postcss-flexbugs-fixes": "3.2.0",
5051
"postcss-loader": "2.0.8",
@@ -54,6 +55,12 @@
5455
"resolve": "1.6.0",
5556
"style-loader": "0.19.0",
5657
"sw-precache-webpack-plugin": "0.11.4",
58+
"ts-jest": "23.1.3",
59+
"ts-loader": "3.5.0",
60+
"tslint": "5.11.0",
61+
"tslint-config-airbnb": "5.9.2",
62+
"tslint-config-prettier": "1.14.0",
63+
"tslint-react": "3.6.0",
5764
"url-loader": "0.6.2",
5865
"webpack": "3.8.1",
5966
"webpack-dev-server": "2.9.4",
@@ -62,7 +69,11 @@
6269
},
6370
"devDependencies": {
6471
"react": "^16.0.0",
65-
"react-dom": "^16.0.0"
72+
"react-dom": "^16.0.0",
73+
"typescript": "^3.0.1"
74+
},
75+
"peerDependencies": {
76+
"typescript": "^3.0.1"
6677
},
6778
"optionalDependencies": {
6879
"fsevents": "^1.1.3"

packages/react-scripts/scripts/init.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,26 @@ module.exports = function(
9999
command = 'npm';
100100
args = ['install', '--save', verbose && '--verbose'].filter(e => e);
101101
}
102-
args.push('react', 'react-dom');
102+
103+
// Install devDependencies
104+
const devDependencies = require('./utils/devDependencies');
105+
console.log(
106+
`Installing ${devDependencies.join(
107+
', '
108+
)} as dev dependencies using ${command}...`
109+
);
110+
console.log();
111+
const devProc = spawn.sync(
112+
command,
113+
args.concat('-D').concat(devDependencies),
114+
{ stdio: 'inherit' }
115+
);
116+
if (devProc.status !== 0) {
117+
console.error(
118+
`\`${command} ${args.concat(devDependencies).join(' ')}\` failed`
119+
);
120+
return;
121+
}
103122

104123
// Install additional template dependencies, if present
105124
const templateDependenciesPath = path.join(
@@ -123,7 +142,9 @@ module.exports = function(
123142
console.log(`Installing react and react-dom using ${command}...`);
124143
console.log();
125144

126-
const proc = spawn.sync(command, args, { stdio: 'inherit' });
145+
const proc = spawn.sync(command, args.concat(['react', 'react-dom']), {
146+
stdio: 'inherit',
147+
});
127148
if (proc.status !== 0) {
128149
console.error(`\`${command} ${args.join(' ')}\` failed`);
129150
return;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = ['react', 'react-dom'];
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
module.exports = [
4+
'@types/node',
5+
'@types/react',
6+
'@types/react-dom',
7+
'@types/jest',
8+
'typescript',
9+
];
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
declare module '*.svg'
2+
declare module '*.png'
3+
declare module '*.jpg'

packages/react-scripts/template/src/App.test.js renamed to packages/react-scripts/template/src/App.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React from 'react';
2-
import ReactDOM from 'react-dom';
1+
import * as React from 'react';
2+
import * as ReactDOM from 'react-dom';
33
import App from './App';
44

55
it('renders without crashing', () => {

packages/react-scripts/template/src/App.js renamed to packages/react-scripts/template/src/App.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import React, { Component } from 'react';
1+
import * as React from 'react';
22
import logo from './logo.svg';
33
import './App.css';
44

5-
class App extends Component {
5+
class App extends React.Component {
66
render() {
77
return (
88
<div className="App">
99
<header className="App-header">
1010
<img src={logo} className="App-logo" alt="logo" />
11-
<h1 className="App-title">Welcome to React</h1>
11+
<h1 className="App-title">Welcome to React!</h1>
1212
</header>
1313
<p className="App-intro">
14-
To get started, edit <code>src/App.js</code> and save to reload.
14+
To get started, edit <code>src/App.tsx</code> and save to reload.
1515
</p>
1616
</div>
1717
);

packages/react-scripts/template/src/index.js

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as React from 'react';
2+
import * as ReactDOM from 'react-dom';
3+
import './index.css';
4+
import App from './App';
5+
import registerServiceWorker from './registerServiceWorker';
6+
7+
ReactDOM.render(<App />, document.getElementById('root') as HTMLElement);
8+
registerServiceWorker();

packages/react-scripts/template/src/registerServiceWorker.js renamed to packages/react-scripts/template/src/registerServiceWorker.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const isLocalhost = Boolean(
2121
export default function register() {
2222
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
2323
// The URL constructor is available in all browsers that support SW.
24-
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
24+
const publicUrl = new URL(process.env.PUBLIC_URL as string, (window as any).location);
2525
if (publicUrl.origin !== window.location.origin) {
2626
// Our service worker won't work if PUBLIC_URL is on a different origin
2727
// from what our page is served on. This might happen if a CDN is used to
@@ -52,14 +52,14 @@ export default function register() {
5252
}
5353
}
5454

55-
function registerValidSW(swUrl) {
55+
function registerValidSW(swUrl: string) {
5656
navigator.serviceWorker
5757
.register(swUrl)
5858
.then(registration => {
5959
registration.onupdatefound = () => {
6060
const installingWorker = registration.installing;
61-
installingWorker.onstatechange = () => {
62-
if (installingWorker.state === 'installed') {
61+
installingWorker!.onstatechange = () => {
62+
if (installingWorker!.state === 'installed') {
6363
if (navigator.serviceWorker.controller) {
6464
// At this point, the old content will have been purged and
6565
// the fresh content will have been added to the cache.
@@ -81,14 +81,14 @@ function registerValidSW(swUrl) {
8181
});
8282
}
8383

84-
function checkValidServiceWorker(swUrl) {
84+
function checkValidServiceWorker(swUrl: string) {
8585
// Check if the service worker can be found. If it can't reload the page.
8686
fetch(swUrl)
8787
.then(response => {
8888
// Ensure service worker exists, and that we really are getting a JS file.
8989
if (
9090
response.status === 404 ||
91-
response.headers.get('content-type').indexOf('javascript') === -1
91+
response.headers.get('content-type')!.indexOf('javascript') === -1
9292
) {
9393
// No service worker found. Probably a different app. Reload the page.
9494
navigator.serviceWorker.ready.then(registration => {

0 commit comments

Comments
 (0)