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

Enterprise React

Enterprise React

My Talk from GeeCon Prague 2017 ( biggest Java conference in Czech Republic )

https://2017.geecon.cz/speakers

React in enterprise? You may say: Oh c’mon dude, It’s just a renderer library, how could it be possibly suitable for enterprise where we need so many puzzles for large and maintainable SPA like Dependency Injection, I18n support, Service layer, State Management, Http client, Routing solution, robust Unit testing and E2E solution and many others. In this session I will show you how to get all the pieces together and how we write SPA’s with React at EmbedIT. And yes Typescript is included. P.S.: Pssst, you might be able to ditch Angular after this talk :P

Martin Hochel

October 20, 2017
Tweet

More Decks by Martin Hochel

Other Decks in Technology

Transcript

  1. Enterprise
    React
    Enterprise
    React
    Martin Hochel
    @martin_hotell

    View Slide

  2. Martin Hochel
    SE, Prague / Czech Republic
    @martin_hotell
    github.com/Hotell
    ▪ @ngPartyCz meetup founder
    ▪ Author of ngMetadata
    ▪ Member of @skate_js


    Hello Prague !

    View Slide

  3. I like Backend Developers
    who switched to Front-End

    View Slide

  4. GoF
    Design patterns

    View Slide

  5. Been there. Done that

    View Slide

  6. Join me, and I will
    show you the
    true power of
    programing

    View Slide


  7. Any application that can be written
    in JavaScript, will eventually be
    written in JavaScript.
    Jeff Atwood

    View Slide

  8. Jabbva Script

    View Slide

  9. Javascript

    View Slide

  10. JavaScript - Doesn’t scale ?
    - Refactoring ?
    - Type safety ?

    View Slide

  11. How do you Javascript?

    View Slide

  12. Typescript

    View Slide


  13. Typescript →
    JavaScript that scales

    View Slide

  14. What
    Types,
    little sugar
    ES Next
    ES 2017
    ES 2016
    ES 2015
    ES 5

    View Slide

  15. How
    TypeScript
    file.ts
    JavaScript
    file.js
    TypeScript Compiler
    Output
    ES3/ES5/ES2015
    compliant code

    View Slide

  16. Why
    function add(a: number, b: number) {
    return a + b;
    }
    function add(a, b) {
    return a + b;
    }
    add(1, 3);
    add(1, '3');
    // 4
    // ‘13’

    View Slide

  17. Vanilla JS
    Type
    checking

    View Slide

  18. Building ui
    that scales

    View Slide

  19. GWT
    Vadin
    Wicket
    Building UI
    Past
    - JQuery / Mootools / Prototype

    View Slide

  20. Building UI
    Now
    - Web Apps / SPA
    - Data driven

    View Slide

  21. Scalable App?
    Let’s use a framework!

    View Slide

  22. View Slide

  23. React

    View Slide


  24. React
    A JavaScript library for building
    user interfaces

    View Slide

  25. UI
    fn() render
    props
    state

    View Slide

  26. Components

    View Slide

  27. import React, { Component } from 'react'
    import { render } from 'react-dom'
    type Props = { name: string }
    class HelloMessage extends Component {
    render() {
    return Hello {this.props.name}
    }
    }
    const mountNode = document.getElementById('app')
    render(, mountNode)
    Component

    View Slide

  28. render() {
    return Hello {this.props.name}
    }
    WTF JSX ?
    render() {
    return React.createElement(
    'div', null, 'Hello ', this.props.name
    )}
    {
    type: 'div',
    props: {
    children: ['Hello', 'Jane'],
    },
    }

    View Slide

  29. WTF VDOM

    View Slide

  30. Type
    safety

    View Slide

  31. React
    - Easy to learn
    - Functional approach
    - A templating system built
    right into the language
    - It’s just
    JavaScript/Typescript

    View Slide

  32. Until you start to build something

    View Slide

  33. View Slide

  34. How (we) to build
    Scalable Enterprise React Apps

    View Slide

  35. The Missing puzzle
    Bundler/Compiler
    Task runner
    Package manager
    HTTP Client
    Service architecture
    State management
    Router
    Forms
    I18n / l10n
    Date/time handling
    Design patterns
    Dependency Injection
    Unit/Integration testing
    E2E testing
    App scaffold
    Style guides

    View Slide

  36. Task runner / package manager

    View Slide

  37. Yarn

    View Slide


  38. FAST, RELIABLE, AND
    SECURE DEPENDENCY
    MANAGEMENT.

    View Slide

  39. yarn

    View Slide

  40. yarn

    View Slide

  41. Bundler

    View Slide

  42. Webpack

    View Slide

  43. webpack

    View Slide

  44. Webpack Senior Developer Task Force

    View Slide

  45. create-react-app
    create-react-app my-app --scripts-version=react-scripts-ts

    View Slide

  46. View Slide

  47. Moar Tooling

    View Slide

  48. Moar
    Tooling
    Prettier
    "fix things for me, please".
    TSLint
    "let me know about problem, so I can fix them".
    Husky + Lint-staged
    Commitizen / Conventional Changelog
    Standard-versioning

    View Slide

  49. View Slide

  50. Releases

    View Slide

  51. Architecture Challenges

    View Slide

  52. 1. How do we structure components ?

    View Slide

  53. View Slide

  54. Component
    Architecture
    Smart
    Dumb
    Dumb
    Dumb
    Dumb
    “how things look”
    “how things work”

    View Slide

  55. This scales just ok!
    Until it doesn’t

    View Slide

  56. import httpClient from '../http-client'
    type State = {
    results: Array
    }
    type Props = {}
    const SEARCH = '//api.github.com/search/repositories'
    export class GithubRepoList extends Component {
    state = {
    results: [],
    }
    componentDidMount() {
    httpClient.get(`${SEARCH}?q=react`).then(({ data }) => {
    this.setState({
    results: data || [],
    })
    })
    }
    }
    How to unit test this code ?

    View Slide

  57. Mocking !
    Now you have 2 problems

    View Slide

  58. DI

    View Slide




  59. const injectables: Injectables = {
    i18n: new I18n(),
    httpClient: new HttpClient(),
    endpoints: {
    search: '...',
    },
    }
    type Props = Pick
    class GithubRepoList extends Component {
    componentDidMount() {
    const { httpClient, endpoints } = this.props
    httpClient
    .get>(`${endpoints.search}?q=react`)
    .then(({data}) => {
    this.setState({results: data || [],})
    })
    }
    }
    const EnhancedGithubRepoList = inject(
    ({ httpClient, endpoints }: Injectables) => ({ httpClient,endpoints})
    )(GithubRepoList)

    View Slide

  60. React DI React context
    pattern
    HOC pattern
    IoC - InversifyJS

    View Slide

  61. Done ?

    View Slide

  62. class GithubRepoList extends Component {
    componentDidMount() {
    const { httpClient, endpoints } = this.props
    httpClient
    .get>(`${endpoints.search}?q=react`)
    .then(({data}) => {
    this.setState({results: data || [],})
    })
    }
    }
    Tight
    coupling

    View Slide

  63. View Slide

  64. 2. How do we handle
    state management / data flow ?

    View Slide

  65. Redux

    View Slide

  66. Redux
    Store

    View Slide

  67. 3. How do we handle
    Service layer / business logic ?

    View Slide

  68. export class AuthService {
    constructor(private httpClient: HttpClient) {}
    login({ username, password, rememberMe }):Promise{
    return this.httpClient
    .post(LOGIN_URL, {
    username,
    password,
    rememberMe,
    })
    }
    logout(): Promise {
    return this.httpClient.get(LOGOUT_URL)
    }
    }
    Services
    /
    Business
    Logic

    View Slide

  69. 4. How State management
    communicates with
    Service layer ?

    View Slide

  70. State
    management
    layer
    Rest service A Rest service B Service Logic
    Epics

    View Slide

  71. Redux Observable

    View Slide

  72. An Epic is the core primitive of
    redux-observable

    View Slide

  73. Epic
    fn() Observable
    Observable
    Reducers

    View Slide

  74. const pingEpic = action$ =>
    action$.ofType('PING')
    .mapTo({ type: 'PONG' })
    Simple
    Epic

    View Slide

  75. import { createEpicMiddleware } from 'redux-observable'
    import { authService } from './auth/auth.service'
    import { userService } from './user/users.service'
    import rootEpic from './app.epics
    const epicInjectables = { authService, userService }
    createEpicMiddleware(rootEpic, {
    dependencies: epicInjectables,
    })
    Epics
    DI setup

    View Slide

  76. const fetchUserEpic = (
    action$: ActionsObservable,
    store: Store,
    { userService }: Injectables
    ) =>
    action$
    .ofType('FETCH_USER')
    .mergeMap(({ payload }) =>
    userService.get(payload.id)
    .then(response => ({
    type: 'FETCH_USER_FULFILLED',
    payload: response,
    }))
    )
    Epics
    DI use

    View Slide

  77. 5. How State management / Service
    layer communicates with
    Presentation Layer ?

    View Slide

  78. State
    management
    layer
    Rest service A Rest service B Service Logic
    Sandbox
    Presentation layer A Presentation layer B Presentation layer C

    View Slide

  79. Sandbox pattern

    View Slide

  80. export const withUserSandbox = compose(
    connect(mapStateToProps, mapDispatchToProps),
    inject(mapInjectables),
    translate(),
    reduxForm()
    )
    export type UserSandboxProps = {...}
    Sandboxed
    HOC
    composition
    type Props = {} & UserSandboxProps
    class UserContainer extends Component{...}
    export default withUserSandbox(UserContainer)

    View Slide

  81. 6. How do you keep contract with
    Backend data models ?

    View Slide

  82. App

    View Slide

  83. 7. Unit testing

    View Slide

  84. Jest

    View Slide


  85. Jest →
    Delightful JavaScript
    Testing

    View Slide

  86. Jest
    Snapshots

    View Slide

  87. 8. E2E Testing

    View Slide

  88. TestCafe

    View Slide


  89. TestCafe →
    A node.js tool to automate
    end-to-end web testing

    View Slide

  90. TestCafe

    View Slide

  91. TestCafe
    App
    E2E
    PO
    E2E Test

    View Slide

  92. Summary of Our stack
    Language - Typescript
    View Layer - React/Preact
    Bundler/Compiler - Webpack
    Task runner/Package manager - yarn
    HTTP Client - facade over Axios
    State management - Redux + Redux
    Observable
    App scaffold/architecture - custom
    Router - React Router 4
    Forms - Redux Forms
    I18n / l10n - react-i18-next
    Date/time handling - date-fns
    Dependency Injection - custom
    Unit/Integration testing - Jest
    E2E testing - Testcafe

    View Slide

  93. What did
    we learn
    today ?
    React in Enterprise is a thing !
    Unidirectional data flow
    Event driven State management
    RxJs/Epics reactivity
    Service Layer / DI
    Component sandbox
    Smart/Dumb components

    View Slide

  94. YMMV
    It depends !

    View Slide

  95. View Slide

  96. Thank you !
    Martin Hochel
    @martin_hotell

    View Slide