Serverless Single Page Apps with React and Redux at ItCamp 2017

65
@ITCAMPRO #ITCAMP17 Community Conference for IT Professionals Serverless Single Page Apps with React and Redux Solution Architect at Haufe Group / #melaniadanciu /mela.ro Melania Andrisan

Transcript of Serverless Single Page Apps with React and Redux at ItCamp 2017

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Serverless Single Page Apps with

React and Redux

Solution Architect at Haufe Group / #melaniadanciu /mela.ro

Melania Andrisan

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Many thanks to our sponsors & partners!

GOLD

SILVER

PARTNERS

PLATINUM

POWERED BY

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Serverless Mindset

Serverless backend

The serverlessweb app

Demo

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

SERVERLESS

It is all about functions and now servers to manage for these functions

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

SERVERLESS IS:

“CORE OF THE FUTURE OF

THE DISTRIBUTED

COMPONENTS”

Satya Nadella

Build 2017 Keynote 1

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Evolution…

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Good to know about Serverless

• Keeping micro-services stateless and immutable

• Focus more on product then infrastructure

• Less Control

• Less Responsibility

• Increased Automation

• Continuous scaling

• No pay for idle

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Easy to change

Static websites

Scalable out of the box

0 Cost for idle time

Security as a service

Authentication and Authorization as a service

DB as a serviceMonitoring as service

Identity management

NoSQL

Easy to maintainCDN as Service

Messaging

A lot more…

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

AWS

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

My app as 3-tier Architecture

App

API GatewayFunctions

Cloud LogicData Storage

Static File Storage

Browser

Static Website

Backend Logic Storage

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

My App on Amazon…

S3

API Gateway AWS Lambda Functions

Browser

DynamoDB

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Microsoft Serverless Offer…

Browser

Azure Cloud Functions

Azure CDN

API Management Cosmos DB

Azure Blob Storage

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

My Project structure

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Serverless Mindset

Serverless backend

The serverlessweb app

Demo

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

BACKEND…

Lambda Functions, AWS Services: Cognito, Dynamo DB, S3

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

serverless/

handlers/

contact/

lib/

contact.js

helper.js

event.json

handler.js

lib/

utils.js

serverless.yml

My Serverless folder structure

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Contracts

Documents

Assets

Contacts

FinanceDoc Storage

Asset UtilitiesExternal Service

API Gateway

S3

DynamoDB

Cloud Formation with Serverless Framework

External Service

Lambda Functions

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

functions:

authorizerFunc:

handler: handlers/authorizer/handler.authorizer

contacts:

handler: handlers/contact/handler.contact

events:

- http:

method: GET

path: /{userId}/contacts/getAll

integration: lambda

cors: true

request: ${file(./templates.yml):request}

authorizer: authorizerFunc

authorizer:

name: authorizer

arn: arn:aws:cognito-idp:us-east-2:165979317528:userpool/us-east-

2_xxxxxxxxx

serverless.yml

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

var contact = require('./lib/contact'),

parser = require('../parser'),

env = require('dotenv').config();

module.exports.contact = (event, context, cb) => {

var event = parser.parseEvent(event),

path = event.path;

switch (path) {

case '/{userId}/contacts':

contact.create(event, context);

break;

case '/contacts/contact/{id}':

contact.view(event, context);

break;

case '/contacts/update':

contact.update(event, context);

break;

case '/{userId}/contacts/getAll':

contact.getAll(event, context);

break;

case '/{userId}/contacts/delete/{id}':

contact.delete(event, context);

break;

default:

context.fail('Invalid api call');

}

};

serverless/

handlers/

contact/

lib/

contact.js

helper.js

event.json

handler.js

lib/

utils.js

serverless.yml

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

var helper = require('./helper');

module.exports.create = (event, context) => {

helper.createContact(event).then(result => {

context.succeed({

result

});

}).catch(err => {

context.fail("Error: " + err + " Event: "

+JSON.stringify(event) );

})

};

…/handlers/contact/lib/contact.js

serverless/

handlers/

contact/

lib/

contact.js

helper.js

event.json

handler.js

lib/

utils.js

serverless.yml

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

function createContact(data) {

let cleanData = utils.removeEmpty(data);

return utils.createItem(cleanData, DB_NAME);

}

…/handlers/contact/lib/helper.js

serverless/

handlers/

contact/

lib/

contact.js

helper.js

event.json

handler.js

lib/

utils.js

serverless.yml

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

function createItem(data, table, item) {

return db('put', {

TableName: DB_PREFIX + table,

Item: data.data

});

}

…/handlers/lib/utils.js

serverless/

handlers/

contact/

lib/

contact.js

helper.js

event.json

handler.js

lib/

utils.js

serverless.yml

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

DEVELOPMENT & DEBUGGING

Serverless-offline, Dynamo DB local

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

More about serverless…

https://www.slideshare.net/melaniadanciu/new-serverless-world-cloud-native-apps

http://dev.haufe.com/Serverless_with_AWS_at_DevTalks/

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Serverless Mindset

Serverless backend

The serverlessweb app

Demo

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

FRONTEND…

React & Redux

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Static Website built with …

• React & Redux

• Unit Testing with Jest, Enzyme, Expect and sinon

• The AJAX calls are done using fetch()

• The style is done using a Bootstrap theme

• Airbnd Coding style for react apps

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

REACTFacebook

A declarative, efficient, and flexible JavaScript

library for building user interfaces.

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

import React from 'react';

import { Button, Glyphicon } from 'react-bootstrap';

export default function LoaderButton({ isLoading, text, loadingText, disabled =

false, ...props }) {

return (

<Button disabled={ disabled || isLoading } {...props}>

{ isLoading && <Glyphicon glyph="refresh" className="spinning" /> }

{ ! isLoading ? text : loadingText }

</Button>

);

}

imports

Component declaration

UI Render

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

JSX

Each JSX element is just syntactic sugar for calling React.createElement(component,

props, ...children). So, anything you can do with JSX you can also be done with just plain

JavaScript.

https://facebook.github.io/react/docs/react-without-jsx.html

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

JSX Component(ES6)

import React from 'react';

import CustomButton from './CustomButton';

function WarningButton() {

// return React.createElement(CustomButton, {color: 'red'},

null);

return <CustomButton color="red" />;

}

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

COMPONENT LIFECYCLE

constructor()

componentWillMount()

render()

componentDidMount()

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Component Initialized Props Changed setState() Component Deleted

getDefaultProps() componentWillReceiveProps()

componentDidUpdate()

shouldComponentUpdate()getInitialState()

componentWillUpdate()

render()

componentWillMount()

componentDidMount()

componentWillUpdate()

First timeAfter first time

setState() doesn’tTrigger re-rendertrue

https://kunigami.blog/2015/04/28/react-js-introduction/

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

CREATE-REACT-APPhttps://github.com/facebookincubator/create-react-app

Create-react-app –> to create the project

React-scripts –> npm start; npm test; npm run build

No server rendering

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

JavaScript entry point

Page Template

The main React Component

create-react-app my-app

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Modern react app

• React, JSX, ES6, and Flow syntax support.

• Language extras beyond ES6 like the object spread operator.

• A dev server that lints for common errors.

• Import CSS and image files directly from JavaScript.

• Auto-prefixed CSS, so you don’t need -webkit or other prefixes.

• A build script to bundle JS, CSS, and images for production, with

sourcemaps.

• An offline-first service worker and a web app manifest, meeting all

the Progressive Web App criteria.

https://github.com/facebookincubator/create-react-app#why-use-this

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

React lessons learned

• Focus on small reusable components

• Do not use component inheritance

• Use Type-checking with propTypes

• Check that your UI is working using unit test and see their result in

real time

• Take care of performance using immutable elements or implement

shouldComponentUpdate

• Read the React documentation carefully and understand the

concepts behind it, there is no 2-way binding with React

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

REDUX

Dan Abramov

App data-flow architecture

App state management

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

LEARN ABOUT IT

Dan Abramov - Live React: Hot Reloading with Time Travel at react-europe 2015 -

https://www.youtube.com/watch?v=xsSnOQynTHs

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Flux Data-Flow Architecture

Action Dispatcher Store View

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Flux Data-Flow

Action

Action

Dispatcher Store View

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Flux Data-Flow

Action

Action

Dispatcher StoreView

[controller-view]

Actions creators – helper methods,create an action from method paramsassign a type and provide it to the dispatcher.

Every action is sent to allStores via callbacks

After stores updated themselves, They emit a change event.

The view listen to changeEvents, retrieve data from the store and provide thenew data to the entire treeOf their children views.

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

REDUCERS+FLUX = REDUX

Elm + Flux => Redux

Dan Abramov - The Redux Journey at react-europe 2016

https://www.youtube.com/watch?v=uvAXVMwHJXU

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Redux Data-Flow

Reducer[Pure function]

UI View

Store[Holds current state]

Action Creator

onClick() eventsUser Interaction

Update stateNew State

Dispatch action

Actions are events

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Constrains and their benefits

• Single State tree

• Actions Describe Updates

• Reducers Apply Updates

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

ACTIONS

= events

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

export function createContactSuccess(contact) {

return { type: ActionTypes.CREATE_CONTACT_SUCCESS, contact: contact }

}

actions/contactActions.js

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

REDUCER

Pure functions

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

import ActionTypes from '../actions/constants/actionTypes'

import InitialState from './initialState'

export default function displayReducer(state =InitialState.display, action) {

switch (action.type) {

case ActionTypes.DISPLY_CONTACT:

return { ...state, selectedContact: action.contact }

default:

return state;

}

}

Contact reducer

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Combine reducers: reducers/index.js

const rootReducer = combineReducers({

contacts, //short hand property name

addressCategories,

display,

assets,

userSettings,

ajaxStatus,

modals: modalReducer

});

export default rootReducer;

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

SELECTORS

Like Map state to props

(state, …args) =>derivation

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Selectors

export function contactsFormatedForDropdown(contacts) {

return contacts.map(contact => {

return {

value: contact.id,

text: contact.firstName + ' ' + contact.lastName

}

})

}

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

STORE

The application state

Dispatch action & Register listener

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

import {createStore, applyMiddleware} from 'redux';

import rootReducer from '../reducers';

import thunk from 'redux-thunk';

export default function configureStore(initialState){

return createStore(

rootReducer,

initialState,

//handle async actions in API calls

applyMiddleware(thunk)

//for dev mode applyMiddleware(reduxImmutableStateInvariant())

);

}

store/configureStore.js

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

REDUX THUNK

https://github.com/gaearon/redux-thunk

Redux Thunk middleware allows you to write action creators that return a function

instead of an action.

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

export function saveContact(contact, userToken) {

//thunk -

return function (dispatch, getState) {

dispatch(beginAjaxCall());

return ContactsApi.saveContact(contact, userToken).then((savedContact) => {

contact.id ? dispatch(updateContactSuccess(savedContact)) :

dispatch(createContactSuccess(savedContact));

}).catch(error => {

dispatch(ajaxCallError());

throw (error);

});

}

}

Save a contact action

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Redux Lesson Leaned

• The entire state of you app is a plain js Object an

Immutable State Object

• Redux is build on top of functional programming concepts

• It heavily uses pure functions

• When you learn it do not use starter kits

• It gives order to your code

• Redux DevTools

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Resources

• https://kunigami.blog/2015/04/28/react-js-introduction/

• https://github.com/facebookincubator/create-react-app

• https://facebook.github.io/react/

• https://app.pluralsight.com/library/courses/react-flux-building-applications/table-of-contents

• https://thenewstack.io/best-practices-for-developing-cloud-native-applications-and-microservice-architectures/

• http://flomotlik.me/blog/challenges-of-serverless-in-2017/

• https://github.com/aws/amazon-cognito-identity-js

• https://medium.com/komenco/react-autobinding-2261a1092849

• https://github.com/airbnb/javascript/tree/master/react

• http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#batchWrite-property

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Serverless Mindset

Serverless backend

The serverlessweb app

Demo

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

DEMO

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

• Be stateless on the backend and on the frontend

• Think functional and make your functions as small as possible

• Make you client independent of you backend with no server rendering

• Automate as much as you can your entire development, debugging, testing

and deployment - it saves a lot of time

• And yes, using the cloud provider services means being locked in with that

cloud provider, so you need to manage this risk

5 thinks to take way

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

SEE YOU NEXT TIME!

Thanks

@ITCAMPRO #ITCAMP17Community Conference for IT Professionals

Q & A