Slide 1

Slide 1 text

Evaluating a year working with React & Redux @kenneth_skovhus React and Redux Copenhagen April 19, 2016

Slide 2

Slide 2 text

Hi! Kenneth Skovhus Full stack software engineer at issuu React/Redux believer

Slide 3

Slide 3 text

issuu is like YouTube for publications

Slide 4

Slide 4 text

25+ million publications 100 million unique visitors/mo Founded in Copenhagen 2007 Offices in Copenhagen, Berlin, Palo Alto ~30 engineers in Copenhagen

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Why are all we here?

Slide 7

Slide 7 text

Building rich client-side web applications (in React/Redux)

Slide 8

Slide 8 text

React View library by Facebook providing a high level abstraction for rendering user interfaces and neat way to create components. V in MV* Flux Fancy term for front-end app architecture based on unidirectional data flow. Provides simple mental model of the application. Redux Becoming the de facto flux implementation.

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

HOT AIR?

Slide 11

Slide 11 text

Where did we come from?

Slide 12

Slide 12 text

Client side eras at issuu.com The golden Macromedia Flash days (2007) Vanilla JS + jQuery (2009) Frameworks! Ember 1.0.0-rc.* (2013) Libraries! Backbone MV* + Handlebars (2014)

Slide 13

Slide 13 text

And they all ended up looking like...

Slide 14

Slide 14 text

Presentation Tracking App flow bootstrapping Validation Data model management Data syncing + Handlebars templates and styling (both presentation)

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Why is building client side applications difficult? Unstable requirements Design and UX adjustments Unlimited number of valid solutions Front-end novelties at crazy pace JavaScript...

Slide 17

Slide 17 text

Why did we settle on React/Redux?

Slide 18

Slide 18 text

We believed in Declarative UIs Composable components Unidirectional data flow Libraries instead of frameworks

Slide 19

Slide 19 text

And if it works for Airbnb, BBC, Dropbox, Facebook, Instagram, Netflix, Paypal, Podio, Salesforce, Uber, Wordpress, Yahoo...

Slide 20

Slide 20 text

Where are we using React/Redux?

Slide 21

Slide 21 text

Document reader (high traffic/usage)

Slide 22

Slide 22 text

Publisher Landing Page (dashboard)

Slide 23

Slide 23 text

Publisher Tools (create, read, update, delete)

Slide 24

Slide 24 text

Embed widget (form heavy)

Slide 25

Slide 25 text

InDesign plugin

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

React/Redux findings & recommendations

Slide 28

Slide 28 text

Quick adaption of React ● Small slowdown for first project ● Fairly short learning curve ● Great documentation to get started ● People still enjoys the new paradigm & DX ● Designers feels at home in JSX

Slide 29

Slide 29 text

Process improvements ● Less stepping on each others toes ● Easier to parallelize work

Slide 30

Slide 30 text

Process improvements ● Less stepping on each others toes ● Easier to parallelize work ● We write more tests (trivial to unit test a component)

Slide 31

Slide 31 text

Process improvements ● Less stepping on each others toes ● Easier to parallelize work ● We write more tests (trivial to unit test a component) ● Refactoring rather easy (always write PropTypes)

Slide 32

Slide 32 text

Structuring your application ● Presentational Components (view) ○ Are only concerned with how things look ○ Pure function, no dependency on actions/store ● Containers (controller-views) ○ Provide data to components or other containers ○ Stateful, connects application to actions, store https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

Slide 33

Slide 33 text

Goodbye copy-paste markup

Slide 34

Slide 34 text

Hello UI Component library const Checkbox = require('ui/checkbox');

Slide 35

Slide 35 text

Hello UI Component library const Checkbox = require('ui/checkbox'); ● Abstracts away implementation details ● Easier upgrade path when changing UI Components

Slide 36

Slide 36 text

Playing well with other kids ● Revamping UI of older Backbone application ● We wanted to replace the Backbone/Handlebars view layer with React ● Keep complex old Backbone Models and Collections intact (if it ain’t broken…)

Slide 37

Slide 37 text

Playing well with other kids backboneCollection.on('sync', (models) => { store.dispatch(actionCreators.sync(models)); }); backboneCollection.on('destroy', (model) => { store.dispatch(actionCreators.destroy(model)); });

Slide 38

Slide 38 text

Cosmos (Component Playground) ● Work on presentational components in isolation ● Fixtures to bootstrap your initial state ● Document what state a component can be in ● Great developer experience for building components ● Improves workflow with designers (~ InVision) github.com/skidding/cosmos

Slide 39

Slide 39 text

github.com/skidding/cosmos

Slide 40

Slide 40 text

Idea: Using fixtures to test rendering Simply render all presentational components with their Playground fixtures.

Slide 41

Slide 41 text

// Find all presentational components const components = glob.sync('./components/**/*.@(js|jsx)'); // Find all fixtures for a given component by doing some more globbing const componentFixture = getFixturesForComponent(c); test('Renders component with fixture data', t => { const oldError = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString();

Slide 42

Slide 42 text

test('Renders component with fixture data', t => { const oldError = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString(); t.pass(`Rendering ${componentFixture.name} (${fixture.name})`); } catch (e) { t.fail(`Failed rendering ${componentFixture.name} (${fixture.name})`); } }); console.error = oldError; t.end(); });

Slide 43

Slide 43 text

test('Renders component with fixture data', t => { const oldError = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString(); t.pass(`Rendering ${componentFixture.name} (${fixture.name})`); } catch (e) { t.fail(`Failed rendering ${componentFixture.name} (${fixture.name})`); } }); console.error = oldError; t.end(); });

Slide 44

Slide 44 text

test('Renders component with fixture data', t => { const oldError = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString(); t.pass(`Rendering ${componentFixture.name} (${fixture.name})`); } catch (e) { t.fail(`Failed rendering ${componentFixture.name} (${fixture.name})`); } }); console.error = oldError; t.end(); });

Slide 45

Slide 45 text

Idea: Using fixtures to test rendering Simply render all presentational components with their Playground fixtures. ● Forces you to document/write fixtures ● Asserts no runtime errors or missing props for all meaningful states without much effort

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

All good?

Slide 48

Slide 48 text

Give a small boy a hammer, and he will find that everything he encounters needs pounding Law of the instrument

Slide 49

Slide 49 text

As a result of the great DX, developers thinks: “React is the hammer that makes all problems look like a nail” May lead to over-engineering

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Leaky Abstractions

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

What leaks? ● Virtual DOM abstraction ○ Unsupported node attributes (Object, SVG) ○ React 15 solves this ○ Will they keep up to date with new DOM features?

Slide 54

Slide 54 text

What leaks? ● Virtual DOM abstraction ○ Unsupported node attributes (Object, SVG) ○ React 15 solves this ○ Will they keep up to date with new DOM features? ● Animations still feels cumbersome ● Combined with Redux you lose Inversion of Control

Slide 55

Slide 55 text

Technology lockdown ● Can we migrate away from React/Redux?

Slide 56

Slide 56 text

Technology lockdown ● Can we migrate away from React/Redux? ● Do I believe in: ○ Declarative UIs ○ Composable components ○ Unidirectional data flow

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

Focus on the user and all else will follow Focus on the user and all else will follow

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

@kenneth_skovhus React and Redux Copenhagen April 19, 2016 Questions?

Slide 61

Slide 61 text

@kenneth_skovhus React and Redux Copenhagen April 19, 2016 Thanks