MEAN Stack Weekend

Preview:

Citation preview

MEAN Stack WeekendCowork South Bay 23 & 24 April 2016

Troy MilesTroy Miles aka the RocknCoder

Over 36 years of programming experience

Author of jQuery Essentials

Speaker and writer on all things web & mobile

rockncoder@gmail.com

@therockncoder

Saturday - Front-end DayCheck installations

JavaScript/ES6

TypeScript overview

Angular 2 overview

Package.json

Components

Templates

Annotation

Data binding

Pipes

Routes

Services

Sunday - Backend Day

Node

Express

RESTful API

First Heroku deploy

MongoDB + Mongoose

Using MongoChef

Deploy to Heroku

Next Steps

Summary

What is the MEAN Stack?

MEAN is a free and open-source JavaScript software stack for building dynamic web sites and web applications.

Term coined by Valeri Karpov

MongoDB

MongoDB is an open-source, document database designed for ease of development and scaling.

v3.2

Initial release - 2009

https://www.mongodb.org/

Express

Fast, unopinionated, minimalist web framework for Node.js

v4.13

http://expressjs.com/

Angular

HTML enhanced for web apps!

v2.0.0-beta.15

https://angular.io/

Node.js

Node.js® is a platform built on Chrome's V8 JavaScript runtime for easily building fast, scalable network applications.

v5.11

https://nodejs.org/

Git + GitHub

Free and open source distributed version control system

v2.8

https://git-scm.com/

https://github.com/

Benefits of the MEAN Stack

Isomorphic JavaScript

Open Source / Community Driven

Performance

Low Cost

Isomorphic JavaScript

One language all the way thru

Client/Server JavaScript

JSON as the data transport format

BSON as the data storage format

JavaScript to control Mongo DB

Text

JavaScript / ES6

Why is JavaScript Beautiful?It is a Functional Language - Closer to Lisp and Scheme than Java or C

First Class Functions

Dynamic Objects

Loose Typing

and more...

ECMAScript VersionsVersion Date

ES1 June 1997ES2 June 1998ES3 December 1999ES4 DOA 2006ES5 December 2009

ES6/ES2015 June 2015ES2016 2016

ES5 Array Methods (2009)

forEach

isArray

every

filter

map

reduce

reduceRight

some

forEachlet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // forEach iterates over the array, once for each element, but there is no way to // break outnums.forEach(function (elem, index, arr) { console.log(index + ': ' + elem); });

maplet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // map iterates over all of the elements and returns a new array with the same // number of elementslet nums2 = nums.map((elem) => elem * 2); console.log(nums2);

filterlet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // filter iterates over the array and returns a new array with only the elements // that pass the testlet nums3 = nums.filter((elem) => !!(elem % 2)); console.log(nums3);

reducelet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // reduce iterates over the array passing the previous value and the current// element it is up to you what the reduction does, let's concatenate the stringslet letters2 = letters.reduce((previous, current) => previous + current); console.log(letters2); // reduceRight does the same but goes from right to leftlet letters3 = letters.reduceRight((previous, current) => previous + current); console.log(letters3);

everylet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // every makes sure that every element matches the expressionlet isEveryNumbers = junk.every((elem) => typeof elem === 'number'); console.log('Are all members of junk numbers: ' + isEveryNumbers);

ES6 aka ES2015

for-of

let

const

Template strings

Arrow functions

Classes

Promises

Using ES6 today

let// let allows us to create a block scoped variables// they live and die within the curly braceslet val = 2; console.info(`val = ${val}`); { let val = 59; console.info(`val = ${val}`); } console.info(`val = ${val}`);

constconst name = 'Troy'; console.info(`My name is ${name}`); // the line below triggers a type errorname = 'Miles';

Template strings

Defined by using opening & closing back ticks

Templates defined by ${JavaScript value}

The value can be any simple JavaScript expression

Allows multi-line strings (return is pass thru)

Template strings var state = 'California'; var city = 'Long Beach'; console.info(`This weekend's workshop is in ${city}, ${state}.`); // template strings can run simple expressions like addition var cup_coffee = 4.5; var cup_tea = 2.5; console.info(`coffee: $${cup_coffee} + tea: $${cup_tea} = $${cup_coffee + cup_tea}.`); // they can allow us to create multi-line strings console.info(`This is line #1.this is line #2.`);

Arrow function

var anon_func = function (num1, num2) { return num1 + num2; }; console.info(`Anonymous func: ${anon_func(1, 2)}`); var arrow_func = (num1, num2) => num1 + num2; console.info(`Arrow func: ${arrow_func(3, 4)}`);

for-offor (let elem of pirateArray) { console.info(elem); } // if we want the element and its index we can get it toofor (let [index, elem] of pirateArray.entries()) { if (index === 5) { break; } console.info(`${index}. ${elem}`); } // unlike forEach, continue and break workfor (let [index, elem] of pirateArray.entries()) { if (index === 5) { continue; } console.info(`${index}. ${elem}`); }

Classes// class must exist before usageclass Animal { constructor(name) { this.name = name; this.legs = 2; } showNameAndLegs() { console.info(`${this.name} has ${this.legs} legs.`); } } var myBird = new Animal("Bird"); myBird.showNameAndLegs();

Promisefunction sometimesWorks() { // note: all this function does is return a promise // the promise returns immediately to the caller return new Promise( function (resolve, reject) { // number of milliseconds to delay let delay = getRandomNum(1000, 3000); setTimeout(function(){ // whether it is successful or not let worked = !!Math.floor(getRandomNum(0, 2)); if(worked){ resolve('It worked!'); } else { reject('It failed'); } }, delay); }); }

PromisesometimesWorks().then( // if it is successful, it will come here function (data) { console.info(data); }, // if it fails it will come here function (err) { console.info(err); } ); console.info('Back from promise land');

How to use ES6 today?

Use only the latest browsers

Use a transpiler: Babel, Traceur, Closure, TypeScript

Use Node.js

https://kangax.github.io/compat-table/es6/

Text

Angular 2

AngularJS -> AngularCreated by Miško Hevery and Adam Abrons

Initial release 2009

Angular 2 alpha release 2015

JavaScript MVC

Angular 2 main conceptsComponent

Data binding

Service

Directive

Dependency injection

Module

Component

A class with component metadata

Responsible for a piece of the screen referred to as view.

Template is a form HTML that tells angular how to render the component.

Metadata tells Angular how to process a class

Componentimport {Component, OnInit} from 'angular2/core'import {QuizService} from './quiz-service'@Component({ selector: 'quiz', templateUrl: './templates/quiz.html', providers: [QuizService]}) export class QuizComponent implements OnInit { quizList: IQuizList[]; constructor(private _quizService:QuizService) { } ngOnInit() { this.getQuiz(); } getQuiz() { this.quizList = this._quizService.getQuizzes(); } }

Data bindingComponent —— DOM

{{ value }} —> interpolation

[property] = “value” —> property binding (used to pass data from parent component to child)

(event) = “handler” <— event binding

[(ng-model)] = “property” <—> two way binding

Service

“Substitutable objects that are wired together using dependency injection (DI)”

Used to share code across an app

Lazily instantiated

Angular has no “Service” defined type

DirectivesA class with directive metadata

Two kinds: attribute & structural

Attribute directives alter the look or behavior of an existing element

Structural directives alter the layout by adding, removing, and replacing elements in the DOM

A component is a directive with a view

Directiveimport {Directive, ElementRef, Renderer, Input, OnInit} from 'angular2/core'; @Directive({ selector: '[sizer]'}) export class Sizer implements OnInit { @Input() sizer:string; element:ELementRef; renderer:Renderer; constructor(element:ElementRef, renderer:Renderer) { this.element = element; this.renderer = renderer; } ngOnInit() { this.renderer.setElementStyle(this.element.nativeElement, 'fontSize', this.sizer + '%'); } }

Component + Directiveimport {Directive, Component, ElementRef, Renderer} from 'angular2/core'; import {Sizer} from './sizer'@Component({ selector: 'my-app', providers: [], template: ` <div> <p [sizer]="200">Butter{{name}}</p> </div> `, directives: [Sizer]}) export class App { constructor() { this.name = 'Monkey' } }

Dependency injectionA way to supply a new instance of a class with the fully-formed dependencies it needs

Most dependencies are services

Angular know which services a components by looking at the types of its constructor parameters

Services are injected by an Injector which uses a Provider to create the service

Module

Modules are optional but a best practice

export tells TypeScript that the resource is a module available for other modules

import tells TypeScript the resource in a module

Angular ships a collection library modules

Text

Node.js

Node 5.11

Merged with the io.js project, which was at 3.x

New version of Chrome V8

Supports ES6

Faster

node -v

Node Package Manager

Or npm for short

version: npm -v

upgrade npm: npm install npm -g

Don’t use sudo

Using sudo with npm is not a best practice

sudo chown -R $USER /usr/local

The command makes you the owner of your local directory

That enables apps your in that directory like npm, able to work without more permissions

Node Hello, world.

mkdir hello

cd hello

touch app.js

edit app.js

node app.js

package.jsonrequired properties (error if missing)

name & version

optional properties (warning if missing)

description, repository, & license

other properties

scripts, dependencies, config, etc.

Text

Express

From scratchnpm install express-generator -g

mkdir <app name>

cd <app name>

npm init

(creates package.json file)

npm install express —save

Text

Heroku

Heroku

Create a free heroku account at:

https://www.heroku.com

Download + install heroku toolbelt at:

https://toolbelt.heroku.com/

(the account is free, no credit card necessary)

Heroku version check

You must have a heroku account, no way to move past this point without it

Node > 4.0.0

git > 2.2

Creating a git repo

git init

git add .

git commit -m "initial commit”

Toolbelt commands

heroku create

heroku ps:scale web=1

heroku open

heroku logs —tail

heroku local web

Heroku Local

Create a Procfile

web: npm start

heroku local

Deploy to Heroku

heroku login

heroku create <app-name>

(must be unique)

git push heroku master

heroku open

Text

MongoDB

Top DB-Engines1. Oracle

2. MySQL

3. MS SQL Server

4. MongoDB

5. PostgreSQL

6. DB2

7. MS Access

8. Cassandra

9. Redis

10.SQLite

Who Uses It?Craigslist

eBay

Foursquare

SourceForge

Viacom

Expedia

Parse

LinkedIn

Medtronic

eHarmony

CERN

and more

When to Use MongoDB?

Document Database

High Performance

High Availability

Easy Scalability

Geospatial Data

What is a Document?

An ordered set of keys and values

like JavaScript objects

no duplicate keys allowed

type and case sensitive

field order is not important nor guaranteed

A Contact Managerfirst name

last name

home address

work address

mobile phone

home phone

In SQL - tables & joins

Person table

Address table

Phone number table

Joins necessary to retrieve complete record

In MongoDB

One collection holds it all

Including the arrays

No joins necessary

SQL MongoDB

column field

row document

table collection

database database

joins none

transactions none

MongoDB commands

show dbs

use <database name>

show collections

db.<collection name>.drop()

Find data

db.<collection name>.find(<query>)

skip()

limit()

sort()

pretty()

Insert data

insert()

remove(<query>)

Using Environment Vars

process.env object holds environment vars

Reading: var dbConnect = process.env.dbConnect;

Writing: process.env.mode = ‘test’;

Heroku Environment Vars

Reading - heroku config

heroku config:get var-name

Writing - heroku config:set var=value

heroku config:unset var-name

Setting Environment Vars

http://bit.ly/rc-setenv

Mac terminal - export variable=value

Installing Mongoose

npm install mongoose —save

var mongoose = require(‘mongoose’);

mongoose.connect(<connection string>);

Mongoose SchemaTypes

Array

Boolean

Buffer

Date

Mixed

Number

ObjectId

String

MongoChef

A GUI for exploring and modifying Mongo DBs

Free for non-commercial use

http://3t.io/mongochef/

Resourceshttps://www.mongodb.org/

http://expressjs.com/

https://angular.io/

https://nodejs.org/

http://mongoosejs.com/

https://www.heroku.com/

Summary

The MEAN Stack build web apps and APIs

It is composed of four main components

Allows development in JavaScript throughout