mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-06-15 01:49:27 +08:00
@@ -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
|
||||
|
||||
10
packages/react-scripts/config/paths.js
vendored
10
packages/react-scripts/config/paths.js
vendored
@@ -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')),
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"dotenv": "4.0.0",
|
||||
"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",
|
||||
@@ -59,3 +60,4 @@
|
||||
"fsevents": "1.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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-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 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`
|
||||
```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(),
|
||||
|
||||
Reference in New Issue
Block a user