Simply Deploy React.js App to Heroku

If you have read my another post about creating a ToDo app in react you are good to go; if not see this post.

You know that React App is a single page application containing only static assets. So, you only need to setup a mechanism to serve your static assets like CSS, JS, HTML, IMAGE, etc. files when clients ask for. Either you can use market leader HTTP servers like Apache, Nginx, etc or simple Express server that runs in Node.js.

Configuration

Its better to have a separate Webpack configuration file for production as you don’t need everything like in development environment.

// In webpack.prod.config.js
// This file contains the configuration needed by Webpack to compile the sources to bundle.js

const webpack = require('webpack');

// The path module provides utilities for working with file
//  and directory paths. It can be accessed using:
// See: https://nodejs.org/docs/latest/api/path.html
const path = require('path');

module.exports = {
  devtool: 'inline-source-map',
  entry: [
    './src/app.jsx' // this file along with dependency libs will be compiled into one file and loaded
      // See index.html, you will see bundle.js embedded
  ],

  // Production details
  output: {
    // When compiled for production, output file location
    path: './src',
    publicPath: '/',
    filename: 'bundle.js' // Its convention to use this name
  },

  // Bundle lookup dir for included/imported modules
  // By default, bundler/webpack with search here for the scripts
  resolve: {
    modulesDirectories: ['node_modules', 'src'],
    extensions: ['', '.js', '.jsx']
  },

  module: {
    loaders: [
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loaders: ['babel?presets[]=react,presets[]=es2015']
      },
        // I am using SASS as Transpiler for style sheets
      {test: /\.scss$/, loaders: ["style-loader", "css-loader", "sass-loader"]},

    ]
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        // This tells the Webpack and Babel for optimization for performance
        NODE_ENV: JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin(),
    new webpack.NoErrorsPlugin(), // Makes sure Webpack will not compile if Errors
  ]
};

Next, you will install express lib in your app;

$ npm i express --save
// in package.json, this will be added
"express": "^4.14.0",

And then,  you  will need is server.js ; filename is not important, can be anything you like.

// in server.js
const express = require('express');
const app = express();

// Since the root/src dir contains our index.html
app.use(express.static(__dirname + '/src/'));

// Heroku bydefault set an ENV variable called PORT=443
//  so that you can access your site with https default port.
// Falback port will be 8080; basically for pre-production test in localhost
// You will use $ npm run prod for this
app.listen(process.env.PORT || 8080);

 

package.json should be like

"scripts": {
  "start": "webpack-dev-server -d --config webpack.dev.config.js --progress --colors",
  
  "prod": "NODE_ENV=production node server.js",
  "build": "webpack --config webpack.prod.config.js -p --progress --colors",
  "postinstall": "webpack --config webpack.prod.config.js -p --progress --colors"
},

 

Before deployment

Just before deployment to production you might want to see what the changes look like in production from local simulation. So, you build your application into bundle.js and start the express server and see the application in localhost:8080.

$ npm run build

Hash: 7c1ebfcd1440c56817f3 
Version: webpack 1.14.0
Time: 11593ms
 Asset Size Chunks Chunk Names
bundle.js 2.83 MB 0 [emitted] main
 [0] multi main 28 bytes {0} [built]
 + 282 hidden modules

WARNING in bundle.js from UglifyJs
$ npm run prod

> todo@1.0.0 prod /home/john/projects/reactjs/todo
> NODE_ENV=production node server.js

see http://localhost:8080

Procfile for Heroku

You need to create a proc file to tell heroku dyno which command to execute when it boots up.

# in ./Procfile
web: node server.js NODE_ENV=production

web represents a server accessible via HTTP.

What actually happen when deploying?

Series of events occur

  • You push your code to heroku
    • $ git push heroku master
      • Make sure you have added remote called heroku
      • Make sure you are in master branch
  • Heroku will receive the codebase via SSH and detects that its a node.js app.
    • How? it recognizes the file package.json
  • Heroku will install Node.js and NPM
  • runs  $ npm install
  • You might have noticed the script above called postinstall
    • NPM automatically executes the script postinstall after the execution of npm install ends.
    • In this app, this script basically compiles the JS Asset in production environment
      • Uglifies the assets for faster site load time
    • You will see the src/bundle.js file is created
  • Then executes the command in Procfile
  • Then visit your heroku app; you are done!

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s