Skip to content

gocreating/express-react-hmr-boilerplate

Repository files navigation

Express-React-HMR-Boilerplate

![Image of Express-React-HMR-Boilerplate] (/src/public/img/logo.png)

A boilerplate for scaffolding production-ready MERN stack projects.

master dev
Build Status Build Status Build Status
Dependency Status Dependency Status -

Demo

https://express-react-hmr-boilerplate.herokuapp.com/

Techniques

  • Nodejs + Express
  • Reactjs + Redux + Redux-Thunk + React-Router + React-Router-Redux + Redux-Form + React-Intl
  • Mongodb + Mongoose + MongoLab
  • Normalizr
  • Livereload
  • Server-Side Rendering (SSR) & State Fetching (Isomorphic)
  • Webpack + Code Splitting
  • CSS Modules
  • ES6/7 + Babel
  • Travis CI
  • Heroku Deploy Script
  • PM2 for Production Serving
  • Examples
    • Todo List App
      • List + Paginate
      • Create
      • Update
      • Delete
    • Passport
      • Jwt Authentication
      • Social Authentication
    • i18n
    • Upload avatar
    • Recaptcha
    • Ajax progress bar
    • Google Analytics
    • Admin System
  • React Native

Setup your new project

Follow the commands below to integrate this boilerplate into your own project as mirror branch.

cd <your_project>
git flow init -d
git remote add -t master mirror https://github.com/gocreating/express-react-hmr-boilerplate.git
git fetch mirror master:mirror # git fetch <remote> <rbranch>:<lbranch>

git flow feature start mirror
git merge --no-ff --no-edit mirror
git flow feature finish mirror

# git flow feature start tune-mirror
# tune the boilerplate to suit your own project
# git flow feature finish tune-mirror

git remote add origin <your_project.git>
git push -u origin master

Once there is a new version of this boilerplate, you can upgrade with the following commands

git checkout mirror
# git pull mirror dev
#          ^^^^^^ ^^^ → upgrade local mirror branch from boilerplate's dev branch
# git fetch mirror dev:mirror --update-head-ok
git checkout develop
git flow feature start upgrade-mirror
git merge --no-ff --no-edit mirror
# solve conflicts
git flow feature finish upgrade-mirror

Installation

npm install -g gulp
npm install

Config MongoDB (Required)

Most services this boilerplate provides rely on mongoDB. You must config your own mongoDB URIs. The only thing you need to do is create your own configs/project/mongo/credential.js based on the provided template configs/project/mongo/credential.tmpl.js.

Config Nodemailer (Optional)

Gmail

Here I take the popular gmail service as example.

  1. Create your own configs/project/nodemailer/credential.js

You can check all supported services here

  1. Fix security issue

If you are going to run tests on travis or deploy the app on heroku, you might meet the issue that the app cannot login your gmail account from travis/heroku server. You need to manually authorize permissions to your testing/production servers.

This is also documented on nodemailer

2.1. Turn on 2-step verification

2.2. Get app passwords

2.3. Replace config's origin password with app password

Config Google Analytics (Optional)

TBD

Config Social Authentication (Optional)

Facebook

TBD

LinkedIn

TBD

Config ReCAPTCHA (Optional)

  1. Get your API keys on reCAPTCHA
  2. Save keys in configs/project/recaptcha/credential.js.

Config Firebase (Optional)

Firebase provides 5GB/user file storage for free and is backed up by google cloud storage service. Thus we use firebase storage for free to host user avatars.

  1. Follow the doc Add Firebase to your Server
  2. Save the credential file to configs/project/firebase/credential.json
  3. Update configs/project/firebase/client.js
  • Open Firebase console

  • Enter your app

  • Go to Auth page

  • Click on 網路設定 and get your configuration

  • Replace the following part with your configuration

    var config = {
      apiKey: '<your-api-key>',
      authDomain: '<your-auth-domain>',
      databaseURL: '<your-database-url>',
      storageBucket: '<your-storage-bucket>'
    };
    
  1. Update configs/project/client.js and configs/project/server.js

Make sure there is a firebase entry in each file:

// configs/project/client.js
module.exports = {
  // ...
  firebase: require('./firebase/client'),
  // ...
};
// configs/project/server.js
module.exports = {
  // ...
  firebase: require('./firebase/credential.json'),
  // ...
};
  1. Setup firebase storage security rule

We follow the doc Secure User Data, and use the following rules to restrict user permissions.

Don't forget to change the project name into your own

service firebase.storage {
  match /b/express-react-hmr-boilerplate.appspot.com/o {
    match /{env}/{userId}/avatar.jpg {
    	allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

Build & Run

For development:

gulp

For production:

gulp build:production
npm start

Test

Test on local

npm test

Test on Travis

There are some sensitive configs inside the project, e.g., facebook app secret or firebase token, while we still need Travis to support our testing automation. Try the following command:

gulp dumpConfigs

It will show you a 3-step instruction to setup private Travis environment variables.

To sync configs on local side and on travis, you need to repeat the steps every time you update configs or tests

Deploy

Deploy on Heroku

Please login heroku first, and run the command

gulp build:production
gulp deploy [--app=<heroku_app_name>] [--create]

Options

  • -a, --app

    Specify new or existing app name of heroku. Default will be package name inside package.json.

  • -c, --create

    If you want to create new app on heroku, please use this switch.

Deploy on local windows system

  1. Allow port 80 for both inbound and outbound
  2. Open terminal as administrator
  3. Launch production server:
set PORT=80 && npm run pm2

Add Free SSL

See SSL FOR FREE

React Native

For development, just use:

npm run android

For production or distributing APK, please refer to the setup part of Generating Signed APK. You can use helper scripts below:

npm run android-keygen
npm run release-android
npm run install-android

Caveats

Form Adapter

We use redux-form as the infrastructure to construct all form elements. Since there is a losing focus issue, please don't render form adapters inside component's render cycle.

// working

class SomeForm extends Component {
  // ...

  someDollarAdapter = ({ input, ...rest }) => {
    return (
      <span>
        <Input input={input} {...rest} /> $NTD
      </span>
    );
  };

  render() {
    return (
      <Form>
        <Field
          name="budget"
          component={FormField}
          label="Budget"
          adapter={this.someDollarAdapter}
          type="number"
        />
      </Form>
    );
  }
};
// broken

class SomeForm extends Component {
  // ...

  render() {
    return (
      <Form>
        <Field
          name="budget"
          component={FormField}
          label="Budget"
          adapter={({ input, ...rest }) => {
            return (
              <span>
                <Input input={input} {...rest} /> $NTD
              </span>
            );
          }}
          type="number"
        />
      </Form>
    );
  }
};

Roadmap

v1.0

v1.0+

  • Disqus Thread
  • Restrict Firebase Upload File (size and MIME type)
  • Information List
  • Stripe Payment System + Donation Button Example
  • Facebook Messenger Bot Example
  • Phone Verification
  • Automatically Refresh Token

Releases

No releases published

Packages

No packages published

Languages