Skip to content

Latest commit

 

History

History
264 lines (199 loc) · 10.3 KB

README.md

File metadata and controls

264 lines (199 loc) · 10.3 KB

React Redux Starter Kit

Join the chat at https://gitter.im/davezuko/react-redux-starter-kit Build Status dependencies

Starter kit to get you up and running with a bunch of awesome new front-end technologies, all on top of a configurable, feature-rich Webpack build system that's already setup to provide unit testing, linting, hot reloading, sass imports with CSS extraction, and a whole lot more. Check out the full feature list below!

Redux, React-Router, and React are constantly releasing new API changes. If you'd like to help keep this boilerplate up to date, please contribute or create a new issue if you think this starter kit is missing something!

Where'd the server go?. This starter kit used to come packaged with a Koa server to perform basic server-side rendering. However, despite that, universal rendering remained secondary to the goal of this starter kit, so it made more sense to remove that aspect; after all, do one thing and do it well.

Table of Contents

  1. Requirements
  2. Features
  3. Getting Started
  4. Usage
  5. Structure
  6. Webpack
  7. Styles
  8. Testing
  9. Utilities
  10. Troubleshooting

Requirements

Node ^4.0.0

Features

  • React (^0.14.0)
    • Includes react-addons-test-utils (^0.14.0)
  • React-Router (1.0.0-rc1)
  • Redux (^3.0.0)
    • redux-router (^1.0.0-beta3)
    • react-redux (^4.0.0)
    • redux-devtools
      • use npm run dev:nw to display in a separate window.
    • redux-thunk middleware
  • Karma
    • Mocha w/ Chai and Sinon-Chai
    • PhantomJS
  • Babel
    • react-transform-hmr for hot reloading
    • react-transform-catch-errors with redbox-react for more visible error reporting
    • Uses babel runtime rather than inline transformations
  • Webpack
    • Splits app code from vendor dependencies
    • webpack-dev-server
    • sass-loader with CSS extraction
    • eslint-loader
    • Pre-configured folder aliases and globals

Getting Started

Just clone the repo and install the necessary node modules:

$ git clone https://github.com/davezuko/react-redux-starter-kit.git ReduxStarterApp
$ cd ReduxStarterApp
$ npm install                   # Install Node modules listed in ./package.json (may take a while the first time)
$ npm start                     # Compile and launch

Usage

npm start

Runs the webpack build system with webpack-dev-server (by default found at localhost:3000).

npm run dev:nw

Same as npm run start but opens the debug tools in a new window.

Note: you'll need to allow popups in Chrome, or you'll see an error: issue 110

npm run dev:no-debug

Same as npm run start but disables devtools.

npm run compile

Runs the Webpack build system with your current NODE_ENV and compiles the application to disk (~/dist). Production builds will fail on eslint errors (but not on warnings).

npm run test

Runs unit tests with Karma.

npm run test:dev

Same as npm run test, but will watch for changes and re-run tests.

npm run lint

Run eslint against all .js files in ~/src. This used to be a preloader, but the browser console output could get fairly ugly. If you want development-time linting, consider using an eslint plugin for your text editor.

npm run test:lint

Lint all .spec.js files in of ~/tests.

npm run deploy

Helper script to run tests and then, on success, compile your application.

Configuration

Basic project configuration can be found in ~/config/index.js. Here you'll be able to redefine your src and dist directories, as well as tweak what ports Webpack and WebpackDevServer run on.

Structure

The folder structure provided is only meant to serve as a guide, it is by no means prescriptive. It is something that has worked very well for me and my team, but use only what makes sense to you.

.
├── bin                      # Build/Start scripts
├── build                    # All build-related configuration
│   ├── webpack              # Environment-specific configuration files for Webpack
├── config                   # Project configuration settings
├── src                      # Application source code
│   ├── components           # Generic React Components (generally Dumb components)
│   ├── containers           # Components that provide context (e.g. Redux Providers)
│   ├── layouts              # Components that dictate major page structure
│   ├── reducers             # Redux reducers
│   ├── routes               # Application route definitions
│   ├── stores               # Redux store configuration
│   ├── utils                # Generic utilities
│   ├── views                # Components that live at a route
│   └── index.js             # Application bootstrap and rendering
└── tests                    # Unit tests

Components vs. Views vs. Layouts

TL;DR: They're all components.

This distinction may not be important for you, but as an explanation: A Layout is something that describes an entire page structure, such as a fixed navigation, viewport, sidebar, and footer. Most applications will probably only have one layout, but keeping these components separate makes their intent clear. Views are components that live at routes, and are generally rendered within a Layout. What this ends up meaning is that, with this structure, nearly everything inside of Components ends up being a dumb component.

Webpack

Configuration

The webpack compiler configuration is located in ~/build/webpack. When the webpack dev server runs, only the client compiler will be used. When webpack itself is run to compile to disk, both the client and server configurations will be used. Settings that are bundle agnostic should be defined in ~/config/index.js and imported where needed.

Vendor Bundle

You can redefine which packages to treat as vendor dependencies by editing vendor_dependencies in ~/config/index.js. These default to:

[
  'history',
  'react',
  'react-redux',
  'react-router',
  'redux-router',
  'redux'
]

Aliases

As mentioned in features, the default Webpack configuration provides some globals and aliases to make your life easier. These can be used as such:

import MyComponent from '../../components/my-component'; // without alias
import MyComponent from 'components/my-component'; // with alias

  // Available aliases:
  actions     => '~/src/actions'
  components  => '~/src/components'
  constants   => '~/src/constants'
  containers  => '~/src/containers'
  layouts     => '~/src/layouts'
  reducers    => '~/src/reducers'
  routes      => '~/src/routes'
  services    => '~/src/services'
  styles      => '~/src/styles'
  utils       => '~/src/utils'
  views       => '~/src/views'

Globals

__DEV__

True when process.env.NODE_ENV is development

__PROD__

True when process.env.NODE_ENV is production

__DEBUG__

True when the compiler is run with --debug (any environment).

Styles

All .scss imports will be run through the sass-loader, extracted during production builds, and ignored during server builds. If you're requiring styles from a base styles directory (useful for generic, app-wide styles) in your JS, you can make use of the styles alias, e.g.:

// ~/src/components/some/nested/component/index.jsx
import `styles/core.scss`;

Furthermore, this styles directory is aliased for sass imports, which further eliminates manual directory traversing. An example nested .scss file:

// current path: ~/src/styles/some/nested/style.scss
// what used to be this:
@import '../../base';

// can now be this:
@import 'base';

Testing

To add a unit test, simply create .spec.js file anywhere in ~/tests. The entry point for Karma uses webpack's custom require to load all these files, and both Mocha and Chai will be available to you within your test without the need to import them.

Utilities

This boilerplate comes with two simple utilities (thanks to StevenLangbroek) to help speed up your Redux development process. In ~/client/utils you'll find exports for createConstants and createReducer. The former is pretty much an even lazier keyMirror, so if you really hate typing out those constants you may want to give it a shot. Check it out:

import { createConstants } from 'utils';

export default createConstants(
  'TODO_CREATE',
  'TODO_DESTROY',
  'TODO_TOGGLE_COMPLETE'
);

The other utility, create-reducer, is designed to expedite creating reducers when they're defined via an object map rather than switch statements. As an example, what once looked like this:

import { TODO_CREATE } from 'constants/todo';

const initialState = [];
const handlers = {
  [TODO_CREATE] : (state, payload) => { ... }
};

export default function todo (state = initialState, action) {
  const handler = handlers[action.type];

  return handler ? handler(state, action.payload) : state;
}

Can now look like this:

import { TODO_CREATE } from 'constants/todo';
import { createReducer } from 'utils';

const initialState = [];

export default createReducer(initialState, {
  [TODO_CREATE] : (state, payload) => { ... }
});

Troubleshooting

Nothing yet. Having an issue? Report it and I'll get to it as soon as possible!