Skip to content

Commit

Permalink
Clean up, restructure folders, switch to css modulues and add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy Yu committed Dec 4, 2018
1 parent dc416ce commit 68b6281
Show file tree
Hide file tree
Showing 19 changed files with 107 additions and 130 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ __Note:__ This boilerplate is not to show case how to code in React / Redux, it

Features

* React 16
* React 16.6
* Redux
* Saga
* ES6 / ES7
* ImmutableJS
* PreCSS ( supports SASS-like markup in your CSS )
* PostCSS ( it support CSS modules, and we recommended B.E.M style )
* Webpack 3
* PostCSS ( with CSS modules activated by default )
* Webpack 4
* Reselect
* Lazy Loading component supports
* Type Checking with Babel Type Check ( Flow syntax )
Expand Down Expand Up @@ -198,8 +198,9 @@ All your javascript code lives in folder `src/js`
-- src/
-- js/
-- common/
-- components/ --> all share components here
-- types/ --> all flow types are here
-- api/ --> all api requests
-- components/ --> all share components
-- types/ --> all flow types
-- redux/
-- modules/ --> all redux code
-- saga/ --> all redux-saga code
Expand Down
13 changes: 9 additions & 4 deletions bin/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ const shell = require('shelljs');
const config = require('config');
const colors = require('colors');

const host = config.get('host') || 'localhost';
const port = config.get('port') || '8080';

const option = process.argv[2];

// The following will allow you to add your own
// - pre process
// - post process
// - parallel process
// - logging
//
// You can add your process here and have package.json to proxy your command
// Please look at package.json -> "scripts" section
switch (option) {
case 'lint':
shell.exec('cross-env eslint --fix src/js/** --format node_modules/eslint-friendly-formatter . --ext .js --ext .jsx --cache; exit 0');
break;
case 'dev':
shell.exec(`cross-env HOST=${host} PORT=${port} webpack-dev-server --config webpack.config.dev-server.babel.js --hot --progress --no-info --inline --colors --content-base ./docroot`);
shell.exec(`cross-env webpack-dev-server --config webpack.config.dev-server.babel.js --hot --progress --no-info --inline --colors`);
break;
case 'build':
shell.exec(`cross-env rimraf docroot && webpack --config webpack.config.build.babel.js --progress --display-error-details`);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-redux-boilerplate",
"version": "1.2.1",
"version": "1.2.2",
"description": "React Redux Boilerplate is a workflow boilerplate that make life easier for developers by providing a virtual development environment and production ready build process framework out of the box.",
"scripts": {
"dev": "cross-env NODE_ENV=development DASHBOARD_PORT=9901 webpack-dashboard -p 9901 -c red -t dashboard -- node bin/commands.js dev",
Expand Down
15 changes: 15 additions & 0 deletions src/js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Before Your Start Coding

This Boilerplate is providing a infrastructure to start your project as quickly as you can.

__BUT__ before you start developing a real large scale project, please do ask yourself or your team a few questions :-

* What is your domain layer looks like ? You can pretend redux as a data repository of everything, but it will provide no actual meaning for your application besides a data bag. For example, am I able to describe what a `User` is in the application. Having a domain layer will help yourself from having heart attack of arbitrary data structure that describe the same thing in different places.
* I know you are a smart engineer, but please remember it is better to write code everyone can understand.
* You only need to solve a problem when you have a real problem, don't prematurely making a decision based on preference.
* Strong convention is better for everyone, if you don't have convention today, you will have N+1 conventions the next month.

If you read to this point, I assumed you are a very serious developer, please help me to read the following links if you haven't!

[SOLID JavaScript](http://aspiringcraftsman.com/2011/12/08/solid-javascript-single-responsibility-principle/)
[Twelve Factor App](https://12factor.net/)
10 changes: 10 additions & 0 deletions src/js/common/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Convention

The following will be convention for this api/

* You can only put your api request here, no business logic.
* You should separate your api files by "requested resources"
* Your api should return a "Promise" interface for consistency
* And you use `index.js` to expose your api

This folder will contain an example using axios, it is not a working api, but show case how you should structure your apis.
7 changes: 7 additions & 0 deletions src/js/common/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
// This is an example will not work
// This is just showing case how I would orangize
export {
getTopTenAvengers,
} from './module/example'
*/
9 changes: 9 additions & 0 deletions src/js/common/api/module/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
// This is an example will not work
// Just only show case how I would orangize
const API_ENDPOINT = __CONFIG__.apiUrl.avengers
export const getTopTenAvengers = (query = {}) => {
return axios.get(`${API_ENDPOINT}?count=10`)
}
*/
4 changes: 2 additions & 2 deletions src/js/common/components/Example/Example.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react';

import './Example.css';
import styles from './Example.css';

/**
* Example
Expand Down Expand Up @@ -45,7 +45,7 @@ class Example extends PureComponent {

if (result && result.size && result.size > 0) {
return (
<div className="exampleOutput">
<div className={styles.exampleOutput}>
<h1>
Let&apos;s Get
<span className="emphasize">Started</span>
Expand Down
4 changes: 2 additions & 2 deletions src/js/common/components/Example/ExampleWithError.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react';

import './Example.css';
import styles from './Example.css';

class ExampleWithError extends PureComponent {
render() {
Expand All @@ -9,7 +9,7 @@ class ExampleWithError extends PureComponent {

if (result && result.size && result.size > 0) {
return (
<div className="exampleOutput">
<div className={styles.exampleOutput}>
<h1>This should catch by ErrorBoundary</h1>
{result.something_not_existed.get('something_not_existed')}
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/js/common/components/Header/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PureComponent } from 'react';
import { Link } from 'react-router-dom';

import './Header.css';
import styles from './Header.css';

class Header extends PureComponent {
render() {
Expand All @@ -12,16 +12,16 @@ class Header extends PureComponent {
const isJustAnotherPage = pathname === '/page';

return (
<header className="globalHeader">
<header className={styles.globalHeader}>
<ul>
<li className={!isHome ? 'active' : ''}>
<li className={!isHome ? styles.active : ''}>
{
isHome
? 'Home' : <Link to="/">Home</Link>

}
</li>
<li className={!isJustAnotherPage ? 'active' : ''}>
<li className={!isJustAnotherPage ? styles.active : ''}>
{
isJustAnotherPage
? 'Just Another Page' : <Link to="/page">Just Another Page</Link>
Expand Down
4 changes: 2 additions & 2 deletions src/js/common/components/LazyLoading/Loading.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react';

import './Loading.css'
import styles from './Loading.css'

class Loading extends PureComponent {
getMessage() {
Expand All @@ -17,7 +17,7 @@ class Loading extends PureComponent {
if (timedOut) {
return <div>{errorMessage}</div>;
} if (pastDelay) {
return <div className="loader">Loading...</div>;
return <div className={styles.loader}>Loading...</div>;
}
return null;
} if (error) {
Expand Down
15 changes: 10 additions & 5 deletions src/js/routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,30 @@ import {
withRouter,
} from 'react-router-dom'

import LazyLoading from './common/components/LazyLoading'
import LazyLoading from 'common/components/LazyLoading'

const ExampleRouteHandler = LazyLoading(() => import('./views/example'))
const Header = LazyLoading(() => import('./common/components/Header/Header'))
import styles from '../style/index.css'

// This is show case how you can lazy loading component
const ExampleRouteHandler = LazyLoading(() => import('views/example'))
const Header = LazyLoading(() => import('common/components/Header/Header'))

// Please remove that, it is an example
const JustAnotherPage = () => (
<div>
<h2>This is Just Another Page</h2>
<p>Please remove this from your route, it is just to show case basic setup for router.</p>
</div>
)

// This show case how you can access routing info in your component
const HeaderWithRouter = withRouter((props) => <Header {...props} />)

module.exports = (
<div className="container">
<div className={styles.container}>
<HeaderWithRouter />
<hr />
<div className="container__content">
<div className={styles.content}>
<Switch>
<Route exact path="/" component={ExampleRouteHandler} />
<Route path="/page" component={JustAnotherPage} />
Expand Down
97 changes: 0 additions & 97 deletions src/js/utility/validation.js

This file was deleted.

10 changes: 10 additions & 0 deletions src/js/views/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Convention

The organization of `views` is suggested as follows:

* Folders correlate to the most significant portion of the URL to map to in case and spelling within the application, and not including the application mount point if there is one.
* Example: if a URL named `/avengers-search/` maps to a page, then we should have a `views/avengers-search/` folder that exports a component that manages the `avengers-search` page.
* NOTE: Due to React component naming requirements, the variable that references the "page" should always be PascalCased, e.g. avengers-search -> AvengersSearch.
* Each folder should make use of the `index.js` trick to allow importing of the folder.
* Major sub views that correlate to URLs should, if appropriate, also be organized within the parent view folder.
* Besides `index.js`, the main coordinating file should be named `View.jsx`, and this is the file that should be exported as default from `index.js`.
File renamed without changes.
1 change: 1 addition & 0 deletions src/js/views/example/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './View'
13 changes: 7 additions & 6 deletions src/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
font-size: 16px;
margin-left: 60px;
margin-right: 60px;
}

.container__content {
}
.content {

}

h1, h2 {
/* This is how you use custom fonts */
font-family: YourFavoriteFont;
h1, h2 {
/* This is how you use custom fonts */
font-family: YourFavoriteFont;
}
}
7 changes: 6 additions & 1 deletion webpack.config.build.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ webpackConfig.module.rules = webpackConfig.module.rules.concat({
},
{
loader: 'css-loader',
options: { sourceMap: true, importLoaders: 1 },
options: {
sourceMap: true,
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]_[hash:base64]',
},
},
{
loader: 'postcss-loader',
Expand Down
7 changes: 6 additions & 1 deletion webpack.config.dev-server.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ webpackConfig.module.rules = webpackConfig.module.rules.concat({
},
{
loader: 'css-loader',
options: { sourceMap: true, importLoaders: 1 },
options: {
sourceMap: true,
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]_[hash:base64]',
},
},
{
loader: 'postcss-loader',
Expand Down

0 comments on commit 68b6281

Please sign in to comment.