Tuesday, March 7, 2017

MERN Series Step 1 - Scaffolding and setup

Note: due to decisions made in step 3 of the series, you can skip all steps in here.  Webapp generator is a good generator for a base SPA, but tech-dojo's MERN starter gives you more to begin with.

I'm going to write a series on creating a MERN stack application (MongoDB, Express, React, Node) from scratch to deployment and maintenance.  Why am I going with React instead of Angular?  Well, I've learned some ng1.x with node.js backend, and I like it, and in the process I learned a lot about Javascript.  I tend to agree with most of what Crockford says, and I place great value on the opinions and findings of Eric Elliot, thus my leaning to learn React and not ng > 1.  

The application is going to be a job site type of application.  Yes, I know there are 100's of them out there, but this will hit most what of any application is going to use: Payment, Subscription, Authentication and Authorization, search, DB back end.  I may change out MongoDB for Couchbase, or Amazon DymanoDB, I haven't decided yet.  I'm going to use Amazon Elastic Beanstalk, possibly with Docker containers depending on how complex the back end gets, but I tend to think that won't be necessary at the start.  For front end hosting using S3 as a static website should do fine to start with.

Step 1: Scaffolding with Yeoman
One of the problems I've often seen is where to start with a new application.  Yeoman helps with that by creating a basic project structure for you.  I'm going to start with the webapp generator and add the React recipie, maybe React Router as well, all will be documented.

Starting with yo webapp: (https://github.com/yeoman/generator-webapp#readme) you will be prompted for a couple of items. I included Sass, and Modernizr, and selected TDD for style of DSL.  I am actually going to be using Less, not Sass, but I've cheated and looked ahead, and the Less recipe we'll be following later instructs you to select Sass, but not Bootstrap.  Bootstrap is added later when following the Less recipe.  After your selections it will create your basic file structure, shown below, including starting points for bower.json, package.json, and gulpfile.js, and it will run npm install and bower install for you

     _-----_     ╭──────────────────────────╮
    |       |    │  'Allo 'allo! Out of the │
    |--(o)--|    │    box I include HTML5   │
   `---------´   │ Boilerplate, jQuery, and │
    ( _´U`_ )    │ a gulpfile to build your │
    /___A___\   /│           app.           │
     |  ~  |     ╰──────────────────────────╯
   __'.___.'__
 ´   `  |° ´ Y `

? What more would you like?

 (*) Sass
>( ) Bootstrap
 (*) Modernizr
? What more would you like? (Press <space> to select)Sass, Bootstrap, Modernizr
? Would you like to include jQuery? (Y/n) n
? Choose your style of DSL TDD
   create bower.json
   create package.json
   create gulpfile.js
   create .babelrc
   create .gitignore
   create .gitattributes
   create .bowerrc
   create .editorconfig
   create app\favicon.ico
   create app\apple-touch-icon.png
   create app\robots.txt
   create app\styles\main.scss
   create app\scripts\main.js
   create app\index.html
   create test\spec\test.js
   create test\index.html

I'm all done. Running npm install & bower install for you to install the required dependencies. If this fails, try running the command yourself.


you will end up with a file structure like this:
you will have a reasonable .gitignore, but no git repo set up, so that should be your first step after running the generator
git init
git add *
git commit -m 'initial commit'

It would probably be wise to also add a remote at this point and push code to it, and create a develop branch.  That has our initial scaffold set up, next step is to follow the steps for the recipes we're adding to it.  The webapp page I put the link for above has a recipes link, go to that and we'll start with Less.  Follow the steps on the recipe page to get less working, they're pretty straight forward.  I am adding bootstrap in, and going with the option to add it fully as I don't know what I'm going to be using yet, so we can optimize it later if we need to.

Next up, the React recipe.  This straightforward, no choices to make.  I like to use gulp-inject for getting my app's js files into html pages, so having jsx files in the scripts folder may be an issue, we'll visit that later and see.

Then we're adding React Router for url routing, again, follow the instructions, no choices to be made here.  I did hit a minor hiccup with the recipe instructions.  React is installed as a bower component from the React recipe, but react-router is installed via npm and didn't like that react wasn't there:
npm WARN react-router@3.0.2 requires a peer of react@^0.14.0 || ^15.0.0 but none was installed.  The warning was quashed if you do npm i react --save-dev before installing react-router, not sure if this will cause any issues later.

Finally, we add AWS S3 Deployment recipe.  You'll need an AWS account for this, or deploy using your favorite hosting provider.  I've been working with AWS for a while and find the capability to script out what I want my environments to look like immensely helpful.  I will also follow the advise to utilize asset revisioning, and help to keep my AWS costs lower, so follow that recipe from the AWS S3 Deployment recipe.  FYI, if you haven't served up static site from S3 before, make sure you name the bucket the same as your root website (i.e. for http://somejobsite.com, name your S3 bucket somejobsite.com).  If this is your first time using AWS, you may also need to set up your default credentials so you can publish successfully, see here.  Now you can verify all this with gulp deploy, maybe.  Due to the way the released version of gulp dependencies work, you will get inconsistent results due to race conditions.  I'd recommend using run-sequence plugin, which will take some modifications to your gulpfile and installing another module:
npm i run-sequence --save-dev
Add run-sequence to the declarations in your gulpfile.js:
const runSequence = require('run-sequence');
And last, modify your default task like so:
gulp.task('default', (done=> {
  runSequence('clean''build', () => {
    done();
  });
});

Finally, so we have a good spot to restore to if needed, commit your changes to git
git add *
git commit -m 'scaffolding complete'
git push