├── postcss.config.js
├── .gitignore
├── src
├── config.js
├── components
│ ├── Profile
│ │ ├── index.js
│ │ ├── package.json
│ │ └── Profile.js
│ ├── App
│ │ ├── package.json
│ │ ├── AppActions.js
│ │ ├── index.js
│ │ ├── App.spec.js
│ │ ├── AppReducer.js
│ │ ├── AppContainer.js
│ │ ├── style.scss
│ │ └── App.js
│ └── NotFound
│ │ ├── package.json
│ │ ├── style.scss
│ │ └── NotFound.js
├── common.js
├── store.js
└── routes.js
├── index.ejs
├── .babelrc
├── index.js
├── .editorconfig
├── webpack.test.config.js
├── webpack.config.js
├── webpack.production.config.js
├── README.md
└── package.json
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | node_modules/
3 | coverage/
4 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | export const BASE_PATH = "/app";
2 |
--------------------------------------------------------------------------------
/src/components/Profile/index.js:
--------------------------------------------------------------------------------
1 | import Profile from "./Profile";
2 |
3 | export default Profile;
4 |
--------------------------------------------------------------------------------
/src/components/App/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "App",
3 | "version": "1.0.0",
4 | "private": true,
5 | "main": "./index.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Profile/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Profile",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "./index.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/NotFound/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "NotFound",
3 | "version": "1.0.0",
4 | "private": true,
5 | "main": "./NotFound.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/common.js:
--------------------------------------------------------------------------------
1 | import { BASE_PATH } from "./config";
2 |
3 | export const routeFor = (path) => {
4 | if (path === "/") return BASE_PATH;
5 | return `${BASE_PATH}/${path}`;
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/App/AppActions.js:
--------------------------------------------------------------------------------
1 | export const CHANGE_COLOR = "CHANGE_COLOR";
2 |
3 | export const changeColor = () => {
4 | return {
5 | type: CHANGE_COLOR
6 | }
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/components/NotFound/style.scss:
--------------------------------------------------------------------------------
1 | ._404 {
2 | text-align: center;
3 | font-size: 3em;
4 | span{ color: red }
5 | a {
6 | font-size: 20px;
7 | color: blue;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | <%= htmlWebpackPlugin.options.title %>
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/App/index.js:
--------------------------------------------------------------------------------
1 | import App from "./App";
2 | import AppActions from "./AppActions";
3 | import AppContainer from "./AppContainer";
4 | import AppReducer from "./AppReducer";
5 |
6 | export {
7 | App,
8 | AppActions,
9 | AppContainer,
10 | AppReducer
11 | }
12 | export default App;
13 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react", "latest", "stage-0"],
3 | "plugins": [ "transform-runtime" ],
4 | "env": {
5 | "test": {
6 | "plugins": [
7 | [
8 | "babel-plugin-webpack-loaders",
9 | {
10 | "config": "./webpack.test.config.js",
11 | "verbose": false,
12 | }
13 | ]
14 | ]
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/App/App.spec.js:
--------------------------------------------------------------------------------
1 | jest.unmock("./App.js");
2 | import React from "react";
3 | import App from "./App.js";
4 | import { shallow, mount } from "enzyme";
5 |
6 | describe("App", function(){
7 | test("renders the App component", function() {
8 | const component = mount();
9 | expect(component.find('p').text()).toEqual("Awesome React!");
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/src/components/App/AppReducer.js:
--------------------------------------------------------------------------------
1 | import { CHANGE_COLOR } from "./AppActions.js";
2 | import randomColor from "randomcolor";
3 |
4 | let DEFAULT_STATE = {
5 | color: randomColor()
6 | };
7 |
8 | export default (state = DEFAULT_STATE, action) => {
9 | switch ( action.type ) {
10 | case CHANGE_COLOR:
11 | return { ...state, color: randomColor()};
12 | default:
13 | return state;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { render } from "react-dom";
3 | import Router from "./src/routes";
4 | import store from "./src/store";
5 |
6 | const run = () => {
7 | render(Router(store), document.getElementById("App"));
8 | }
9 |
10 | if (["complete", "loaded", "interactive"].includes(document.readyState) && document.body) {
11 | run();
12 | } else {
13 | document.addEventListener("DOMContentLoaded", run, false);
14 | }
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/src/components/App/AppContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from "react-redux";
2 | import App from "./App";
3 | import { changeColor } from "./AppActions";
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | color: state.AppReducer.color
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onChangeColor: () => dispatch(changeColor()),
14 | }
15 | }
16 |
17 | const AppContainer = connect(
18 | mapStateToProps,
19 | mapDispatchToProps
20 | )(App);
21 |
22 | export default AppContainer;
23 |
--------------------------------------------------------------------------------
/src/components/App/style.scss:
--------------------------------------------------------------------------------
1 | .react-logo {
2 | display: block;
3 | width: 400px;
4 | height: 400px;
5 | margin: 0 auto;
6 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
7 | span {
8 | width: 200px;
9 | display: block;
10 | cursor: pointer;
11 | margin: 0 auto;
12 | font-size: 22em;
13 | &:before {
14 | content: '⚛';
15 | font-weight: bold;
16 | }
17 | }
18 | }
19 |
20 | p, a{
21 | width: 400px;
22 | height: 20px;
23 | display: block;
24 | margin: 0 auto;
25 | text-align: center;
26 | text-decoration: none;
27 | cursor: pointer;
28 | &:hover {
29 | font-weight: bold;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/components/Profile/Profile.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 |
3 | class Profile extends Component {
4 |
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | name: "Alejandro Espinoza",
9 | email: "alexesba@gmail.com",
10 | avatar: "https://avatars2.githubusercontent.com/u/579793?v=4&s=460"
11 | }
12 | }
13 |
14 | render() {
15 | return (
16 |
17 |

18 |
19 |
{ this.state.name }
20 |
{ this.state.email }
21 |
22 |
23 | );
24 | }
25 | }
26 |
27 | export default Profile;
28 |
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, combineReducers } from 'redux'
2 | import thunk from "redux-thunk";
3 | import { browserHistory } from 'react-router'
4 | import { routerMiddleware } from "react-router-redux";
5 |
6 | // Import reducers
7 | import { AppReducer } from "./components/App";
8 |
9 | const reactRouterReduxMiddleware = routerMiddleware(browserHistory);
10 |
11 | let createStoreWithMiddleware = applyMiddleware(
12 | thunk, reactRouterReduxMiddleware
13 | )(createStore);
14 |
15 | let reducers = combineReducers({
16 | AppReducer
17 | });
18 |
19 | export default createStoreWithMiddleware(reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
20 |
21 |
--------------------------------------------------------------------------------
/src/routes.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Router, Route, browserHistory } from "react-router";
3 | import { AppContainer } from "./components/App";
4 | import NotFound from "./components/NotFound";
5 | import Profile from "./components/Profile";
6 | import { routeFor } from "./common";
7 | import { Provider } from "react-redux";
8 |
9 | export default (store) => {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/App/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import CSSModules from "react-css-modules";
3 | import { Link } from "react-router";
4 | import style from "./style.scss";
5 | import { routeFor } from "../../common";
6 |
7 | class App extends Component {
8 |
9 | render() {
10 | const { onChangeColor, color } = this.props;
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 | Awesome React!
19 |
20 |
21 |
22 | );
23 | }
24 |
25 | };
26 |
27 | export default CSSModules(App, style);
28 |
--------------------------------------------------------------------------------
/src/components/NotFound/NotFound.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import CSSModules from "react-css-modules";
3 | import { Link } from "react-router";
4 | import style from "./style.scss";
5 | import { routeFor } from "../../common";
6 |
7 | class NotFound extends Component {
8 |
9 | constructor(props) {
10 | super(props);
11 | }
12 |
13 | static defaultProps = {
14 | message: "not found"
15 | }
16 | render() {
17 | const { location: { pathname } } = this.props;
18 | return(
19 |
20 | Page: { pathname } {this.props.message }
21 | Home
22 |
23 | );
24 | }
25 | }
26 |
27 | export default CSSModules(NotFound, style);
28 |
--------------------------------------------------------------------------------
/webpack.test.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path'); // eslint-disable-line no-var
2 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); // eslint-disable-line no-var
3 |
4 | const loaderString = [
5 | 'css?minimize&modules&localIdentName=[hash:base64:4]',
6 | 'postcss-loader?parser=postcss-scss',
7 | "sass-loader"
8 | ].join('!')
9 | module.exports = {
10 | output: {
11 | // for babel plugin
12 | libraryTarget: 'commonjs2',
13 | // where to place webpack files
14 | path: path.join(__dirname, './build/'),
15 | // for url-loader if limit exceeded to set publicPath
16 | publicPath: '',
17 | },
18 | module: {
19 | loaders: [
20 | {
21 | test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|eot|ttf)$/,
22 | loader: 'url-loader?limit=1000',
23 | },
24 | {
25 | test: /.json$/,
26 | loader: "json-loader"
27 | },
28 | {
29 | test: /\.scss?$/,
30 | exclude: /node_modules/,
31 | loader: ExtractTextPlugin.extract(loaderString)
32 | }
33 | ]
34 | },
35 | "plugins": [
36 | new ExtractTextPlugin('style.css')
37 | ]
38 | };
39 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require("path");
2 | var lodash = require("lodash");
3 | var ExtractTextPlugin = require("extract-text-webpack-plugin");
4 | var HtmlWebpackPlugin = require("html-webpack-plugin");
5 |
6 |
7 | module.exports = {
8 | entry: path.join(__dirname, "index.js"),
9 | output: {
10 | publicPath: '/'
11 | },
12 | devServer: {
13 | historyApiFallback: true,
14 | hot: true,
15 | inline: true,
16 | open: true,
17 | progress: true
18 | },
19 | module: {
20 | loaders: [
21 | { test: /\.jsx?$/,
22 | loader: "babel",
23 | exclude: /node_modules/,
24 | include: __dirname,
25 | query: {
26 | presets: ['react-hmre', 'react', 'latest', "stage-0"]
27 | }
28 | },
29 | {
30 | test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|eot|ttf)$/,
31 | loader: 'url-loader?limit=9999999',
32 | },
33 |
34 | { test: /\.scss?$/, loaders: [
35 | "style?sourceMap",
36 | "css-loader?sourceMap&modules&localIdentName=[path]__[name]__[local]__[hash:base64:5]",
37 | "postcss-loader?parser=postcss-scss",
38 | "sass-loader?sourceMap"
39 | ]
40 | },
41 | ]
42 | },
43 | "plugins": [
44 | new HtmlWebpackPlugin({
45 | title: "Awesome React!!",
46 | template: "index.ejs",
47 | })
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/webpack.production.config.js:
--------------------------------------------------------------------------------
1 | var path = require("path");
2 | var lodash = require("lodash");
3 | var ExtractTextPlugin = require("extract-text-webpack-plugin");
4 | var HtmlWebpackPlugin = require("html-webpack-plugin");
5 | var HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
6 |
7 |
8 | const loaderString = [
9 | 'css?minimize&modules&localIdentName=[hash:base64:4]',
10 | 'postcss-loader?parser=postcss-scss',
11 | "sass-loader"
12 | ].join('!')
13 | module.exports = {
14 | node: {
15 | fs: "empty"
16 | },
17 | entry: {
18 | app: [ path.join(__dirname, "/index.js") ]
19 | },
20 | output: {
21 | path: path.resolve(__dirname + "/build"),
22 | filename: "app.js"
23 | },
24 | resolve: {
25 | extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx', '.json'],
26 | modulesDirectories: ['src', 'node_modules'],
27 | root: [path.join(__dirname, "src")]
28 | },
29 | module: {
30 | loaders: [
31 | { test: /\.jsx?$/, loader: "babel-loader", exclude: /node_modules/ },
32 | {
33 | test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|eot|ttf)$/,
34 | loader: 'url-loader?limit=1000',
35 | },
36 | {
37 | test: /.json$/,
38 | loader: "json-loader"
39 | },
40 | {
41 | test: /\.scss?$/,
42 | exclude: /node_modules/,
43 | loader: ExtractTextPlugin.extract(loaderString)
44 | },
45 | ]
46 | },
47 | "externals": {
48 | "react": "React",
49 | "react-dom": "ReactDOM"
50 | },
51 | "plugins": [
52 | new ExtractTextPlugin('style.css'),
53 | new HtmlWebpackPlugin({
54 | title: "Awesome React!!",
55 | template: "index.ejs"
56 | }),
57 | new HtmlWebpackExternalsPlugin([
58 | { name: "react", var: "React", url: "https://unpkg.com/react@15.4.1/dist/react.js" },
59 | { name: "react-dom", var: "ReactDOM", url: "https://unpkg.com/react-dom@15.4.1/dist/react-dom.js" }
60 | ])
61 | ]
62 | }
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simple Rebo
2 |
3 | ## Simple [**React**](https://facebook.github.io/react/) boilerplate
4 |
5 | > Create [**React**](https://facebook.github.io/react/) applications and avoid spent time configuring tasks for transpiling scss and javascripts
6 | This project has born with the main idea to have something up and running in a couple of minutes. It also provides you
7 | a structure of files to keep your code organized in packages called **Components** this boilerplate integrates [**Redux**](https://github.com/reactjs/redux)
8 |
9 | ## Technologies implemented:
10 | - *babel*
11 | - *es6*
12 | - *jsx*
13 | - *react*
14 | - *redux*
15 | - *scss*
16 |
17 |
18 | ## Available tasks/commands:
19 | * `npm start:` runs the application in development mode it will open your browser in a tab and display a small demo
20 | * `npm run build`: compiles the whole src directory whithin the `build` directory
21 | * `npm run test`: runs the test suite.
22 | * `npm coverage`: opens the coverage results in the browser
23 |
24 |
25 | ## File Structure:
26 | ```sh
27 | .
28 | ├── README.md
29 | ├── build
30 | │ ├── 966a74a61246a4060d377bbc8321529e.svg
31 | │ ├── app.js
32 | │ ├── index.html
33 | │ └── style.css
34 | ├── coverage
35 | ├── index.ejs #ejs template which is used on production and development env.
36 | ├── index.js #entry file for webpack compilations in other word our main file
37 | ├── package.json #package dependencies and dev-dependcies.
38 | ├── src
39 | │ ├── components
40 | │ │ ├── App
41 | │ │ │ ├── App.js
42 | │ │ │ ├── App.spec.js
43 | │ │ │ ├── AppActions.js
44 | │ │ │ ├── AppContainer.js
45 | │ │ │ ├── AppReducer.js
46 | │ │ │ ├── index.js
47 | │ │ │ ├── package.json
48 | │ │ │ ├── react.svg
49 | │ │ │ └── style.scss
50 | │ │ └── NotFound
51 | │ │ ├── NotFound.js
52 | │ │ └── package.json
53 | │ ├── routes.js
54 | │ └── store.js
55 | ├── webpack.config.js #config file used for development
56 | ├── webpack.production.config.js #config file used for production
57 | ├── webpack.test.config.js #used to compile and run the suite test
58 | └── yarn.lock #used to install all dependencies if you are using yarn
59 | ```
60 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo-react",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "author": "alexesba ",
6 | "license": "MIT",
7 | "dependencies": {
8 | "lodash": "^4.17.4",
9 | "prop-types": "^15.5.8",
10 | "randomcolor": "^0.4.4",
11 | "react": "^15.5.4",
12 | "react-css-modules": "^4.0.5",
13 | "react-dom": "^15.5.4",
14 | "react-redux": "^4.4.6",
15 | "react-router": "^3.0.0",
16 | "react-router-redux": "^4.0.7",
17 | "redux": "^3.6.0",
18 | "redux-thunk": "^2.1.0"
19 | },
20 | "scripts": {
21 | "start": "webpack-dev-server --hot",
22 | "clean": "rm -rf build",
23 | "compile": "webpack --config webpack.production.config.js",
24 | "build": "npm run clean && npm run compile",
25 | "test": "BABEL_DISABLE_CACHE=1 NODE_ENV=test jest",
26 | "coverage": "opener coverage/lcov-report/index.html"
27 | },
28 | "jest": {
29 | "rootDir": ".",
30 | "collectCoverage": true,
31 | "transform": {
32 | ".js": "/node_modules/babel-jest"
33 | },
34 | "moduleFileExtensions": [
35 | "js",
36 | "jsx",
37 | "json"
38 | ],
39 | "moduleDirectories": [
40 | "node_modules"
41 | ]
42 | },
43 | "devDependencies": {
44 | "autoprefixer-core": "^6.0.1",
45 | "babel-cli": "^6.18.0",
46 | "babel-core": "^6.18.2",
47 | "babel-eslint": "^7.1.1",
48 | "babel-jest": "^17.0.2",
49 | "babel-loader": "^6.2.8",
50 | "babel-plugin-css-modules-transform": "^1.1.0",
51 | "babel-plugin-react-transform": "^2.0.2",
52 | "babel-plugin-transform-runtime": "^6.15.0",
53 | "babel-plugin-webpack-loaders": "^0.8.0",
54 | "babel-preset-latest": "^6.16.0",
55 | "babel-preset-react": "^6.16.0",
56 | "babel-preset-react-hmre": "^1.1.1",
57 | "babel-preset-stage-0": "^6.16.0",
58 | "babel-runtime": "^6.18.0",
59 | "css-loader": "^0.26.0",
60 | "enzyme": "^2.6.0",
61 | "extract-text-webpack-plugin": "^1.0.1",
62 | "file-loader": "^0.9.0",
63 | "html-webpack-externals-plugin": "^2.1.2",
64 | "html-webpack-plugin": "^2.24.1",
65 | "identity-obj-proxy": "^3.0.0",
66 | "isomorphic-style-loader": "^1.1.0",
67 | "jest": "^17.0.3",
68 | "jest-cli": "^17.0.3",
69 | "jest-css-modules": "^1.1.0",
70 | "json-loader": "^0.5.4",
71 | "mocha": "^3.2.0",
72 | "node-sass": "^3.13.0",
73 | "opener": "^1.4.2",
74 | "postcss-color-rebeccapurple": "^2.0.1",
75 | "postcss-loader": "^1.1.1",
76 | "postcss-scss": "^0.4.0",
77 | "raw-loader": "^0.5.1",
78 | "react-addons-test-utils": "^15.4.1",
79 | "react-hot-loader": "^1.3.1",
80 | "react-test-renderer": "^15.4.1",
81 | "resolve-url": "^0.2.1",
82 | "resolve-url-loader": "^1.6.0",
83 | "sass-loader": "^4.0.2",
84 | "style-loader": "^0.13.1",
85 | "url-loader": "^0.5.7",
86 | "webpack": "^1.13.3",
87 | "webpack-dev-middleware": "^1.8.4",
88 | "webpack-dev-server": "^1.16.2",
89 | "webpack-hot-middleware": "^2.13.2"
90 | }
91 | }
92 |
--------------------------------------------------------------------------------