├── .babelrc ├── README.md ├── .travis.yml ├── src ├── css │ ├── BlockExample.css │ └── TextBlockExample.css ├── containers │ ├── App.js │ ├── Test.js │ └── Root.js ├── components │ ├── BlockExample.js │ └── TextBlockExample.js └── index.js ├── webpack.config.prod.js ├── index.html ├── .editorconfig ├── .gitignore ├── server.js ├── .eslintrc ├── webpack.config.js ├── package.json └── .stylelintrc /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["react-hot-loader/babel", "transform-decorators-legacy", "transform-runtime"], 3 | "presets": ["es2015", "react", "stage-0"] 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-starter 2 | 3 | 4 | For information about this starter application, see https://medium.com/@olegafx/frontend-welcome-to-the-future-91ff064884b6 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | cache: 4 | directories: 5 | - ~/.npm 6 | - ~/.cache 7 | notifications: 8 | email: false 9 | node_js: '8' 10 | -------------------------------------------------------------------------------- /src/css/BlockExample.css: -------------------------------------------------------------------------------- 1 | .blockFlex { 2 | display: flex; 3 | background-color: #444; 4 | margin-left: 45px; 5 | } 6 | 7 | .text { 8 | color: white; 9 | font-size: 3rem; 10 | } 11 | -------------------------------------------------------------------------------- /src/css/TextBlockExample.css: -------------------------------------------------------------------------------- 1 | .blockFlex { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | 7 | .text { 8 | font-size: 2rem; 9 | line-height: 1.5; 10 | color: #000000cc; 11 | } -------------------------------------------------------------------------------- /src/containers/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import Test from './Test'; 4 | 5 | export default class Root extends Component { 6 | constructor (props) { 7 | super(props); 8 | } 9 | 10 | render () { 11 | return ( 12 | 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var config = require('./webpack.config'); 3 | 4 | config.plugins.push( 5 | new webpack.DefinePlugin({ 6 | 'process.env': { 7 | 'NODE_ENV': JSON.stringify('production') 8 | } 9 | }) 10 | ); 11 | 12 | module.exports = config; 13 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React starter project 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | [COMMIT_EDITMSG] 18 | max_line_length = 0 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ########## App ########## 2 | /dist/ 3 | /log/ 4 | 5 | ########## Jetbrains ########## 6 | .idea 7 | 8 | ########## Node ########## 9 | node_modules 10 | npm-debug.log 11 | 12 | ########## Temp files ########## 13 | # Windows 14 | Thumbs.db 15 | ehthumbs.db 16 | Desktop.ini 17 | 18 | # OSX 19 | .DS_Store 20 | .AppleDouble 21 | .LSOverride 22 | .Spotlight-V100 23 | .Trashes 24 | -------------------------------------------------------------------------------- /src/components/BlockExample.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import styles from '../css/BlockExample.css'; 4 | 5 | export default class TextBlockExample extends Component { 6 | constructor (props) { 7 | super(props); 8 | } 9 | 10 | render () { 11 | return ( 12 |
13 | It works! 14 |
15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/containers/Test.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import BlockExample from '../components/BlockExample'; 4 | import TextBlockExample from '../components/TextBlockExample'; 5 | 6 | export default class TestPage extends Component { 7 | constructor (props) { 8 | super(props); 9 | } 10 | 11 | render () { 12 | return ( 13 |
14 | 15 | 16 |
17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var WebpackDevServer = require('webpack-dev-server'); 3 | var config = require('./webpack.config'); 4 | 5 | new WebpackDevServer(webpack(config), { 6 | publicPath: config.output.publicPath, 7 | hot: true, 8 | historyApiFallback: true, 9 | stats: { 10 | assets: false, 11 | children: false, 12 | colors: true, 13 | version: false, 14 | hash: false, 15 | timings: false, 16 | chunks: false, 17 | chunkModules: false 18 | } 19 | }) 20 | .listen(3000, 'localhost', function (err) { 21 | if (err) { 22 | console.log(err); 23 | } 24 | 25 | console.log('Listening at localhost:3000'); 26 | }); 27 | -------------------------------------------------------------------------------- /src/components/TextBlockExample.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import styles from '../css/TextBlockExample.css'; 4 | 5 | export default class TextBlockExample extends Component { 6 | constructor (props) { 7 | super(props); 8 | } 9 | 10 | componentDidMount () { 11 | this.getData(); 12 | } 13 | 14 | async getData () { 15 | const rawData = await fetch('http://headers.jsontest.com/'); 16 | const data = await rawData.json(); 17 | 18 | console.log('data', data); 19 | } 20 | 21 | render () { 22 | return ( 23 |
24 | text block example 25 |
26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { AppContainer } from 'react-hot-loader'; 4 | 5 | import 'babel-polyfill'; 6 | import 'whatwg-fetch'; 7 | 8 | import Root from './containers/Root'; 9 | 10 | const renderApp = () => { 11 | render( 12 | 13 | 14 | , 15 | document.getElementById('root') 16 | ); 17 | }; 18 | 19 | renderApp(); 20 | 21 | if (module.hot) { 22 | module.hot.accept('./containers/Root', () => { 23 | const NextApp = require('./containers/Root').default; 24 | 25 | render( 26 | 27 | 28 | , 29 | document.getElementById('root') 30 | ); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /src/containers/Root.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import Match from 'react-router/Match'; 4 | import Miss from 'react-router/Miss'; 5 | import Link from 'react-router/Link'; 6 | import Router from 'react-router/BrowserRouter'; 7 | 8 | import App from './App'; 9 | 10 | import BlockExample from '../components/BlockExample'; 11 | import TextExample from '../components/TextBlockExample'; 12 | 13 | const NoMatch = ({ location }) => ( 14 |
15 |

Whoops

16 |

Sorry but {location.pathname} didn’t match any pages

17 |
18 | ); 19 | 20 | const Root = () => ( 21 | 22 |
23 |
    24 |
  • Home
  • 25 |
  • Block
  • 26 |
  • Text
  • 27 |
28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 | ); 39 | 40 | export default Root; 41 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jquery": true, 6 | "node": true 7 | }, 8 | 9 | "plugins": [ 10 | "react" 11 | ], 12 | 13 | "ecmaFeatures": { 14 | "modules": true, 15 | "jsx": true 16 | }, 17 | 18 | "parser": "babel-eslint", 19 | 20 | "rules": { 21 | "camelcase": [2, {"properties": "never"}], 22 | "eqeqeq": 2, 23 | "global-strict": 0, 24 | "indent": [2, 2], 25 | "jsx-quotes": [2, "prefer-double"], 26 | "max-params": [2, 3], 27 | "no-console": 0, 28 | "no-shadow": 1, 29 | "no-undef": 1, 30 | "no-underscore-dangle": 0, 31 | "no-use-before-define": 1, 32 | "no-var": 2, 33 | "quotes": [2, "single", "avoid-escape"], 34 | "object-shorthand": [2, "always"], 35 | "semi": 1, 36 | "strict": [1, "function"], 37 | "react/display-name": 0, 38 | "react/jsx-no-undef": 1, 39 | "react/jsx-uses-react": 1, 40 | "react/jsx-uses-vars": 1, 41 | "react/no-did-mount-set-state": 1, 42 | "react/no-did-update-set-state": 1, 43 | "react/no-multi-comp": 1, 44 | "react/no-unknown-property": 1, 45 | "react/prop-types": 1, 46 | "react/react-in-jsx-scope": 1, 47 | "react/self-closing-comp": 1, 48 | "react/wrap-multilines": 1 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var autoprefixer = require('autoprefixer'); 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | 5 | var path = require('path'); 6 | 7 | module.exports = { 8 | entry: { 9 | 'index': [ 10 | 'webpack-dev-server/client?http://0.0.0.0:3000', 11 | 'webpack/hot/only-dev-server', 12 | 'react-hot-loader/patch', 13 | './src/index' 14 | ] 15 | }, 16 | 17 | output: { 18 | filename: '[name].js', 19 | path: path.join(__dirname, '/dist/'), 20 | publicPath: '/dist/' 21 | }, 22 | 23 | module: { 24 | loaders: [ 25 | { 26 | test: /\.css$/, 27 | loader: ExtractTextPlugin.extract('css-loader?modules&localIdentName=' + (process.env.NODE_ENV === 'production' ? '[hash:base64]' : '[name]__[local]___[hash:base64:5]') + '&importLoaders=1!postcss-loader') }, 28 | { 29 | test: /\.js$/, 30 | loaders: ['babel-loader'], 31 | exclude: /node_modules/ 32 | } 33 | ] 34 | }, 35 | 36 | postcss: function () { 37 | return [autoprefixer]; 38 | }, 39 | 40 | resolve: { 41 | extensions: ['', '.jsx', '.js', '.json'], 42 | modulesDirectories: ['node_modules'] 43 | }, 44 | 45 | plugins: [ 46 | new ExtractTextPlugin('index.css'), 47 | new webpack.optimize.OccurenceOrderPlugin(), 48 | new webpack.HotModuleReplacementPlugin(), 49 | new webpack.NoErrorsPlugin() 50 | ] 51 | }; 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-starter", 3 | "version": "2.0.0", 4 | "description": "React starter project", 5 | "keywords": [ 6 | "react", 7 | "bootstrap", 8 | "babel", 9 | "cssnext", 10 | "postcss" 11 | ], 12 | "author": "Oleg Kislitsyn", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "git@git-ok:olegafx/dev.sm-tr.com.git" 17 | }, 18 | "main": "src/index.js", 19 | "scripts": { 20 | "build": "./node_modules/.bin/webpack -p --bail --config ./webpack.config.prod.js", 21 | "start": "node server.js" 22 | }, 23 | "pre-commit": [ 24 | "lint-staged" 25 | ], 26 | "lint-staged": { 27 | "eslint": "*.js", 28 | "stylelint": "*.css" 29 | }, 30 | "devDependencies": { 31 | "babel-eslint": "6.1.0", 32 | "eslint": "3.0.1", 33 | "eslint-plugin-react": "5.2.2", 34 | "stylelint": "6.8.0", 35 | "webpack-dev-server": "1.14.1", 36 | "why-did-you-update": "0.0.8" 37 | }, 38 | "dependencies": { 39 | "autoprefixer": "6.4.1", 40 | "babel-core": "6.14.0", 41 | "babel-loader": "6.2.5", 42 | "babel-plugin-transform-decorators-legacy": "1.3.4", 43 | "babel-plugin-transform-runtime": "6.12.0", 44 | "babel-polyfill": "6.13.0", 45 | "babel-preset-es2015": "6.14.0", 46 | "babel-preset-react": "6.11.1", 47 | "babel-preset-stage-0": "6.5.0", 48 | "babel-runtime": "6.9.2", 49 | "css-loader": "0.25.0", 50 | "extract-text-webpack-plugin": "1.0.1", 51 | "lint-staged": "3.0.1", 52 | "lodash": "4.13.1", 53 | "postcss-loader": "0.13.0", 54 | "pre-commit": "1.1.3", 55 | "react": "15.3.1", 56 | "react-dom": "15.3.1", 57 | "react-hot-loader": "3.0.0-beta.3", 58 | "react-router": "4.0.0-2", 59 | "webpack": "1.13.2", 60 | "whatwg-fetch": "1.0.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "color-named": "never", 4 | "color-no-hex": true, 5 | 6 | "font-family-name-quotes": "always-where-recommended", 7 | "font-weight-notation": "numeric", 8 | 9 | "function-comma-newline-after": "never-multi-line", 10 | "function-comma-newline-before": "never-multi-line", 11 | "function-comma-space-after": "always", 12 | "function-comma-space-before": "never", 13 | "function-linear-gradient-no-nonstandard-direction": true, 14 | "function-name-case": "lower", 15 | "function-url-data-uris": "never", 16 | "function-url-quotes": "always", 17 | "function-whitespace-after": "always", 18 | 19 | "number-leading-zero": "always", 20 | "number-max-precision": 4, 21 | "number-no-trailing-zeros": true, 22 | "number-zero-length-no-unit": true, 23 | 24 | "string-no-newline": true, 25 | "string-quotes": "single", 26 | 27 | "time-no-imperceptible": true, 28 | 29 | "unit-blacklist": ["px", "em", "deg"], 30 | "unit-case": "lower", 31 | "unit-no-unknown": true, 32 | 33 | "value-no-vendor-prefix": true, 34 | 35 | "value-list-comma-newline-after": "never-multi-line", 36 | "value-list-comma-newline-before": "never-multi-line", 37 | "value-list-comma-space-after": "always", 38 | "value-list-comma-space-before": "never", 39 | 40 | "custom-property-no-outside-root": true, 41 | 42 | "property-case": "lower", 43 | "property-no-vendor-prefix": true, 44 | 45 | "keyframe-declaration-no-important": true, 46 | 47 | "declaration-block-no-duplicate-properties": [true, { 48 | ignore: ["consecutive-duplicates"] 49 | }], 50 | 51 | "indentation": 2, 52 | "max-empty-lines": 1, 53 | "max-line-length": 120, 54 | "max-nesting-depth": 1, 55 | "no-duplicate-selectors": true, 56 | "no-eol-whitespace": true, 57 | "no-extra-semicolons": true, 58 | "no-invalid-double-slash-comments": true, 59 | "no-missing-eof-newline": true, 60 | "no-unknown-animations": true, 61 | "selector-no-id": true 62 | } 63 | } 64 | --------------------------------------------------------------------------------