mean stack weekend
TRANSCRIPT
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
@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/
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
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