Slide 1

Slide 1 text

Enterprise React Enterprise React Martin Hochel @martin_hotell

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

I like Backend Developers who switched to Front-End

Slide 4

Slide 4 text

GoF Design patterns

Slide 5

Slide 5 text

Been there. Done that

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Jabbva Script

Slide 9

Slide 9 text

Javascript

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

How do you Javascript?

Slide 12

Slide 12 text

Typescript

Slide 13

Slide 13 text

“ Typescript → JavaScript that scales

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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’

Slide 17

Slide 17 text

Vanilla JS Type checking

Slide 18

Slide 18 text

Building ui that scales

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Building UI Now - Web Apps / SPA - Data driven

Slide 21

Slide 21 text

Scalable App? Let’s use a framework!

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

React

Slide 24

Slide 24 text

“ React A JavaScript library for building user interfaces

Slide 25

Slide 25 text

UI fn() render props state

Slide 26

Slide 26 text

Components

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

WTF VDOM

Slide 30

Slide 30 text

Type safety

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Until you start to build something

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

How (we) to build Scalable Enterprise React Apps

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Task runner / package manager

Slide 37

Slide 37 text

Yarn

Slide 38

Slide 38 text

“ FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT.

Slide 39

Slide 39 text

yarn

Slide 40

Slide 40 text

yarn

Slide 41

Slide 41 text

Bundler

Slide 42

Slide 42 text

Webpack

Slide 43

Slide 43 text

webpack

Slide 44

Slide 44 text

Webpack Senior Developer Task Force

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

Moar Tooling

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

Releases

Slide 51

Slide 51 text

Architecture Challenges

Slide 52

Slide 52 text

1. How do we structure components ?

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

This scales just ok! Until it doesn’t

Slide 56

Slide 56 text

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 ?

Slide 57

Slide 57 text

Mocking ! Now you have 2 problems

Slide 58

Slide 58 text

DI

Slide 59

Slide 59 text

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)

Slide 60

Slide 60 text

React DI React context pattern HOC pattern IoC - InversifyJS

Slide 61

Slide 61 text

Done ?

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

Redux

Slide 66

Slide 66 text

Redux Store

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

4. How State management communicates with Service layer ?

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

Redux Observable

Slide 72

Slide 72 text

An Epic is the core primitive of redux-observable

Slide 73

Slide 73 text

Epic fn() Observable Observable Reducers

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

Sandbox pattern

Slide 80

Slide 80 text

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)

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

App

Slide 83

Slide 83 text

7. Unit testing

Slide 84

Slide 84 text

Jest

Slide 85

Slide 85 text

“ Jest → Delightful JavaScript Testing

Slide 86

Slide 86 text

Jest Snapshots

Slide 87

Slide 87 text

8. E2E Testing

Slide 88

Slide 88 text

TestCafe

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

TestCafe

Slide 91

Slide 91 text

TestCafe App E2E PO E2E Test

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

YMMV It depends !

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

Thank you ! Martin Hochel @martin_hotell