/react-webpack-node

Your One-Stop solution for a full-stack universal Redux App!

Primary LanguageJavaScript

React Webpack Node

Dependency Status devDependency Status Gitter npm version

Deploy

Your One-Stop solution for a full-stack app with ES6/ES2015 React.js featuring universal Redux, React Router, React Router Redux Hot reloading, CSS modules, Express 4.x, mongoose.

Demo site:

https://react-webpack-node.herokuapp.com/

Features:

  • isomorphic universal Redux
    • Server-side rendering with React Router 2.x. Having server-side rendering allows you to pre-render the initial state of your components when a user (or search engine crawler) requests a page.
    • Integrating Redux with React Router with Redux Simple Router React Router Redux
    • Asynchonous Data Fetching on server-side rendering
    • Server side authentication + Redirecting for components
  • Hot reloading using react-transform-hmr
  • Webpack for both development and production bundles. It's (in my opinion) the best bundler for JS, CSS, LESS, images, and lots more!
  • CSS Modules allows for modular and reusable CSS. Say goodbye to conflicts (most of them) and global scope
  • Unit Tests with webpack, karma, jsdom, mocha, & sinon
    • Reducers
    • Components
    • Synchronous and Asynchronous Actions
  • Express 4.x server with a ton of middleware
  • Mongoose for MongoDB
  • Procfile to enable deployment to Heroku & Docs on Salt configurations + Deployment for Digital Ocean

Easter Eggs 🥚

This boilerplate has gone through an evolution

React.js -> Facebook Flux -> Alt -> Redux

We have two implementations of universal flux:

  • Redux is on our active master branch
  • Alt (previously implemented) on flux/alt branch. It features iso, react-router and ImmutableJS.

Note: If you have previously used an alt implementation of this repository, please refer to this branch. I will not be updating it as frequently as master, but definitely welcome suggestions!

Motivation

The aim of this repo is to incorporate the best practices to building a non-trivial, performant, secure and quality full-stack apps with React.js and Webpack and Node (hence...react-webpack-node). However, along the way we definitely have had extensive additions to this boilerplate! I am working to document this repo extensively so it would be easy for both beginners and experts to begin dev-ing on it without pulling your hair out.

Why

Redux

I'm really a fan of this implementation of flux for state management. The main principles of having:

  • a single store
  • state being read-only (you have to express an intent to mutate being creating actions)
  • mutations written as pure functions

make it very fun and easy to write predictable code! There's a ton of reasons why, but you should head to the Redux docs to dive in!

alt

Having isomorphic React was one of my key criteria when choosing a Flux library, which helped narrow down the scope of libraries. I found alt's implementation to be clean and simple, and like the option of allowing us to create alt instances or using singletons (and flushing the stores). I also like the direction in which alt is heading.

Instructions

Prerequisites

Install MongoDB as your database:

# Update brew formulae
brew update
# Install MongoDB
brew install mongodb

If you hate MongoDB with a passion and would like to see a postgresql example, check reap out!

Setup your mongoDB directory

Note: Make sure you have the directory and its permissions setup (i.e. /data/db):

sudo mkdir -p /data/db
sudo chown -R `id -u` /data/db

Run your mongoDB server

mongod

Build & Dev

Installation

# Install node modules - this includes those for production and development
# You only need to do this once :)
npm install

Development

# Starts the server with Hot Reloading
# Run webpack through webpack.config.dev.js
npm run dev

Note: If you get an error saying file not found, run npm run build && npm run dev (because the server relies on the compiled file to exist in order to serve those files).

Production

Run the commands below for a production build, i.e. what is deployed to Heroku. If you are deploying to Heroku or similar, we assume that you serving the pages over HTTPS.

# Clean public folder
# Run webpack through webpack.config.prod.js
npm run build

# Start server
## Note: You need MongoDB running
npm start

Deployment

Heroku

heroku create

# Deploy to Heroku server
git push heroku master

# Database on Heroku
heroku addons:add mongohq
# or
heroku addons:add mongolab

# OPTIONAL:

# Rename if you need to
heroku app:rename <newname>

# Open Link in browser
heroku open

Note:

  1. If you are working from a different machine and get heroku does not appear to be a remote repository message, be sure to run git remote add heroku git@heroku.com:appname.git.
  2. For setting up Google Authentication for Heroku and local dev, read the FAQ section

Digital Ocean

  1. Create a Droplet
  2. Follow this or this tutorial to set up nodejs
  3. Follow this tutorial to install mongodb
  4. git clone this repo
npm install
sudo npm install pm2 -g
pm2 start server/index.js
pm2 startup ubuntu
sudo env PATH=$PATH:/usr/local/bin pm2 startup ubuntu -u sammy

Read more on DO config here

AWS

TBD - if you have an interest, please help

Unit Tests

Testing with:

  • karma as test runner
    • karma.conf.js for the main karma configuration (it has webpack configurations)
    • tests.webpack.js which is the single entry file. It uses webpack's require API to find all the files we need that have a -test.js suffix.
  • mocha as the test framework
  • jsdom as my test environment
# Run test once
npm test

# Run in watch mode
npm test:watch

We have unit tests for async (redux) actions, reducers, and components.

Data Flow

A simplistic representation of data flow from server to client is:

Express app.use() receives a request
-> Calls a pre-built webpack file for the server
-> Runs matching of routes in react-router for server
-> Makes async data fetching request
-> Renders Route component to string
-> Construct HTML file (with Meta, Link tags using helmet)
-> Browser receives html file with initial state
-> Client side React.JS kicks in and initializes with given state
-> Continues where it left off
-> Everyone is happy :)

More TBD

Yeoman Generator

If you like using yeoman generators, you could check out this cool yeoman generator by @iiegor!

FAQ

  1. Where do you compile your scss? We use ExtractTextPlugin to extract compiled css in our webpack config file
  2. What loaders do you use for ES6/ ES2015? babel-loader. Seriously, try it!
  3. Google Authentication does not work locally or on heroku!
    1. Follow these steps from Google to create your API keys on Google Developers Console
    2. Under APIs & Auth, Copy your Client ID and Client Secret

Dev

  • For Google Auth to work locally, you need to do the following in your terminal before starting the server:
export GOOGLE_CLIENTID=YOUR_CLIENTID
export GOOGLE_SECRET=YOUR_SECRET

Heroku

  • Fret not! Heroku's covered this pretty well:
heroku config:set GOOGLE_CLIENTID=YOUR_CLIENTID
heroku config:set GOOGLE_SECRET=YOUR_SECRET
heroku config:set GOOGLE_CALLBACK=YOUR_CALLBACK
  1. I do not know how to write React Components/anything in ES6. Help!
    • Don't you worry child. Read this.
    • You can learn more about ES6 (or ES2015) here.

How to Contribute:

Best way to keep up to date is check the issues. I really welcome improvements for all aspects of an app.

  1. Any suggestions/improvements/bugs can be in the form of Pull Requests, or creating an issue.
  2. Coding guidelines:

Credits to webpack-server-side-example, example-app, flux-examples, node-express-mongo-demo, hackathon-starter, web-starter-kit, awesome material-ui, alt and iso, react-starter, reap, isomorphic-redux-app and mxstbr/react-boilerplate

License

MIT