Skip to content

Commit 24fd718

Browse files
authored
drop flow, use typescript (#57)
* drop flow, use typescript * several fixes * smallish fixes * added dependency-graph gimmick
1 parent 5b117c5 commit 24fd718

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+906
-555
lines changed

.circleci/config.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
version: 2
2+
jobs:
3+
build:
4+
docker:
5+
- image: circleci/node:10.15
6+
7+
working_directory: ~/repo
8+
9+
steps:
10+
- checkout
11+
12+
# Download and cache dependencies
13+
- restore_cache:
14+
keys:
15+
- v1-dependencies-{{ checksum "package.json" }}
16+
# fallback to using the latest cache if no exact match is found
17+
- v1-dependencies-
18+
19+
- run: yarn install
20+
21+
- save_cache:
22+
paths:
23+
- node_modules
24+
key: v1-dependencies-{{ checksum "package.json" }}
25+
26+
# run tests!
27+
- run: yarn lint
28+
29+
- run: yarn tsc
30+
31+
- run: yarn test

.dependency-cruiser.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ module.exports = {
7979
},
8080
],
8181
options: {
82+
tsConfig: {
83+
fileName: 'tsconfig.json',
84+
},
8285
/* conditions specifying which files not to follow further when encountered:
8386
- path: a regular expression to match
8487
- dependencyTypes: see https://github.com/sverweij/dependency-cruiser/blob/develop/doc/rules-reference.md#dependencytypes
@@ -99,7 +102,7 @@ module.exports = {
99102
/* pattern specifying which files to exclude (regular expression) */
100103
// , exclude : ''
101104

102-
/* pattern specifying which files to include (regular expression)
105+
/* pattern specifying which files to include (regular expression)
103106
dependency-cruiser will skip everything not matching this pattern
104107
*/
105108
// , includeOnly : ''

.eslintignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
**/node_modules
22
**/public
33
src/frontend/config/env.js
4-
**/build
4+
**/build
5+
*.d.ts

.eslintrc.js

+3-13
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,26 @@
11
const paths = require('./config/paths');
22

33
module.exports = {
4-
extends: [
5-
'wiremore',
6-
'wiremore/react',
7-
'prettier',
8-
'prettier/react',
9-
'plugin:flowtype/recommended',
10-
'plugin:import/errors',
11-
'plugin:import/warnings',
12-
'plugin:prettier/recommended',
13-
'plugin:security/recommended',
14-
],
4+
extends: ['wiremore', 'wiremore/react', 'wiremore/typescript'],
155
globals: {
166
__BROWSER__: true,
177
__SERVER__: true,
188
},
19-
plugins: ['babel', 'import', 'prettier', 'flowtype', 'security'],
209
settings: {
2110
'import/resolver': {
2211
node: {
2312
paths: paths.resolveModules,
13+
extensions: ['.js', '.jsx', '.ts', '.tsx'],
2414
},
2515
},
2616
react: {
2717
version: 'detect',
2818
},
2919
},
3020
rules: {
31-
'import/named': 0,
3221
'import/no-unassigned-import': 0,
3322
'import/no-named-as-default-member': 0,
3423
'prettier/prettier': 'error',
3524
},
25+
// overrides: [{ files: ['*.tsx'], rules: { 'import/named': 0 } }],
3626
};

.flowconfig

-28
This file was deleted.

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ yarn-error.log
1515
tmp
1616
bundle-stats.json
1717
.vscode
18+
/dependency-graph.svg

.lintstagedrc

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"linters": {
3-
"*.{js,jsx,css}": [
3+
"*.{js,jsx,ts,tsx,css}": [
44
"prettier --write",
55
"git add"
66
],
7-
"*.{js,jsx}": [
8-
"eslint src --fix",
7+
"*.{js,jsx,ts,tsx}": [
8+
"yarn lint:js --fix",
99
"git add"
1010
],
1111
"*.css": [
12-
"stylelint src/**/*.css --fix",
12+
"yarn lint:css --fix",
1313
"git add"
1414
]
1515
}

.prettierrc

+3
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ overrides:
99
- files: "*.json"
1010
options:
1111
tabWidth: 2
12+
- files: "*.yml"
13+
options:
14+
tabWidth: 2

.stylelintrc

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66
"extends": ["stylelint-prettier/recommended"],
77
"rules": {
88
"declaration-block-no-shorthand-property-overrides": [true, { "severity": "warning" } ],
9-
"order/properties-alphabetical-order": true
9+
"order/properties-alphabetical-order": true,
10+
"color-no-invalid-hex": true,
11+
"font-family-no-duplicate-names": true,
12+
"function-calc-no-invalid": true,
13+
"function-calc-no-unspaced-operator": true,
14+
"unit-no-unknown": true,
15+
"property-no-unknown": [true, { "severity": "warning" }],
16+
"block-no-empty": true,
17+
"no-duplicate-at-import-rules": true,
18+
"no-extra-semicolons": true,
19+
"no-invalid-double-slash-comments": true
1020
}
1121
}

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 3.0.0-beta.0 (2019-05-02)
4+
5+
- Dropped Flow Type in favor of TypeScript (sorry Flow, but the battle is lost)
6+
37
## 2.9.0 (2019-04-28)
48

59
- Experimentally added dependency-cruiser

README.md

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# ⚛ React + Express – SSR Setup
1+
# ⚛ React + Express – SSR Setup with TypeScript
22

33
[![Maintainability](https://api.codeclimate.com/v1/badges/085d871cd62fe4435865/maintainability)](https://codeclimate.com/github/manuelbieh/react-ssr-setup/maintainability)
44
[![dependencies Status](https://david-dm.org/manuelbieh/react-ssr-setup/status.svg)](https://david-dm.org/manuelbieh/react-ssr-setup)
55
[![Known Vulnerabilities](https://snyk.io/test/github/manuelbieh/react-ssr-setup/badge.svg)](https://snyk.io/test/github/manuelbieh/react-ssr-setup)
66
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
77

88
**Advertising**: I wrote a book about React. If you speak German, buy it here: [https://leanpub.com/react-lernen](https://leanpub.com/react-lernen)!
9-
9+
1010
[![](./src/shared/assets/book-cover-small.png)](https://leanpub.com/react-lernen)
1111

1212
## TOC
@@ -24,6 +24,7 @@
2424
- [Avoid source map generation for faster builds](#avoid-source-map-generation-for-faster-builds)
2525
- [Change the port of the dev environment](#change-the-port-of-the-dev-environment)
2626
- [Import SVGs as ReactComponent](#import-svgs-as-reactcomponent)
27+
- [Use plain JavaScript instead of TypeScript](#use-plain-javascript-instead-of-typescript)
2728
- [Caveats](#caveats)
2829
- [Todo](#todo)
2930
- [Changelog](#changelog)
@@ -50,9 +51,9 @@ This project has out-of-the-box support for the following things:
5051

5152
- General Setup
5253
- 🔥 Babel 7
53-
- 🔥 Webpack 4
54+
- 📦 Webpack 4
5455
- 🔥 ESLint 5 (with a set of custom rules which may be mostly identical to AirBnB with some personal flavor added)
55-
- 🔥 Flow Type
56+
- 🔥 TypeScript (via Babel)
5657
- 🔥 Prettier
5758
- 🔥 Jest 24
5859
- ✅ Server Side Rendering with Express
@@ -168,6 +169,18 @@ Then you can use it in JSX like `<div><Logo /></div>`.
168169

169170
[Here is a video](https://egghead.io/lessons/react-add-svgs-as-react-components-with-create-react-app-2-0) that explains that a bit more.
170171

172+
### Use plain JavaScript instead of TypeScript
173+
174+
You can just do it‬™. Really. Name your files `.js` instead of `.ts`/`.tsx` and you should not be bothered by TypeScript anymore. If you want to _fully_ remove TypeScript:
175+
176+
- remove the `@babel/typescript` preset from `babel.config.js`
177+
- uninstall TypeScript: `yarn remove typescript @babel/preset-typescript`
178+
- uninstall all dependencies beginning with `@types/`
179+
- delete `tsconfig.json` and `src/global.d.ts`
180+
- remove `wiremore/typescript` from the `extends` section in `.eslintrc.js`
181+
- remove all types from all files if there still are any
182+
- remove `tsConfig` option from `.dependency-cruiser.js`
183+
171184
## Caveats
172185

173186
- ~~[1] MiniCSSExtractPlugin doesn't play nicely with consecutive builds in Webpack's watchmode yet ([Github issue here](https://github.com/webpack-contrib/mini-css-extract-plugin/issues/23)). So I'm using ExtractTextWebpackPlugin until this is fixed~~ Fixed! [490e6e9](https://github.com/manuelbieh/react-ssr-setup/commit/490e6e95fc811b0ce42d1bbc1252d3f26c4bd1ab)
@@ -184,7 +197,7 @@ Then you can use it in JSX like `<div><Logo /></div>`.
184197
- [x] ~~Add `react-loadable` or `react-universal-component` (or both, still investigating what makes most sense). **Update:** `react-loadable` is out due to [questionable license change](https://github.com/jamiebuilds/react-loadable/commit/c3272b3132e4fe25937c3610b7cd0dd2da48c5e9)~~ Just use React.lazy which was introduced in React 16.6.
185198
- [x] Improve server side template
186199
- [x] Add (and use) `react-helmet`
187-
- [ ] Add/improve server side chunk loading
200+
- [ ] ~~Add/improve server side chunk loading~~ - Wait for the new React Fizz Renderer to land
188201
- [x] Add test setup using Jest
189202
- [ ] Add `optimize-css-assets-webpack-plugin` and `postcss-safe-parser` similar to how CRA 2 is doing it
190203
- [x] Modify ~~`svg-loader`~~ `babel-loader` so SVGs can be imported as React component (see CRA 2)

babel.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = {
1111
},
1212
],
1313
'@babel/react',
14-
'@babel/flow',
14+
'@babel/typescript',
1515
],
1616
plugins: [
1717
'@babel/proposal-object-rest-spread',

config/filetypes.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = ['js', 'jsx', 'ts', 'tsx', 'mjs'];

config/paths.js

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const paths = {
1313
srcClient: resolveApp('src/client'),
1414
srcServer: resolveApp('src/server'),
1515
srcShared: resolveApp('src/shared'),
16+
types: resolveApp('node_modules/@types'),
1617
publicPath: '/static/',
1718
};
1819

config/plop/component/component.js.plop

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
{{#if useFlow}}// @flow
2-
import * as React from 'react';
3-
4-
type PropsT = {};
5-
{{else}}
61
import React from 'react';
7-
{{/if}}
82

9-
const {{pascalCase componentName}} = (props{{#if useFlow}}: PropsT{{/if}}) => {
3+
const {{pascalCase componentName}} = (props) => {
104
return <div />;
115
};
126

config/plop/reducer/actions.js.plop

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// @flow
2-
// import type { Dispatch } from 'redux';
3-
41
export const ActionTypes = {
52
{{upperCase (snakeCase reducerName) }}_REQUEST: '{{pkg 'name'}}/{{dashCase reducerName}}/request',
63
{{upperCase (snakeCase reducerName) }}_SUCCESS: '{{pkg 'name'}}/{{dashCase reducerName}}/success',
@@ -12,7 +9,7 @@ export const {{pascalCase reducerName}}Request = () => ({
129
type: ActionTypes.{{upperCase (snakeCase reducerName)}}_REQUEST,
1310
});
1411

15-
export const {{pascalCase reducerName}}Success = (items: {{pascalCase reducerName}}T[]) => ({
12+
export const {{pascalCase reducerName}}Success = (items: {{pascalCase reducerName}}[]) => ({
1613
type: ActionTypes.{{upperCase (snakeCase reducerName)}}_SUCCESS,
1714
payload: {
1815
items,

config/plop/reducer/reducer.js.plop

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
// @flow
21
import { ActionTypes } from './actions';
3-
import type { ActionT, {{pascalCase reducerName}}StateT } from './types';
2+
import { Action, {{pascalCase reducerName}}State } from './types';
43

5-
export const initialState: {{pascalCase reducerName}}StateT = Object.freeze({
4+
export const initialState: {{pascalCase reducerName}}State = Object.freeze({
65
didInvalidate: false,
76
isLoading: false,
87
items: [],
98
updatedAt: null,
109
});
1110

12-
export default (state: {{pascalCase reducerName}}StateT = initialState, action: ActionT) => {
11+
export default (state: {{pascalCase reducerName}}State = initialState, action: Action) => {
1312
switch (action.type) {
1413
case ActionTypes.{{upperCase (snakeCase reducerName)}}_REQUEST:
1514
return {

config/plop/reducer/selectors.js.plop

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
// @flow
21
import { createSelector } from 'reselect';
3-
import type { {{pascalCase reducerName}}StateT } from './types';
2+
import { {{pascalCase reducerName}}State } from './types';
43

54
// Cache TTL in Milliseconds
65
const CACHE_TTL = 60 * 1000;
76

8-
export const get{{pascalCase reducerName}} = (state: { {{camelCase reducerName}}: {{pascalCase reducerName}}StateT }) => state.{{camelCase reducerName}} || {};
7+
export const get{{pascalCase reducerName}} = (state: { {{camelCase reducerName}}: {{pascalCase reducerName}}State }) => state.{{camelCase reducerName}} || {};
98

109
export const get{{pascalCase reducerName}}Items = createSelector(
1110
[get{{pascalCase reducerName}}],
12-
({{camelCase reducerName}}): Array<*> => {
11+
({{camelCase reducerName}}): Array<any> => {
1312
return {{camelCase reducerName}}.items;
1413
}
1514
);
1615

17-
export const isExpired = (state: { {{camelCase reducerName}}: {{pascalCase reducerName}}StateT }): boolean => {
16+
export const isExpired = (state: { {{camelCase reducerName}}: {{pascalCase reducerName}}State }): boolean => {
1817
const { updatedAt, didInvalidate } = get{{pascalCase reducerName}}(state);
1918
if (didInvalidate === true || !updatedAt || Date.now() - updatedAt > CACHE_TTL) {
2019
return true;

config/plop/reducer/types.js.plop

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
// @flow
2-
export type {{pascalCase reducerName}}StateT = {
1+
export {{pascalCase reducerName}}State = {
32
didInvalidate: boolean,
43
isLoading: boolean,
5-
items: {{pascalCase reducerName}}T[],
6-
updatedAt: ?number,
4+
items: {{pascalCase reducerName}}[],
5+
updatedAt: number | null,
76
};
87

9-
export type {{pascalCase reducerName}}T = {};
8+
export type {{pascalCase reducerName}} = {};
109

11-
export type GenericActionT = {
10+
export type GenericAction = {
1211
type: '{{pkg 'name'}}/{{dashCase reducerName}}/request' | '{{pkg 'name'}}/{{dashCase reducerName}}/invalidate',
1312
};
1413

15-
export type ActionT = GenericActionT;
14+
export type Action = GenericAction;

config/webpack.config.js/client.base.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
const path = require('path');
2+
const TerserPlugin = require('terser-webpack-plugin');
23
const paths = require('../paths');
34
const { client: clientLoaders } = require('./loaders');
45
const resolvers = require('./resolvers');
56
const plugins = require('./plugins');
6-
const TerserPlugin = require('terser-webpack-plugin');
77
const generateSourceMap = process.env.OMIT_SOURCEMAP === 'true' ? false : true;
88

99
module.exports = {
@@ -13,7 +13,7 @@ module.exports = {
1313
bundle: [
1414
require.resolve('core-js/stable'),
1515
require.resolve('regenerator-runtime/runtime'),
16-
`${paths.srcClient}/index.js`,
16+
paths.srcClient,
1717
],
1818
},
1919
output: {

0 commit comments

Comments
 (0)