Deploying my weather app

13th Aug 18
forget me not

In this article I go through deploying my app with Node, Express and Heroku.

Run webpack in production mode

Before I start to deploy my app, I will set up webpack for production.  Running wepack -p in the command line will result in setting the Node ENV variable to 'production' and tell the React third party libraries to load the bare bones versions by optimising and minimising the code.  Within package.json I add a separate 'build' script for production.

    "build:dev": "webpack",
    "build:prod": "webpack -p --env production",

Within the webpack config files, I wrap my configuration in a function passing the environment.  I then check whether the environment is set to production or development.

module.exports = (env) => {
  const isProduction = env === 'production';
...

Source maps take a large amount of space and need to be optimised for production:

devtool: isProduction ? 'source-map' : 'inline-source-map',

Currently the bundle.js contains the CSS along with all the javascript code.  The CSS styling will only be applied after all the javascript code is loaded.  This results in a less optimised site.  I will configure webpack to compile a file that just outputs javascript, and a separate file that contains the CSS.  For this we need a to use plugin called ExtractTextPlugin.  

Within the webpack configuration I require the plugin.

const ExtractTextPlugin = require('extract-text-webpack-plugin');

Inside the module.exports I assigned the new instance of ExtractTextString to variable, passing the name of the file we the plugin to create for the styles extraction.

  const CSSExtract = new ExtractTextPlugin('styles.css');

Then within the css rules, I add on the plugins array called the extract method and passing the rules to it.

 test: /\.s?css$/,
        use: CSSExtract.extract({
          use: [
            {
              loader: 'css-loader',
              options: {
                sourceMap: true
              }
            },
            {
              loader: 'sass-loader',
              options: {
                sourceMap: true
              }
            },

          ]
        })

Then I add the plugin within the returned object: 

 ...
      test: /\.(png|jpg|jpeg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[path][name].[ext]'
            }
          }
        ]
      }

    ]
    },
    plugins: [
      CSSExtract
    ],

...

Finally I need add the newly created style file to the index file.

...
    <title>Local Weather App</title>
    <link rel="stylesheet" type="text/css" href="/styles.css" />
...

 

Screenshots of the bundle size for the development environment and production respectively are below.

package size in development
package size in production

Setting up an Express server

Inside my project I create a folder called server outside of the React root directory and a server.js file within where I will write the code for the Node server.  Express is a tool used to create servers with Node.  First I install express with yarn add express.  

server.js

I import express and create a new instance of it.

const express = require('express');
const app = express();

We need to tell Express where I files live and which port it should listen to, for that we use the 'use' method. I pass the return value of express.static which is just a method.  And within the express function we pass the path to the public folder (root directory for React frontend).  I create another variable and use the path module to extract the path.

const path = require('path');
...
const publicPath = path.join(__dirname, '..', 'public');
app.use(express.static(publicPath));

Starting up the server we use the listen method.  I set the port to either the development port (heroku port) or 3000.  Within the listen method you pass two arguments.  The first argument is the port and the second a function that is called when the server is up and running.

const port = process.env.PORT || 3000;

app.listen(port, () => {
  console.log('Server is up!');
});

To run the server we need to run the server.js with node.  In in command line you can run : node server/server.js

 

Deploying on Heroku

I firstly had to create an account with Heroku.  I then installed the Heroku Cli.  Then run the command: heroku login and login.  To create the app, I run heroku create.  This adds a new 'heroku' remote to your git where you can deploy by pushing your code to that remote.  But before you do that, you need to set up the configuration for Heroku.  Within the package.json I add a start script to tell Heroku where the server file is.  

    "start": "node server/server.js",

I now need to make sure Heroku runs webpack to generate all the assets by adding this additional script: 

"heroku-postbuild": "yarn run build:prod"

Then I add these folders / files to to gitignore:

node_modules/
public/bundle.js
public/bundle.js.map
public/styles.css
public/styles.css.map

I now can push my code to the heroku remote.  Take a look https://react-practice-weatherapp.herokuapp.com/!

I have recently completed my apprenticeship.  I am currently building the API to a React JS site using Firebase.