Full Stack Scala

  • View
    6.557

  • Download
    0

  • Category

    Internet

Preview:

Citation preview

Full Stack ScalaScala in the backend and frontend!

Ramnivas LaddadFounder, Paya Labs

@ramnivas

@ramnivas

• Spring framework and Cloud Foundry contributor

• Main interests • Scala and functional programming • Cloud computing

• Author of books and articles • AspectJ in Action (1st and 2nd edition)

• Speaker at many professional conferences • JavaOne, ScalaDays, JavaPolis, SpringOne, Software

Development, No Fluff Just Stuff, OSCON etc.

A Quick Demo

High-level Architecture

API Server Static Page Server

html, js, css, …

GET, PUT, POST, DELETE

{ "name" : ...}

Backend Stack

API Server

API Server Static Page Server

html, js, css, …

GET, PUT, POST, DELETE

{ "name" : ...}

API Server

API Server Static Page Server

html, js, css, …

GET, PUT, POST, DELETE

{ "name" : ...}

Backend Structure

Backend Structure

Database

Backend Structure

DatabaseSendgrid

Backend Structure

DatabaseSendgridS3

Backend Structure

DatabaseSendgridS3

Backend Structure

DatabaseSendgridS3

Backend Structure

DatabaseSendgridS3

Backend Structure

Database

Data Access Layer

SendgridS3

Backend Structure

Database

Data Access Layer

SendgridS3

Talk by Rob NorrisPrograms as Values: JDBC Programming with Doobie

Backend Structure

Database

Data Access Layer

SendgridS3

Backend Structure

Database

Data Access Layer

SendgridS3

ApacheCommons

Backend Structure

Database

Data Access Layer

SendgridS3

ApacheCommons

AWSSDK

Backend Structure

Database

Data Access Layer

Service Layer

SendgridS3

ApacheCommons

AWSSDK

Backend Structure

Database

Data Access Layer

Service Layer

HTTP Layer

SendgridS3

ApacheCommons

AWSSDK

Frontend Stack

High-level Architecture

Static Page Server

html, js, css, …

API Server

GET, PUT, POST, DELETE

{ "name" : ...}

High-level Architecture

Static Page Server

html, js, css, …

API Server

GET, PUT, POST, DELETE

{ "name" : ...}

Serving static contentsvar express = require('express');var fs = require('fs');

var app = express();var port = process.env.PORT || 4000;

var devMode = process.env.SERVE_MODE != "SERVE_PROD";

var serveInfo = { dir: __dirname + ‘/dev-bin', maxAge: 0}if (!devMode) {

var oneHour = 60*60*1000;serveInfo = { dir: __dirname + ‘/prod-bin', maxAge: oneHour}

}

app.use(express.static(serveInfo.dir, { maxAge: serveInfo.maxAge }));

app.get('*', function(request, response, next) { response.sendFile(serveInfo.dir + '/index.html');});

app.listen(port, function() {console.log("Started on " + port + " (dev mode = " + devMode + ")\n");

});

High-level Architecture

API Server Static Page Server

html, js, css, …

GET, PUT, POST, DELETE

{ "name" : ...}

High-level Architecture

API Server Static Page Server

html, js, css, …

GET, PUT, POST, DELETE

{ "name" : ...}

Why Scala.js?

Why Scala.js?

Why Scala.js

Scala!

Why Scala.js

Static Types

Why Scala.js

Functional Programming

Why Scala.js

Isomorphism

Why Scala.js

Maturity!

Why Scala.js

Eco-system

UI Framework

Choosing a UI Framework

Choosing a UI FrameworkSimple

Mental Model

Choosing a UI FrameworkSimple

Mental ModelImmutable

Data

Choosing a UI FrameworkSimple

Mental ModelFunctional

programmingImmutable

Data

Choosing a UI FrameworkSimple

Mental Model

Mobile

Functionalprogramming

Immutable Data

Choosing a UI FrameworkSimple

Mental Model

Mobile

Functionalprogramming

Immutable Data

Isomorphism

Choosing a UI FrameworkSimple

Mental Model

CommunityMobile

Functionalprogramming

Immutable Data

Isomorphism

Choosing a UI FrameworkSimple

Mental Model

CommunityMobile

Functionalprogramming

Immutable Data

Isomorphism

What is React?• “A JavaScript library for building user interfaces” by

Facebook

• Focuses just on the UI• Uses virtual DOM• One-way data-flow

Frontend Overview

Frontend Overview

Router

Frontend Overview

Router

Frontend Overview

Router Flux Component

Frontend Overview

Router Flux Component

Frontend Overview

Router

Store

Flux Component

Frontend Overview

Router

Store

Flux Component

Frontend Overview

Router

Store

Flux Component

Rest Client

Frontend Overview

Router

Store

Flux Component

Rest Client

Frontend Overview

Router

Store

Flux Component

Rest Client

Frontend Overview

Router

Store

Flux Component

Rest Client

Frontend Overview

ComponentRouter

Store

Flux Component

Rest Client

Frontend Overview

ComponentRouter

Store

Flux Component

Rest Client

Scala.js with React

• Statically-typed wrapper around React• Fluent, builder API to create components• Well-implemented router (v2)

scalajs-react

Simple Mental Model

View

PropertiesState

Composition

Composition

Composition

Composition

Composition

Real World Composition

Real World Composition

Real World Composition

Mostly Immutable

ComponentRouter

Store

Flux Component

Rest Client

Taking advantage of immutability

def shouldComponentUpdate(scope: ScopeType, nextProps: P, nextState: S) = { scope.props != nextProps || scope.state != nextState}

Flux

Flux Componentobject ArtistRegistrationWrapper extends FluxComponent[String, ArtistEditDto](Seq(ArtistStore, InstrumentStore)) {

def onArtistChange(artist: ArtistEditDto): Unit = { ArtistUpdated(artist).dispatch() }

...

def element(props: String) = { ... div( ArtistRegistration( ArtistRegistrationProps( artist, allInstruments, onArtistChange, onArtistCoverPhotoChange, onArtistProfilsePhotoChange) ) ) }}

Component

object ArtistRegistration extends Component[ArtistRegistrationProps] {

def element(props: ArtistRegistrationProps): ReactTag = { div(…) }}

Responding to events

override def receive = { case ArtistUpdated(newValue) => artist = newValue emitChange() case ArtistSaved => save() emitChange() ...

No sweat undo/redotrait CompositionStore extends AbstractStore { val compositionStack = new UndoStack[Composition]() override def receive = { case NewComposition => compositionStack.clear() loaded() case LoadComposition(c) => compositionStack.clear() compositionStack.push(c) loaded() case UpdateComposition(c) => compositionStack.push(c) emitChange() case UndoComposition => compositionStack.undo() emitChange() case RedoComposition => compositionStack.redo() emitChange() ...}

Mobile: React Native

Mobile: React Native

https://facebook.github.io/react-native

Mobile: React Native

https://github.com/chandu0101/scalajs-react-native

https://facebook.github.io/react-native

Using external components

Bridging Native React Components• Problem:

• You got to use components developed in the wild

• Requires significant boilerplate to make it work from scalajs-react

• Solution: Some macro magic!

Bridging Native React Components• Problem:

• You got to use components developed in the wild

• Requires significant boilerplate to make it work from scalajs-react

• Solution: Some macro magic!

github.com/payalabs/scalajs-react-bridge

Example Bridge Component

case class TagsInput(id: js.UndefOr[String] = js.undefined, className: js.UndefOr[String] = js.undefined, ref: js.UndefOr[String] = js.undefined, key: js.UndefOr[Any] = js.undefined, defaultValue: js.UndefOr[Seq[String]] = js.undefined, value: js.UndefOr[Array[String]] = js.undefined, placeholder: js.UndefOr[String] = js.undefined, onChange: js.UndefOr[js.Array[String] => Unit] = js.undefined, validate: js.UndefOr[String => Boolean] = js.undefined, transform: js.UndefOr[String => String] = js.undefined) extends ReactBridgeComponent

Using TagsInput

div( TagsInput( defaultValue = Seq(“foo","bar"), onChange = printSequence _ ))

Using MDL in React• Problem:

• Components need to be “upgraded”

• Solution:• React wrapper component around a ReactTag• Upgrades element upon mounting• Implicits to avoid noise

Using MDL in React• Problem:

• Components need to be “upgraded”

• Solution:• React wrapper component around a ReactTag• Upgrades element upon mounting• Implicits to avoid noise

github.com/payalabs/scalajs-react-mdl

Example MDL Use

a(className := "mdl-button mdl-js-button mdl-button--raised mdl-button—colored mdl-js-ripple-effect", onClick --> saveAction())("Save").material

Example MDL Use

a(className := "mdl-button mdl-js-button mdl-button--raised mdl-button—colored mdl-js-ripple-effect", onClick --> saveAction())("Save").material

Things on the Horizon

• GraphQL?• Stitch?• Relay?• Falcor?

?Ramnivas Laddad

@ramnivas