Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WorkWave Frontend Technologies

WorkWave Frontend Technologies

Internal presentation of technologies used in WorkWave projects

Matteo Ronchi

January 25, 2017
Tweet

More Decks by Matteo Ronchi

Other Decks in Programming

Transcript

  1. • Server-side generated HTML pages • Static CSS files •

    Most interactions trigger a page reload • Javascript is used only for UI interactions • Javascript is inlined inside the HTML code • Limited User Experience • Poor Developer Experience
  2. • Javascript generated HTML pages • Compiled CSS • The

    page is never reloaded • Javascript is used for everything • Javascript files are compiled, minified and bundled • Improved User Experience • Rich Developer Experience
  3. <div> <h1 id="my-title"></h1> <p id="my-contents"></p> </div> <script type="text/javascript"> $(document).ready(() =>

    { $.ajax("my-url.php") .done((data) => { $("#my-title").text(data.title) $("#my-contents").text(data.contents) }) }) </script> JQUERY
  4. <div ng-app="app"> <my-page my-url="my-url.php"></my-page> </div> <script type="text/javascript"> angular.module("app", []).directive("myPage", function($http)

    { return { scope: { myUrl: "@"} template: `<div> <h1>{{myTitle}}</h1> <p>{{myContents}}</p> </div>` link: function(scope) { $http.get(scope.myUrl).success((data) => { scope.myTitle = data.title scope.myContents = data.contents }) } } }) </script> ANGULAR
  5. <div id="root" /> <script type="text/javascript"> class App extends React.Component {

    componentWillMount() { axios.get(this.props.myUrl).then(({ title, contents }) => { this.setState({ title, contents }) }) } render() { return ( <div> <h1>{this.state.title}</h1> <p>{this.state.contents}</p> </div> ) } } ReactDOM.render( <App myUrl="my-url.php" />, document.getElementById("root") ) </script> REACT
  6. PROS Maintained by Google Declarative syntax Encourage code maintainability Encourage

    Components reusability Built-in utilities to facilitate Unit tests Play nice with distributed teams Rich ecosystem of ready-to-use components Huge number of developers available
  7. “You can think of a module as a container for

    the different elements of your app.”
  8. A MODULE CAN BE The whole Application A single Component

    A collection of Components and/or services
  9. function loadBeers($http) { return function (){ // load data from

    remote source return $http.then( function dataReceived(result)) { return result.data } } } angular.module('myApp') .factory('loadBeers', loadBeers) SERVICE - FACTORY - PROVIDER
  10. –Angular Docs “Angular services are substitutable objects that are wired

    together using dependency injection. You can use services to organize and share code across your app. Lazily instantiated – Angular only instantiates a service when an application component depends on it. Singletons – Each component dependent on a service gets a reference to the single instance generated by the service factory.”
  11. // JS function myCtrl($scope, loadBeers) { loadBeers().then( function beerLoaded(beers) {

    $scope.beers = beers }) } angular.module(‘myApp') .controller('myCtrl', myCtrl) // HTML <body ng-app="myApp"> <div ng-controller="myCtrl"> <ul> <li ng-repeat="beer in beers track by $index”> {{beer}} </li> </ul> </div> </body> CONTROLLERS
  12. // JS function beer() { return { scope: { provider:

    '=' }, restrict: 'E', // E = Element, A = Attribute templateUrl: 'beerTemplate.html' } } angular.module('myApp').directive('beer', beer) // beerTemplate.html <li>{{provider.name}} - {{provider.price}}€</li> // main-view.html <ul> <beer ng-repeat="beer in beers track by $index” provider="beer" ></beer> </ul> DIRECTIVES
  13. –Angular Docs “At a high level, directives are markers on

    a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.”
  14. // DOM <input id="toggleShowHide" type="checkbox"> <div id="status"></div> <div id="showText">Hello JQuery!</div>

    // JS $(function() { function toggle() { var isChecked = $('#toggleShowHide').is(':checked') $('#status').text('Status: ' + isChecked) var specialParagraph = $('#showText') if (isChecked) { specialParagraph.show() } else { specialParagraph.hide() } } $(‘#toggleShowHide’).change( function() { toggle() }) toggle() }) ANGULAR VS JQUERY
  15. // DOM <body ng-init="showText = false"> <input ng-model="showText" type="checkbox" >

    <div>Status: {{showText}}</div> <div ng-show="showText"> Hello Angular! </div> <body> ANGULAR VS JQUERY
  16. &

  17. angular.module('wwLoaderLayer') .component('wwLoaderLayer', { template: ‘ww-loader-layer.html’, bindings: { showAtLoading: '@' },

    controller($document, toggleLoaderLayer) { let modal let toggleLoaderLayerSubscriber const toggleLoaderLayerSignalReceived = (status) => { const action = status ? undefined : 'hide' modal.modal(action) } this.$onInit = () => { toggleLoaderLayerSubscriber = toggleLoaderLayer.subscribe(toggleLoaderLayerSignalReceived) } this.$postLink = () => { modal = $document.find('#loader-layer') } this.$onDestroy = () => { toggleLoaderLayerSubscriber.unsubscribe() } } }) ANGULAR COMPONENT
  18. RX.JS “An API for asynchronous programming with observable streams” [reactivex.io]

    Can be used to implement Unilateral data flow architectures Offers powerful operators to create really complex async workflows Very steep learning curve
  19. – reactivex.io “ReactiveX is a combination of the best ideas

    from the Observer pattern, the Iterator pattern, and functional programming”
  20. View User Interactions User Store A Store B Actions Web

    API Web Socket Screen Stream Updated Data Pass Data To Store Store
  21. ANGULAR TIMELINE AngularJS was originally developed in 2009 by Misko

    Hevery and Adam Abrons Misko Hevery started to work for Google in 2009 1st release of AngularJS: 1 developer, 3 weeks, 1000 loc AngularJS version 1.0 was released in 2012 by Google Angular version 2 was released in September 2016 after 2 years development
  22. ANGULAR FEATURES Optimized for both desktop and mobile Ahead of

    Time (AoT) compilation Incredible performances Native Reactive support (Rx.js)
  23. import { Injectable } from `angular2/core`; @Injectable() export class MyService

    { constructor(private loadData:LoadData) {} getData() { return this.loadData.load(); } } @INJECTABLE
  24. import { Component } from '@angular/core'; @Component({ selector: 'hello', template:

    '<p>Hello, {{name}}</p>' }) export class Hello { name: string; constructor() { this.name = 'World'; } } @COMPONENT
  25. import { Directive, HostListener } from '@angular/core'; @Directive({ selector: `[confirm]`

    }) export class ConfirmDirective { @HostListener(`click`, [`$event`]) confirmFirst(event: Event) { return window.confirm( `Are you sure you want to do this?` ); } } // Usage <button type="button" (click)="visitOtherPage()" confirm>Visit another page</button> @DIRECTIVE
  26. import { Component } from '@angular/core'; @Component({ selector: `product-price`, template:

    `<p>Price: {{ price | currency }}</p>` }) export class ProductPrice { price: number = 99.99; } @PIPES
  27. import {Injectable} from '@angular/core'; import {Http, Response} from '@angular/http'; import

    {Observable} from 'rxjs'; import {Hero} from './hero'; @Injectable() export class LoadDataService { constructor(private http: Http) {} search(term: string): Observable<Hero[]> { return this.http .get(`app/heroes/?name=${term}`) .map((r: Response) => { return r.json().data as Hero[] }); } } HTTP SERVICE
  28. ANGULAR $DIGEST CYCLE AngularJS engine is built using a dirty

    checking algorithm. Application state is a single entity connected to every visual component and calculated every time a component mutates some data It’s very easy to trigger unwanted $digest cycles impacting performances Very difficult to debug
  29. ANGULAR 2 CHANGE DETECTION Based on ngZone Recalculate the components

    tree state after every async interaction (events, timers, observables..) Every component has its own Change Detector Component’s Change Detector is generated at runtime to improve performances Developers control how and when components are recalculated
  30. – ngBook2 “When one of the components change, no matter

    where in the tree it is, a change detection pass is triggered for the whole tree, from top to bottom.”
  31. CHANGE DETECTION TRAVELS TOP TO BOTTOM CD CD CD CD

    CD CD CD CD Change Detection Flow
  32. ANGULAR 2 CHANGE DETECTION Every component gets a change detector

    responsible for checking the bindings defined in its template ChangeDetectionStrategy: - default: update the component every time data changes - onPush: update the component only when its inputs change or the component requests to be updated
  33. CONS Is not a framework Developers must have a strong

    knowledge of javascript automation tools Weird template syntax(at first glance)
  34. const Label = (props) => <h1>{props.children}</h1> const Icon = (props)

    => { return ( <i className="fa fa-anchor"> {props.label} </i> ) } const App = () => <div> <Label>Some label</Label> <Icon label="ready to sail" /> </div> STATELESS FUNCTIONAL COMPONENTS
  35. class Toggle extends React.Component { constructor(props) { super(props) this.state =

    { enabled: false } this.toggle = this.toggle.bind(this) } toggle() { this.setState({ enabled: !this.state.enabled }) } render() { const cls = this.state.enabled ?'btn-success':'btn-danger' return ( <button className={‘btn ‘ + cls} onClick={this.toggle}> {this.props.label} </button> ) } } STATEFUL COMPONENTS
  36. class MyComponent extends React.Component { // Component Initialization constructor(props) {}

    // component ready to be mounted componentWillMount() {} // Props have changed componentWillReceiveProps(nextProps) {} // prevent rendering if not required shouldComponentUpdate(nextProps, nextState) {} // Prepare before rendering componentWillUpdate(nextProps, nextState) {} } COMPONENT LIFECYCLE
  37. class MyComponent extends React.Component { // create/update the component render()

    {} // Component DOM it’s been created componentDidMount() {} // Component DOM it’s been updated componentDidUpdate(prevProps, prevState) {} // cleanup before component destruction componentWillUnmount() {} } COMPONENT LIFECYCLE
  38. function applyVat(vat) { return (value) => ((vat + 100) /

    100) * value } const applyVat22 = applyVat(22) console.log(applyVat22(100)) // print -> 122 function maybe(condition, action) { if (condition) { action() } } const action = (msg) => () => console.log(msg) maybe(true, action(`It works!`)) maybe(false, action(`Doesn't work!`)) // print -> It works! HOF
  39. const Wrapped = () => <h1>Wrapped Comp</h1> const wrapper =

    (Comp) => () => { return <div><Comp /></div> } const FinalComponent = wrapper(Wrapped) const App = () => { return ( <div> <FinalComponent /> </div> ) } SIMPLE HOC
  40. WORKWAVE UNIFIED UI NodeJS based project’s automation Production bundle created

    with Webpack Unilateral data flow with redux Async sequences with redux-saga Online documentation Live styleguide
  41. WORKWAVE UNIFIED UI COMPONENTS LIBRARY Reusable independent components Themed Components

    Ad-hoc Theme engine CSS in JS styling (runtime generated CSS classes)
  42. WORKWAVE UNIFIED UI Uses both library projects Support dynamic theming

    Client-server communication via WebSocket WorkWave SSO