diff --git a/.eslintrc.js b/.eslintrc.js index d5f44b0b5..3f59d0835 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,18 +10,21 @@ // ESLint configuration // http://eslint.org/docs/user-guide/configuring module.exports = { - parser: 'babel-eslint', + parser: '@typescript-eslint/parser', extends: [ 'airbnb', - 'plugin:flowtype/recommended', 'plugin:css-modules/recommended', 'prettier', - 'prettier/flowtype', 'prettier/react', ], - plugins: ['flowtype', 'css-modules', 'prettier'], + plugins: ['@typescript-eslint/eslint-plugin', 'css-modules', 'prettier'], + + parserOptions: { + sourceType: 'module', + project: './tsconfig.json', + }, globals: { __DEV__: true, @@ -46,6 +49,15 @@ module.exports = { }, ], + // Allow only special identifiers + // https://eslint.org/docs/rules/no-underscore-dangle + 'no-underscore-dangle': [ + 'error', + { + allow: ['__typename', '__DEV__'], + }, + ], + // Prefer destructuring from arrays and objects // http://eslint.org/docs/rules/prefer-destructuring 'prefer-destructuring': [ @@ -78,7 +90,7 @@ module.exports = { // Allow .js files to use JSX syntax // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md - 'react/jsx-filename-extension': ['error', { extensions: ['.js', '.jsx'] }], + 'react/jsx-filename-extension': [1, { extensions: ['.ts', '.tsx'] }], // Functional and class components are equivalent from React’s point of view // https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md @@ -87,15 +99,32 @@ module.exports = { // ESLint plugin for prettier formatting // https://github.com/prettier/eslint-plugin-prettier 'prettier/prettier': 'error', - }, - settings: { - // Allow absolute paths in imports, e.g. import Button from 'components/Button' - // https://github.com/benmosher/eslint-plugin-import/tree/master/resolvers - 'import/resolver': { - node: { - moduleDirectory: ['node_modules', 'src'], + 'react/forbid-prop-types': 'off', + 'react/destructuring-assignment': 'off', + // TypeScript types checks prop-types + 'react/prop-types': 'off', + + // PropTypes and states are typed by Flow basically, but Flow cannot type defaultProps. + 'react/require-default-props': 'off', + + // Cannot config .ts, .tsx resolution + 'import/no-unresolved': 'off', + + 'import/no-webpack-loader-syntax': 'off', + + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + vars: 'local', + args: 'after-used', + ignoreRestSiblings: false, + argsIgnorePattern: '^_', }, - }, + ], + + // Type variables by Codegen can not be camelcase. + camelcase: 'off', }, }; diff --git a/.flowconfig b/.flowconfig index f111649a9..4e334642c 100644 --- a/.flowconfig +++ b/.flowconfig @@ -7,5 +7,14 @@ [include] [options] -module.system.node.resolve_dirname=node_modules -module.system.node.resolve_dirname=src +suppress_comment=\\(.\\|\n\\)*\\$FlowExpectError +module.file_ext=.js +module.file_ext=.jsx +module.file_ext=.json +module.file_ext=.css +module.file_ext=.scss +module.file_ext=.graphql +module.name_mapper.extension='json' -> 'empty/object' +module.name_mapper.extension='css' -> 'empty/object' +module.name_mapper.extension='scss' -> 'empty/object' +module.name_mapper.extension='graphql' -> 'empty/object' diff --git a/.gitignore b/.gitignore index 1a0fe2e26..0816d0cd2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ node_modules/ # Compiled output build +# Generate Types +__generated__ + # Runtime data database.sqlite diff --git a/.travis.yml b/.travis.yml index e2790b341..743316249 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js node_js: - 'stable' + - '10' - '8' - - '6' env: - CXX=g++-4.8 addons: diff --git a/README.md b/README.md index 545e088b3..c8378dad0 100644 --- a/README.md +++ b/README.md @@ -21,31 +21,29 @@ and newcomers to the industry. Hiring

- ### Getting Started - * Follow the [getting started guide](./docs/getting-started.md) to download and run the project - ([Node.js](https://nodejs.org/) >= 6.5) - * Check the [code recipes](./docs/recipes) used in this boilerplate, or share yours - +- Follow the [getting started guide](./docs/getting-started.md) to download and run the project + ([Node.js](https://nodejs.org/) >= 6.5) +- Check the [code recipes](./docs/recipes) used in this boilerplate, or share yours ### Customization The `master` branch of React Starter Kit doesn't include a Flux implementation or any other -advanced integrations. Nevertheless, we have some integrations available to you in *feature* +advanced integrations. Nevertheless, we have some integrations available to you in _feature_ branches that you can use either as a reference or merge into your project: - * [feature/redux](https://github.com/kriasoft/react-starter-kit/tree/feature/redux) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1084)) - — isomorphic Redux by [Pavel Lang](https://github.com/langpavel) - (see [how to integrate Redux](./docs/recipes/how-to-integrate-redux.md)) (based on `master`) - * [feature/apollo](https://github.com/kriasoft/react-starter-kit/tree/feature/apollo) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1147)) - — isomorphic Apollo Client by [Pavel Lang](https://github.com/langpavel) - (see [Tracking PR #1147](https://github.com/kriasoft/react-starter-kit/pull/1147)) (based on `feature/redux`) - * [feature/react-intl](https://github.com/kriasoft/react-starter-kit/tree/feature/react-intl) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1135)) - — isomorphic Redux and React Intl by [Pavel Lang](https://github.com/langpavel) - (see [how to integrate React Intl](./docs/recipes/how-to-integrate-react-intl.md)) (based on `feature/apollo`) - * [feature/apollo-pure](https://github.com/kriasoft/react-starter-kit/tree/feature/apollo-pure) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1664)) - — bare Apollo codebase by [piglovesyou](https://github.com/piglovesyou) (based on `master`) +- [feature/redux](https://github.com/kriasoft/react-starter-kit/tree/feature/redux) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1084)) + — isomorphic Redux by [Pavel Lang](https://github.com/langpavel) + (see [how to integrate Redux](./docs/recipes/how-to-integrate-redux.md)) (based on `master`) +- [feature/apollo](https://github.com/kriasoft/react-starter-kit/tree/feature/apollo) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1147)) + — isomorphic Apollo Client by [Pavel Lang](https://github.com/langpavel) + (see [Tracking PR #1147](https://github.com/kriasoft/react-starter-kit/pull/1147)) (based on `feature/redux`) +- [feature/react-intl](https://github.com/kriasoft/react-starter-kit/tree/feature/react-intl) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1135)) + — isomorphic Redux and React Intl by [Pavel Lang](https://github.com/langpavel) + (see [how to integrate React Intl](./docs/recipes/how-to-integrate-react-intl.md)) (based on `feature/apollo`) +- [feature/apollo-pure](https://github.com/kriasoft/react-starter-kit/tree/feature/apollo-pure) ([PR](https://github.com/kriasoft/react-starter-kit/pull/1664)) + — bare Apollo codebase by [piglovesyou](https://github.com/piglovesyou) (based on `master`) You can see status of most reasonable merge combination as [PRs labeled as `TRACKING`](https://github.com/kriasoft/react-starter-kit/labels/TRACKING) @@ -53,7 +51,6 @@ If you think that any of these features should be on `master`, or vice versa, so removed from the `master` branch, please [let us know](https://gitter.im/kriasoft/react-starter-kit). We love your feedback! - ### Comparison @@ -100,12 +97,10 @@ We love your feedback! @@ -151,7 +146,6 @@ We love your feedback!
React, History, - Redux React, History, - Redux
- ### Backers ♥ React Starter Kit? Help us keep it alive by donating funds to cover project @@ -180,45 +174,40 @@ expenses via [OpenCollective](https://opencollective.com/react-starter-kit) or - ### How to Contribute Anyone and everyone is welcome to [contribute](CONTRIBUTING.md) to this project. The best way to start is by checking our [open issues](https://github.com/kriasoft/react-starter-kit/issues), -[submit a new issues](https://github.com/kriasoft/react-starter-kit/issues/new?labels=bug) or +[submit a new issue](https://github.com/kriasoft/react-starter-kit/issues/new?labels=bug) or [feature request](https://github.com/kriasoft/react-starter-kit/issues/new?labels=enhancement), participate in discussions, upvote or downvote the issues you like or dislike, send [pull requests](CONTRIBUTING.md#pull-requests). - ### Learn More - * [Getting Started with React.js](http://facebook.github.io/react/) - * [Getting Started with GraphQL and Relay](https://quip.com/oLxzA1gTsJsE) - * [React.js Questions on StackOverflow](http://stackoverflow.com/questions/tagged/reactjs) - * [React.js Discussion Board](https://discuss.reactjs.org/) - * [Flux Architecture for Building User Interfaces](http://facebook.github.io/flux/) - * [Enzyme — JavaScript Testing utilities for React](http://airbnb.io/enzyme/) - * [Flow — A static type checker for JavaScript](http://flowtype.org/) - * [The Future of React](https://github.com/reactjs/react-future) - * [Learn ES6](https://babeljs.io/docs/learn-es6/), [ES6 Features](https://github.com/lukehoban/es6features#readme) - +- [Getting Started with React.js](http://facebook.github.io/react/) +- [Getting Started with GraphQL and Relay](https://quip.com/oLxzA1gTsJsE) +- [React.js Questions on StackOverflow](http://stackoverflow.com/questions/tagged/reactjs) +- [React.js Discussion Board](https://discuss.reactjs.org/) +- [Flux Architecture for Building User Interfaces](http://facebook.github.io/flux/) +- [Enzyme — JavaScript Testing utilities for React](http://airbnb.io/enzyme/) +- [Flow — A static type checker for JavaScript](http://flowtype.org/) +- [The Future of React](https://github.com/reactjs/react-future) +- [Learn ES6](https://babeljs.io/docs/learn-es6/), [ES6 Features](https://github.com/lukehoban/es6features#readme) ### Related Projects - * [GraphQL Starter Kit](https://github.com/kriasoft/graphql-starter-kit) — Boilerplate for building data APIs with Node.js, JavaScript (via Babel) and GraphQL - * [Membership Database](https://github.com/membership/membership.db) — SQL schema boilerplate for user accounts, profiles, roles, and auth claims - * [Babel Starter Kit](https://github.com/kriasoft/babel-starter-kit) — Boilerplate for authoring JavaScript/React.js libraries - +- [GraphQL Starter Kit](https://github.com/kriasoft/graphql-starter-kit) — Boilerplate for building data APIs with Node.js, JavaScript (via Babel) and GraphQL +- [Membership Database](https://github.com/membership/membership.db) — SQL schema boilerplate for user accounts, profiles, roles, and auth claims +- [Babel Starter Kit](https://github.com/kriasoft/babel-starter-kit) — Boilerplate for authoring JavaScript/React.js libraries ### Support - * [#react-starter-kit](http://stackoverflow.com/questions/tagged/react-starter-kit) on Stack Overflow — Questions and answers - * [#react-starter-kit](https://gitter.im/kriasoft/react-starter-kit) on Gitter — Watch announcements, share ideas and feedback - * [GitHub issues](https://github.com/kriasoft/react-starter-kit/issues), or [Scrum board](https://waffle.io/kriasoft/react-starter-kit) — File issues, send feature requests - * [appear.in/react](https://appear.in/react) — Open hours! Exchange ideas and experiences (React, GraphQL, startups and pet projects) - * [@koistya](https://twitter.com/koistya) on [Codementor](https://www.codementor.io/koistya), or [Skype](http://hatscripts.com/addskype?koistya) — Private consulting - +- [#react-starter-kit](http://stackoverflow.com/questions/tagged/react-starter-kit) on Stack Overflow — Questions and answers +- [#react-starter-kit](https://gitter.im/kriasoft/react-starter-kit) on Gitter — Watch announcements, share ideas and feedback +- [GitHub issues](https://github.com/kriasoft/react-starter-kit/issues), or [Scrum board](https://waffle.io/kriasoft/react-starter-kit) — File issues, send feature requests +- [appear.in/react](https://appear.in/react) — Open hours! Exchange ideas and experiences (React, GraphQL, startups and pet projects) +- [@koistya](https://twitter.com/koistya) on [Codementor](https://www.codementor.io/koistya), or [Skype](http://hatscripts.com/addskype?koistya) — Private consulting ### License @@ -228,6 +217,7 @@ file. The documentation to the project is licensed under the [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) license. --- + Made with ♥ by Konstantin Tarkus ([@koistya](https://twitter.com/koistya)) and [contributors](https://github.com/kriasoft/react-starter-kit/graphs/contributors) [rsk]: https://www.reactstarterkit.com diff --git a/babel.config.js b/babel.config.js index aceed26eb..cf6b9d5ad 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,14 +1,3 @@ -/** - * React Starter Kit (https://www.reactstarterkit.com/) - * - * Copyright © 2014-present Kriasoft, LLC. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE.txt file in the root directory of this source tree. - */ - -// Babel configuration -// https://babeljs.io/docs/usage/api/ module.exports = { presets: [ [ @@ -19,9 +8,12 @@ module.exports = { }, }, ], - ['@babel/preset-stage-2', { decoratorsLegacy: true }], - '@babel/preset-flow', '@babel/preset-react', + '@babel/preset-typescript', + ], + plugins: [ + '@babel/plugin-proposal-class-properties', + '@babel/plugin-syntax-dynamic-import', ], ignore: ['node_modules', 'build'], }; diff --git a/docs/README.md b/docs/README.md index 99f478a28..ec0f1fd79 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,7 +5,6 @@ * [Getting Started](./getting-started.md) * [React Style Guide](./react-style-guide.md) * [How to configure text editors and IDEs](./how-to-configure-text-editors.md) -* [Data fetching with WHATWG Fetch](./data-fetching.md) * [Testing your application](./testing-your-application.md) ### Questions @@ -16,7 +15,6 @@ ### Recipes * [How to Implement Routing and Navigation](./recipes/how-to-implement-routing.md) -* [How to Integrate Redux](./recipes/how-to-integrate-redux.md) * [How to Integrate React Intl](./recipes/how-to-integrate-react-intl.md) * [How to Integrate Disqus](./recipes/how-to-integrate-disqus.md) * [How to Use Sass/SCSS](./recipes/how-to-use-sass.md) diff --git a/docs/data-fetching.md b/docs/data-fetching.md deleted file mode 100644 index 1ce808b16..000000000 --- a/docs/data-fetching.md +++ /dev/null @@ -1,63 +0,0 @@ -## Data Fetching - -At a bare minimum you may want to use [HTML5 Fetch API][fetch] as an HTTP client -utility for making Ajax request to the [data API server][nodeapi]. This API is -supported natively in all the major browsers except for IE (note, that Edge -browser does support Fetch). - -**React Starter Kit** is pre-configured with [`whatwg-fetch`][wfetch] polyfill -for the browser environment and [`node-fetch`][nfetch] module for the -server-side environment (see [`src/createFetch.js`](../src/createFetch.js)), -allowing you to use the `fetch(url, options)` method universally in both the -client-side and server-side code bases. - -In order to avoid the amount of boilerplate code needed when using the raw -`fetch(..)` function, a simple wrapper was created that provides a base URL of -the data API server, credentials (cookies), CORS etc. For example, in a browser -environment the base URL of the data API server might be an empty string, so -when you make an Ajax request to the `/graphql` endpoint it's being sent to the -same origin, and when the same code is executed on the server, during -server-side rendering, it fetches data from the `http://api:8080/graphql` -endpoint (`node-fetch` doesn't support relative URLs for obvious reasons). - -Because of these subtle differences of how the `fetch` method works internally, -it makes total sense to pass it as a `context` variable to your React -application, so it can be used from either routing level or from inside your -React components as follows: - -#### Route Example - -```js -{ - path: '/posts/:id', - async action({ params, fetch }) { - const resp = await fetch(`/api/posts/${params.id}`, { method: 'GET' }); - const data = await resp.json(); - return { title: data.title, component: }; - } -} -``` - -#### React Component - -```js -class Post extends React.Component { - static contextTypes = { fetch: PropTypes.func.isRequired }; - handleDelete = (event) => { - event.preventDefault(); - const id = event.target.dataset['id']; - this.context.fetch(`/api/posts/${id}`, { method: 'DELETE' }).then(...); - }; - render() { ... } -} -``` - -#### Related articles - -* [That's so fetch!](https://jakearchibald.com/2015/thats-so-fetch/) by - [Jake Archibald](https://twitter.com/jaffathecake) - -[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch -[wfetch]: https://github.com/github/fetchno -[nfetch]: https://github.com/bitinn/node-fetch -[nodeapi]: https://github.com/kriasoft/nodejs-api-starter diff --git a/docs/getting-started.md b/docs/getting-started.md index b1a86d22c..e8f1530c5 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -44,11 +44,6 @@ Before you start, take a moment to see how the project structure looks like: └── yarn.lock # Fixed versions of all the dependencies ``` -**Note**: The current version of RSK does not contain a Flux implementation. It -can be easily integrated with any Flux library of your choice. The most commonly -used Flux libraries are [Flux](http://facebook.github.io/flux/), -[Redux](http://redux.js.org/) and [Relay](http://facebook.github.io/relay/). - ### Quick Start #### 1. Get the latest version diff --git a/docs/react-style-guide.md b/docs/react-style-guide.md index 280641a66..c71243986 100644 --- a/docs/react-style-guide.md +++ b/docs/react-style-guide.md @@ -6,21 +6,21 @@ ### Table of Contents -* [Separate folder per UI component](#separate-folder-per-ui-component) -* [Prefer using functional components](#prefer-using-functional-components) -* [Use CSS Modules](#use-css-modules) -* [Use higher-order components](#use-higher-order-components) +- [Separate folder per UI component](#separate-folder-per-ui-component) +- [Prefer using functional components](#prefer-using-functional-components) +- [Use CSS Modules](#use-css-modules) +- [Use higher-order components](#use-higher-order-components) ### Separate folder per UI component -* Place each major UI component along with its resources in a separate folder\ +- Place each major UI component along with its resources in a separate folder\ This will make it easier to find related resources for any particular UI element (CSS, images, unit tests, localization files etc.). Removing such components during refactorings should also be easy. -* Avoid having CSS, images and other resource files shared between multiple +- Avoid having CSS, images and other resource files shared between multiple components.\ This will make your code more maintainable, easy to refactor. -* Add `package.json` file into each component's folder.\ +- Add `package.json` file into each component's folder.\ This will allow to easily reference such components from other places in your code.\ Use `import Nav from '../Navigation'` instead of `import Nav from '../Navigation/Navigation.js'` @@ -46,7 +46,7 @@ For more information google for ### Prefer using functional components -* Prefer using stateless functional components whenever possible.\ +- Prefer using stateless functional components whenever possible.\ Components that don't use state are better to be written as simple pure functions. ```jsx @@ -69,16 +69,16 @@ Navigation.propTypes = { items: PropTypes.array.isRequired }; ### Use CSS Modules -* Use CSS Modules\ +- Use CSS Modules\ This will allow using short CSS class names and at the same time avoid conflicts. -* Keep CSS simple and declarative. Avoid loops, mixins etc. -* Feel free to use variables in CSS via +- Keep CSS simple and declarative. Avoid loops, mixins etc. +- Feel free to use variables in CSS via [precss](https://github.com/jonathantneal/precss) plugin for [PostCSS](https://github.com/postcss/postcss) -* Prefer CSS class selectors instead of element and `id` selectors (see +- Prefer CSS class selectors instead of element and `id` selectors (see [BEM](https://bem.info/)) -* Avoid nested CSS selectors (see [BEM](https://bem.info/)) -* When in doubt, use `.root { }` class name for the root elements of your +- Avoid nested CSS selectors (see [BEM](https://bem.info/)) +- When in doubt, use `.root { }` class name for the root elements of your components ```scss @@ -126,13 +126,16 @@ Navigation.propTypes = { items: PropTypes.array.isRequired }; ```jsx // Navigation.js import React from 'react'; -import PropTypes from 'prop-types'; import withStyles from 'isomorphic-style-loader/lib/withStyles'; import s from './Navigation.scss'; -function Navigation() { +type PropTypes = { + className: string, +}; + +function Navigation(props: PropTypes) { return ( -